"java.lang.UnsatisfiedLinkError: Native Library C:\test.dll already loaded in another classloader" can happen in Lotus Notes/Domino when Java agents or libraries use native calls to Windows DLL files.
What was strange about this error is that the same Java scriptlibrary worked fine in Java agent, but not in LS2J LotusScript agent.
I guess the error happens because the JAR file (the one which calls the DLL) is automatically detached at run-time and gets a new filename each time, which confuses JVM. With pure Java agents this behaviour might be different and the error does not occur.
Anyway, here is the solution:
Instead of including JAR files directly into the Java agent/scriptlibrary, put them into Notes's classpath.
Tuesday, June 20, 2006
Monday, June 19, 2006
Jumping with a parachute
I was watching "Rocky & Drago" documentary today on TV6. One of the missions the 2 actors got was a tandem jump with a parachute from 4000 meters height.
I did a tandem jump for 1 year ago so I want to share my experience of skydiving :)
Many people think that they are going to be afraid of the height, specially in the moment when they jump out. This is partially true, but shouldn't bother 97% of the people. Here is what happens: When you jumped out of the plane, you can see that the ground is very far away and it's going to get a loooong while to get there. This is rather calming. And actually you do not notice that you move towards the ground because the height is too high to be able to estimate the distance to the ground and speed of the fall. So you will not see a big difference if you are at 4000 meters or at 1000 meters. At 800-1000 meters you can begin suspecting that you are getting closer to the ground. At this moment the parachute opens. You understand that you are still falling, but now you can estimate the speed of the fall and you see that the speed is not dangerous.
The only thing I worried about was that I totally depended on the instructor who was strapped with me on my back. I mean maybe he was very upset over something today and decided to take his last jump. The other thing I worried about was that when the parachute opens, the sudden pull upwards can cause the strapping between me and instructor to burst. But nothing of this happened, otherwise you won't read this post :)
BUT.. I have a warning to you: if your ears hurt when you fly airplane (because of air pressure changes), consult with the instructor before deciding to jump, and get ear-plugs. I got a terrible ear-ache during the jump, which ruined this fantastic experience. I guess in some cases it can lead to serious injuries.
You can also get a slight head ache because of the turbulence.
I did a tandem jump for 1 year ago so I want to share my experience of skydiving :)
Many people think that they are going to be afraid of the height, specially in the moment when they jump out. This is partially true, but shouldn't bother 97% of the people. Here is what happens: When you jumped out of the plane, you can see that the ground is very far away and it's going to get a loooong while to get there. This is rather calming. And actually you do not notice that you move towards the ground because the height is too high to be able to estimate the distance to the ground and speed of the fall. So you will not see a big difference if you are at 4000 meters or at 1000 meters. At 800-1000 meters you can begin suspecting that you are getting closer to the ground. At this moment the parachute opens. You understand that you are still falling, but now you can estimate the speed of the fall and you see that the speed is not dangerous.
The only thing I worried about was that I totally depended on the instructor who was strapped with me on my back. I mean maybe he was very upset over something today and decided to take his last jump. The other thing I worried about was that when the parachute opens, the sudden pull upwards can cause the strapping between me and instructor to burst. But nothing of this happened, otherwise you won't read this post :)
BUT.. I have a warning to you: if your ears hurt when you fly airplane (because of air pressure changes), consult with the instructor before deciding to jump, and get ear-plugs. I got a terrible ear-ache during the jump, which ruined this fantastic experience. I guess in some cases it can lead to serious injuries.
You can also get a slight head ache because of the turbulence.
Wednesday, June 14, 2006
Can you crack Da Andrei code?
Monday, June 12, 2006
Make incorrectly populated fields blink on web
This tip shows how to make fields with incorrect values to blink with blue and red colors. The correctness of a field is verified against field's expected value.
click image to view in full size
Formula for the first computed field: @If(Field1="This field has correct value";"color:black";"color:blue; font-weight: bold")
Formula for the second computed field: @If(Field2="This field has correct value";"color:black";"color:blue; font-weight: bold")
Code on Form (remove space in tags):
< div id="field1" style="< Computed Value >">FIELD1< /div >
< div id="field2" style="< Computed Value >">FIELD2< /div >
< div id="field3" style="< Computed Value >">FIELD3< /div >
< script >
checkfield('field1');
checkfield('field2');
checkfield('field3');
< /script >
Code in JSHeader:
function blinkme(fldid) {
var fld=document.all[fldid];
if (fld.style.color=="red"){
fld.style.color="blue";
}else{
fld.style.color="red";
}
mytime=setTimeout("blinkme('"+fldid+"')",800);
}
function checkfield(fldid){
var fld=document.all[fldid];
if(fld.style.color=="blue"){
mytime=setTimeout("blinkme('"+fldid+"')",800);
}
}
click image to view in full size
Formula for the first computed field: @If(Field1="This field has correct value";"color:black";"color:blue; font-weight: bold")
Formula for the second computed field: @If(Field2="This field has correct value";"color:black";"color:blue; font-weight: bold")
Code on Form (remove space in tags):
< div id="field1" style="< Computed Value >">FIELD1< /div >
< div id="field2" style="< Computed Value >">FIELD2< /div >
< div id="field3" style="< Computed Value >">FIELD3< /div >
< script >
checkfield('field1');
checkfield('field2');
checkfield('field3');
< /script >
Code in JSHeader:
function blinkme(fldid) {
var fld=document.all[fldid];
if (fld.style.color=="red"){
fld.style.color="blue";
}else{
fld.style.color="red";
}
mytime=setTimeout("blinkme('"+fldid+"')",800);
}
function checkfield(fldid){
var fld=document.all[fldid];
if(fld.style.color=="blue"){
mytime=setTimeout("blinkme('"+fldid+"')",800);
}
}
Sunday, June 11, 2006
Validating numeric fields in Javascript
Unless you use "Punctuated at thousands" field property of number fields, you can use following:
isnumeric=parseFloat(tmp)==(tmp*1)
But if you must have "Punctuated at thousands" property, the above code will not work properly.
For example, 20 000,00 is not the same as 20000,00.
The "space" character in the number is not a regular space, but a special separator. It's ASCII code is 160. This special character makes the validation code above work incorrectly.
Here is how you can validate such field without changing it's properties:
Code to put in onBlur event of the field:
isNumber(this, "Product Price"); // pass field handle and field title
Code to put on Form or in JSHeader:
< script >
function isNumber(obj, title){
if(typeof obj=="undefined" || obj.value.length==0){
return true;
}
tmp="";i=0;
sText=obj.value.replace(".", ","); //replace dot to comma, which is decimal separator
for(i=0; i <= sText.length; i++){
if(sText.charAt(i).length!=0){
if(sText.charCodeAt(i)!=160 && sText.charCodeAt(i)!=32){ // remove thousands space and regular space
tmp=tmp+sText.substring(i,i+1);
}
}
}
obj.value=tmp;
tmp=tmp.replace(",", ".").replace(" ", ""); //replace dot to comma and remove space
res=(parseFloat(tmp)==(tmp*1));
if(res==false){
alert(title+" field must be numeric!");
obj.focus();
};
return res;
}
< /script >
isnumeric=parseFloat(tmp)==(tmp*1)
But if you must have "Punctuated at thousands" property, the above code will not work properly.
For example, 20 000,00 is not the same as 20000,00.
The "space" character in the number is not a regular space, but a special separator. It's ASCII code is 160. This special character makes the validation code above work incorrectly.
Here is how you can validate such field without changing it's properties:
Code to put in onBlur event of the field:
isNumber(this, "Product Price"); // pass field handle and field title
Code to put on Form or in JSHeader:
< script >
function isNumber(obj, title){
if(typeof obj=="undefined" || obj.value.length==0){
return true;
}
tmp="";i=0;
sText=obj.value.replace(".", ","); //replace dot to comma, which is decimal separator
for(i=0; i <= sText.length; i++){
if(sText.charAt(i).length!=0){
if(sText.charCodeAt(i)!=160 && sText.charCodeAt(i)!=32){ // remove thousands space and regular space
tmp=tmp+sText.substring(i,i+1);
}
}
}
obj.value=tmp;
tmp=tmp.replace(",", ".").replace(" ", ""); //replace dot to comma and remove space
res=(parseFloat(tmp)==(tmp*1));
if(res==false){
alert(title+" field must be numeric!");
obj.focus();
};
return res;
}
< /script >
Friday, June 09, 2006
Blogging by phone
When you absolutely MUST create a blog post but has NO access to Internet, there is a solution! You can make a phone call and leave a message which gets posted to your blog!
Blogger.com is a partner with Audioblogger.com. Audioblogger.com allows to save voice messages as blog posts in Blogger.com. They are saved as MP3 files. To access audioblogger, login to your Blogger account and on the "Edit Profile" page click "audio clips" link. You will get a phone number in USA which you can call and leave a voice message. This message will be posted to your ordinary Blogger blog.
Not sure if this audio blog post is compatible with podcasting software.
Next time I will test bloggin from email and from a mobile device. Looks like text and photos can be posted from cell phones to Blogger.
Steps to post a voice message to Blogger:
1. Call the number
(Listen very carefully to the Voice Prompts)
2. Enter your Primary Number
3. Enter your PIN, press #
4. Record your post, Press #
5. Press 1 to post, 2 to review, 3 to re-record.
Blogger.com is a partner with Audioblogger.com. Audioblogger.com allows to save voice messages as blog posts in Blogger.com. They are saved as MP3 files. To access audioblogger, login to your Blogger account and on the "Edit Profile" page click "audio clips" link. You will get a phone number in USA which you can call and leave a voice message. This message will be posted to your ordinary Blogger blog.
Not sure if this audio blog post is compatible with podcasting software.
Next time I will test bloggin from email and from a mobile device. Looks like text and photos can be posted from cell phones to Blogger.
Steps to post a voice message to Blogger:
1. Call the number
(Listen very carefully to the Voice Prompts)
2. Enter your Primary Number
3. Enter your PIN, press #
4. Record your post, Press #
5. Press 1 to post, 2 to review, 3 to re-record.
Thursday, June 08, 2006
Create web charts from LotusScript agents. An easy way. And cool.
Thomas Adrian in his blog shows how to create a web-based chart without using any image files, by simply printing out DHTML from the agent.
Creating charts has never been easier before!
http://notessidan.se/A55B53/blogg.nsf/plink/TADN-6QET46
Creating charts has never been easier before!
http://notessidan.se/A55B53/blogg.nsf/plink/TADN-6QET46
Old pictures from Lotus Evolution seminar
Just found a webpage I've created for 4-6 months ago with pictures from Lotus Evolution seminar in Stockholm.
YOu can see the pictures and 2 videos here:
http://www.dominokonsult.se/lotusevolution.html
YOu can see the pictures and 2 videos here:
http://www.dominokonsult.se/lotusevolution.html
Wednesday, June 07, 2006
Run two instances of Skype
Originally posted here.
Same tip can be used to start multiple instances of other programs.
Same tip can be used to start multiple instances of other programs.
The only way to run 2 instances of Skype presently is:
On a Windows OS you can run another Skype instance at the same time if you start the second with another Windows user account. Example
1. Make sure you have another user account (login) for your Windows.
2. Right click the Skype icon and select "Run as..."
3. On the next screen click "The following user:" and select one different from the one you are currently logged in as on your computer.
4. Voila - another Skype opening which can be used independently from your first Skype instance. You can even make calls between them on the same computer
Additional tip from JP White.
To help automate the 'run as' trick you can create a second desktop icon for Skype and modify its properties. Click the advanced button and check the box 'run with different credentials'. After clicking on the modified icon it will ask you to sign in as another user. Changing the icon graphic also helps ensures you click on the correct icon.
Tuesday, June 06, 2006
Scan papers directly from Lotus Notes code
Dmitrij Vojtushin in his blog shares LotusScript code to scan papers and attach the scanned picture to a Notes document. Looks like it works in both UI and background code.
Here is a short example:
Sub Initialize
' Scan paper page to clipboard and then paste to Body
Call TWAIN_AcquireToClipboard(0,0)
Dim workspace As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = workspace.CurrentDocument
Call uidoc.GotoField( "Body" )
Call uidoc.Paste
End Sub
http://my.opera.com/LotusDomiNotes/blog/show.dml/144710
Here is a short example:
Sub Initialize
' Scan paper page to clipboard and then paste to Body
Call TWAIN_AcquireToClipboard(0,0)
Dim workspace As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = workspace.CurrentDocument
Call uidoc.GotoField( "Body" )
Call uidoc.Paste
End Sub
http://my.opera.com/LotusDomiNotes/blog/show.dml/144710
IBM DeveloperWorks article about AJAX
In "Using AJAX to manipulate Lotus Notes documents" article written by Joachim Dagerot you can see how to use AJAX in Domino databases. Included example shows how to update To-Do list in a Domino database using an agent. The agent receives data through a HTTP request and performs the requested action on a document. The document is found in the database by it's ID.
http://www-128.ibm.com/developerworks/lotus/library/domino-ajax/
http://www-128.ibm.com/developerworks/lotus/library/domino-ajax/
Sunday, June 04, 2006
Sleep function in LotusScript
If you want to pause script execution in LotusScript, yuo can use Sleep function. You might want to do it if you need to wait until external operation completes.
Syntax:
Sleep n
Where n is a number of seconds.
If you want to pause for less than 1 second, use following:
Sleep 0.2 ' pause for 200ms
Another good function to use in conjunction with Sleep is DoEvents. Using DoEvents in code allows you to stop looping code with Ctrl+Break keyboard command. Without it Notes client is often not responsible to break command.
Documentation says that Doevents and Yield functions are same, but in my experience DoEvents works much better... at least in older versions of Notes.
Call MyObject.SendExternalMessageDLL("message")
While Not MyObject.Status=2
sleep 0.1
DoEvents
Wend
Syntax:
Sleep n
Where n is a number of seconds.
If you want to pause for less than 1 second, use following:
Sleep 0.2 ' pause for 200ms
Another good function to use in conjunction with Sleep is DoEvents. Using DoEvents in code allows you to stop looping code with Ctrl+Break keyboard command. Without it Notes client is often not responsible to break command.
Documentation says that Doevents and Yield functions are same, but in my experience DoEvents works much better... at least in older versions of Notes.
Call MyObject.SendExternalMessageDLL("message")
While Not MyObject.Status=2
sleep 0.1
DoEvents
Wend
POST data to Domino agent using AJAX
Many people on Domino forums ask about getting data from LotusScript agent without refreshing the page, as if it was a pure javascript function call. It is possible with AJAX, here is an example and a live demo.
This example sends text located in a DIV tag on a web page to a LotusScript agent and updates the DIV element with response data received back from the agent.
Live example
Sub Initialize
< script >
var http_request = false;
function makePOSTRequest(url, parameters) {
http_request = false;
if (window.XMLHttpRequest) { // Mozilla
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = GetResponse;
http_request.open('POST', url, true);
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Content-length", parameters.length);
http_request.setRequestHeader("Connection", "close");
http_request.send(parameters);
}
function GetResponse() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
result = http_request.responseText;
document.getElementById('test').innerHTML = result;
} else {
alert('There was a problem with the request.');
}
}
}
function GetAgentData(txtdata) {
var poststr = txtdata; //encodeURI(txtdata);
makePOSTRequest('/test.nsf/postagent?openagent', poststr);
}
< /script >
-------------- LOTUSSCRIPT AGENT ---------------------
Sub Initialize
Dim session As New NotesSession
Dim doc As NotesDocument
Set doc=session.DocumentContext
req=doc.Request_Content(0)
For x=Len(req) To 1 Step -1
tmp=tmp+Mid(req,x,1)
Next
Print tmp
End Sub
This example sends text located in a DIV tag on a web page to a LotusScript agent and updates the DIV element with response data received back from the agent.
Live example
Sub Initialize
< script >
var http_request = false;
function makePOSTRequest(url, parameters) {
http_request = false;
if (window.XMLHttpRequest) { // Mozilla
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = GetResponse;
http_request.open('POST', url, true);
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Content-length", parameters.length);
http_request.setRequestHeader("Connection", "close");
http_request.send(parameters);
}
function GetResponse() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
result = http_request.responseText;
document.getElementById('test').innerHTML = result;
} else {
alert('There was a problem with the request.');
}
}
}
function GetAgentData(txtdata) {
var poststr = txtdata; //encodeURI(txtdata);
makePOSTRequest('/test.nsf/postagent?openagent', poststr);
}
< /script >
-------------- LOTUSSCRIPT AGENT ---------------------
Sub Initialize
Dim session As New NotesSession
Dim doc As NotesDocument
Set doc=session.DocumentContext
req=doc.Request_Content(0)
For x=Len(req) To 1 Step -1
tmp=tmp+Mid(req,x,1)
Next
Print tmp
End Sub
Funny story
The local bar was so sure that its bartender was the strongest man around that they offered a standing $1,000 bet. The bartender would squeeze a lemon until all the juice ran into a glass, and hand the lemon to a patron. Anyone who could squeeze one more drop of juice out would win the money.
Many people had tried over time (weightlifters, longshoremen, etc.) but nobody could do it. One day this scrawny little man came into the bar, wearing thick glasses and a polyester suit, and said in a tiny squeaky voice “I’d like to try the bet.”
After the laughter had died down, the bartender said OK, grabbed a lemon, and squeezed away. Then he handed the wrinkled remains of the rind to the little man. But the crowd’s laughter turned to total silence as the man clenched his fist around the lemon and six drops fell into the glass.
As the crowd cheered, the bartender paid the $1,000 and asked the little man, “What do you do for a living? Are you a lumberjack, a weightlifter, what?”
The man replied, "I work for the IRS."
Many people had tried over time (weightlifters, longshoremen, etc.) but nobody could do it. One day this scrawny little man came into the bar, wearing thick glasses and a polyester suit, and said in a tiny squeaky voice “I’d like to try the bet.”
After the laughter had died down, the bartender said OK, grabbed a lemon, and squeezed away. Then he handed the wrinkled remains of the rind to the little man. But the crowd’s laughter turned to total silence as the man clenched his fist around the lemon and six drops fell into the glass.
As the crowd cheered, the bartender paid the $1,000 and asked the little man, “What do you do for a living? Are you a lumberjack, a weightlifter, what?”
The man replied, "I work for the IRS."
Subscribe to:
Posts (Atom)