The UrlFetcher LotusScript Library (Tuesday, May 22)

Last week we talked about getting URLs in LotusScript, and Jan-Piet Mens asked about a more cross-platform approach (actually, he also made the same request on his own blog a few months ago). So, I recycled some old code and wrote some new, and J-P helped me test and debug it. As a result, here is a database with some Java and LS2J code that allows you to easily make cross-platform GET and POST requests from Java or LotusScript:

The UrlFetcher Java library is pretty well commented, and should answer most of your questions about how everything works. The UrlFetcherLS library in LotusScript is just an LS2J wrapper around the Java stuff, and it’s not nearly as well documented, but just read the comments in the Java class and you’ll figure it out.

There are also a few sample agents that show how some of the functionality works. For example:

Option Public
Option Declare
Use "UrlFetcherLS"

Sub Initialize
	Dim fetcher As New UrlFetcher
	Print fetcher.getUrlAsString("http://www.nsftools.com")
End Sub

That’s not too bad, is it? You can also get HTTP headers, set headers, add POST parameters, make proxy settings, and a few other things. I even have an example of making an SSL/HTTPS request, but that’s Notes 7 only. Everything else should work in both Notes 6 and 7.


[ permalink ] [ e-mail me ] [ read/add comments ]

GMail Spellcheck (Correction: It’s Firefox) (Monday, May 21)

CORRECTION: Okay, I’m a bonehead. It’s actually Firefox 2.0 doing the spellchecking, not Gmail. I finally updated from Firefox 1.5 on the machine I usually check mail on. I thought about deleting this blog entry and pretending I never wrote it, but then I figured I’d just leave my tattered laundry out for everyone to see. What the heck.


This is cool. There’s inline spellcheck in Gmail Firefox — using the familiar red dotted underline for unknown words and right-click to get suggestions:


GMail Spellcheck Screenshot

Then again, maybe it’s been there for a while (UPDATE: yes, it has…) and I’ve never noticed (UPDATE: stupid, stupid, stupid…). It works in Gmail chat too.


[ permalink ] [ e-mail me ] [ read/add comments ]

Article on Web Services in Domino 8 (Wednesday, May 16)

There’s a new Domino Web Services article on developerWorks today: Engineering WS-I compliant Web Services for IBM Lotus Domino V8.

Even if you’re not specifically interested in trying to make your Domino Web Services fully WS-I compliant, there are some great tips and gotchas in there, including:

  • Web Services created on Notes/Domino 8.0 will not work on Domino 7 (however, the D7 Web Services work just fine on D8).
  • Using arrays as method parameters in D7 only works when using the RPC/Encoded format (all formats work properly in D8). They do show a very interesting workaround using imported WSDL, though.
  • Another workaround is to use a custom class as a parameter, with an array as a public member of the custom class (see below). However, in D8 a custom class that has an array as its only member is treated as an array in the WSDL, not as a proper complex data type (there has to be at least one other public member variable).
  • Custom SOAP Fault subclasses are not returned properly in D7 (although they are in D8).
  • Remember to set the server to “Run web agents concurrently” (I always forget that this isn’t default behavior).

Regarding arrays as parameters using custom classes/complex data types, here’s how I like to set that up:

Class PhoneNumbers
    Public phoneNumberArray() As String
    Public count As Integer
End Class

Class DirectoryAssistance
    Public Function reverseLookup (nums As PhoneNumbers) As NameList
        ...
    End Function
End Class

I mention this type of setup in one of my web services articles. The nice thing about this structure is that it’s easy for the client to determine whether or not an array that is a return value is empty (count=0) or not — you can decide for yourself if you want to enforce proper “count” values on the server side when accepting the class as a parameter.

Luckily, it also seems to have the fortunate side-effect of making the arrays work properly as method parameters for WSDL formats other than RPC/Encoded. I need to do some more testing to confirm, but I don’t remember having problems before, and the new “WS-I Compliant Web Services” article seems to say that it’s true.


[ permalink ] [ e-mail me ] [ read/add comments ]

Native TNEF Decoding, Java Library Crashes (Monday, May 14)

Here are two [hopefully] unrelated interesting things I saw recently on the IBM Support site.

First, SPR #SBRN5PGPCN describes a fix for TNEF extraction on Domino. The really interesting thing is that it applies to Domino 7.0.2 and 6.5.6. So maybe native TNEF extraction is in the Domino 6.5.6 server too? That would be cool. I’m not sure if I saw that anywhere before or not.

Second, Technote #1202732 describes a scenario where Java JAR files that are attached to agents or script libraries can cause Out Of Memory errors. There’s an SPR associated with it, which would seem to indicate that it’s a problem that hasn’t been fixed yet. The solution is to detach the JAR file to the local file system and access it that way (either the JavaUserClasses INI setting or just plopping it in the JRE ext directory).

The wording of the technote (at the time I’m writing this — it may change) makes it a little unclear as to whether this affects code that run on servers, or just clients. It talks about a “Domino client” (?!?), and also mentions that if you access the library using JavaUserClasses then every time the JAR file changes “you must copy it to your local server” — and, um, I don’t think that a Notes client that has a JAR file listed in JavaUserClasses would look on a Domino server for a JAR file. But hey, maybe it does, and that’s one more thing I don’t know.


[ permalink ] [ e-mail me ] [ read/add comments ]

Debugging JavaScript in IE (Sunday, May 13)

Now, I know that the be-all-end-all of JavaScript debuggers these days is Firebug, but sometimes I have to use Internet Explorer for my testing (like intranet pages with VBScript or ActiveX controls). I’ve always used the old Microsoft Script Debugger for such things — which isn’t even in the same league as Firebug, but at least it allows you to step through code and change variables and execute expressions on the fly.

In the last week or so, I’ve seen links to two very interesting other ways of debugging JavaScript in IE:

So, new toys to try…

UPDATE: I got some great suggestions in the comments so far, including:


[ permalink ] [ e-mail me ] [ read/add comments ]

SnTT: Fetching URLs With LotusScript (Thursday, May 10)

Someone asked me how to fetch a URL using LotusScript today. It’s pretty easy, but if you need some code here’s an old test agent I dug up:

Sub Initialize '** this will give you the whole web page, not including the HTTP Headers, '** as raw HTML/XML text Dim XmlHttpRequest As Variant Dim response As String Set XmlHttpRequest = CreateObject("Microsoft.XMLHTTP") Call XmlHttpRequest.Open("GET", "http://www.google.com", False) Call XmlHttpRequest.Send() response = XmlHttpRequest.responseText '** this will give you the body of the web page, translated to NotesRichText '** (the HTTP headers are available as individual fields -- one for each header '** name -- on the document) Dim session As New NotesSession Dim db As NotesDatabase Dim doc As NotesDocument Dim pageBody As String Set db = session.CurrentDatabase Set doc = db.GetDocumentByURL("http://www.google.com", True) pageBody = doc.GetItemValue("Body")(0) Call doc.Remove(True) End Sub

If you run this on a server, make sure you have the “Runtime Security Level” set to at least “2”, since you’re doing network operations.

Also, the GetDocumentByURL method uses the Web Navigator database somehow (perweb.nsf on the client, or web.nsf plus the WEB service on a server), so make sure that’s all set up properly. That database can get kind of funky sometimes and cause problems, as John Roling can tell you. On the other hand, the XmlHttpRequest method only works on Windows, so choose your poison.

BONUS: Thomas Adrian has a good quick reference on his site too.

UPDATE: Markus Koller mentioned in the comments that ServerXmlHttp might be a better option than XmlHttp for this — and he linked to a very good Microsoft Knowledgebase article describing the difference between the two. Looks like ServerXmlHttp allows you to set up some proxy settings, which could be very handy. Thanks Markus!

technorati tag: ,


[ permalink ] [ e-mail me ] [ read/add comments ]

A Warren Of Rabbits (Wednesday, May 9)

We saw a couple of rabbits in the back yard the other day, and since there was more than one I told the kids that there are probably a whole bunch of them out in the woods somewhere — or will be soon, they being rabbits and all…

However, I knew that “bunch” wasn’t the correct word for a group of rabbits. I know that cows are in herds, birds are in flocks, and even that frogs are in armies. But I had no idea what the collective name for rabbits was.

Go Google, go! After one or two searches and a few clicked links, I found two excellent references:

The reference.com page is a little more complete, but the San Diego Zoo site has some great links with more information about the animals themselves. I think my favorites on the list were a plague of locusts, and a shiver of sharks. A parliament of owls and a scourge or mosquitoes were probably close seconds.

Oh, and rabbits come in “warrens” (there were a few other names, but that seemed the most common in other references).


[ permalink ] [ e-mail me ] [ read/add comments ]

A Dog Named Poop (Wednesday, May 2)

This weekend we got a dog. A puppy actually. From the Humane Society, so she’s nice and “rescued”. Here’s a picture:


Julian and the dog: feel the love

You can just feel the love right there, can’t you?

She’s actually a really good dog, except for the fact that she’s not quite housebroken yet. We’re still trying out different names on her. I’m currently leaning toward the name: “It Shits All Over The House” — that would be “Isaoth” for short, but it doesn’t have a good ring to it. We’ll see.


[ permalink ] [ e-mail me ] [ read/add comments ]

Drive Cancelled (Tuesday, May 1)

What better way to pull me out of an unofficial one month blogging break than for Fox Broadcasting to cancel my new favorite show: Drive.


Drive: the TV Show on Fox

Produced by Tim Minear (producer/co-writer of Firefly and Angel) and starring Nathan Fillion (star of Firefly), it was a show that Joss Whedon fans at least had to try — I tried it and liked it. A lot.

After only four episodes, it got pulled off the air. Rumor has it that it got poor ratings and it was also lowering ratings for ’24’.

However, that just doesn’t sound right to me. There are plenty of truly lousy shows that last WAY more than 4 episodes. And if it was a ratings issue for ’24’, they could have just moved it to another night. There’s got to be something else going on there. Here are my conspiracy theories:

  • Funding problems
  • Major personality problems, either within the show or between the show and Fox
  • Fox/Minear is trying to build up Firefly-like underground enthusiasm for the show, and it will be back in full force this summer

I’m pretty fond of the last theory, even if it’s kind of far-fetched. Firefly was hugely successful AFTER it got cancelled by Fox, and has sold a whole lot of DVD box sets. The success was largely a word-of-mouth and Internet grassroots effort. Fox will supposedly air the LAST two episodes of the show this summer, but I’m wondering if they might continue on where they left off if there’s enough “underground” interest — especially because there would be much less competition from other popular shows over the summer.

Maybe it’s just wishful thinking on my part too…

Oh, and if you missed the show, now’s a good time to watch the first 4 episodes. You can buy the episodes for $1.99 each at the official BitTorrent site, or I’ve heard that the torrents are also available for download on “other” servers. I’m not sure if a Google search for “drive fox torrent” would help there or not.


[ permalink ] [ e-mail me ] [ read/add comments ]

Adding OpenLog JavaScript Logging to a Lotus Notes Form (Thursday, Mar 22)

I was going to write up a nice long, detailed explanation of how to add the new OpenLog JavaScript logging to a Lotus Notes form, but I figured a Flash demo would be much better. So here you go (click the picture):


OpenLog JavaScript Flash Demo

Sorry for the big ol’ Flash file (@ 2.5 MB). Better than bullet points though. And besides, the text instructions are in the OpenLog database Help docs.


[ permalink ] [ e-mail me ] [ read/add comments ]

OpenLog 1.5 BETA Released (Wednesday, Mar 21)

Late tonight, I posted the OpenLog 1.5 BETA release. That’s the one with the JavaScript error handling for web pages, and RSS feeds for notification. More later, because I’m tired now.

Go play!


[ permalink ] [ e-mail me ] [ read/add comments ]

OpenLog Wednesday (Monday, Mar 19)

Okay, okay. I’m finally going to release version 1.6 of OpenLog on Wednesday. That’s the version that Rob McDonagh and I presented at Lotusphere, with the JavaScript logging library and the RSS feeds.

I have a feeling I’ll be releasing it with a “beta” moniker, although I haven’t completely decided yet. If nothing else, I finally worked my way around the cross-domain scripting issue that wouldn’t let it work if the Notes server that OpenLog was running on had a different hostname than the one that the web page was being served from (i.e. — if the page was on http://apache.nsftools.com and OpenLog was on http://domino.nsftools.com, the Ajax POST wouldn’t work).

The answer to the cross-domain POST problem? iFrames…


[ permalink ] [ e-mail me ] [ read/add comments ]

The Four Kinds of Blogs (Sunday, Mar 18)

Tom Haskins wrote an interesting blog entry about Different Motivations for Blogging. He puts blogs into four broad categories:

  • Distraction Blogs: relief, mood changing, escape
  • Archive Blogs: sharing expertise, solutions, advice
  • Conversation Blogs: contributing to collective wisdom
  • Democratic Blogs: changing community dynamics

Off the top of my head, that seems to almost cover it in broad strokes. However, I’m trying to figure out if I agree that those are general reasons for writing blogs or reading them. Seems to me that an additional category for writing a blog would be: self-ego gratification. Tom Haskins files that under “Distraction”, but I think it might be a category unto itself (not that it matters, really).

via Roger von Oech at Creative Think


[ permalink ] [ e-mail me ] [ read/add comments ]

Peachtree Road Race Registration This Weekend (Saturday, Mar 17)

If you’re in or near the Atlanta area and you want to run in the Peachtree Road Race this year, make sure you buy an Atlanta Sunday paper this weekend. This is the weekend that the registration forms are in the newspaper. If you don’t fill out the form and mail it by Monday (maybe Tuesday), you probably won’t get a number.

The form says that photocopies are acceptable as valid registrations. That could potentially mean scanned copies of the form that are printed from your computer and filled out… I’m just saying…


[ permalink ] [ e-mail me ] [ read/add comments ]

Sparta: Super Or Not? (Monday, Mar 12)

I went to see the movie 300 this past weekend and it was enjoyable. Pretty much what I expected after seeing the previews: it looked just like a movie version of a Frank Miller graphic novel. In a good way, of course.

Since I know essentially nothing about “real” ancient history, I decided to check out the Wikipedia entry on Sparta to get an overview and I noticed that it was locked and under dispute:


Disputed Wikipedia message on the Sparta entry

Hmm, what’s that all about? So I clicked through to the Talk:Sparta page and man o’ man, what a grand Edit War they’ve got going on there. It’s absolutely hilarious to a disinterested outsider like me. At this point in time (here’s the permalink to a version of the page from today, in case it goes away or gets drastically changed) the big dispute is over whether Sparta should have been called a “superpower” or not, although there seems to be a lot of personality clash going on to fuel the fire.

If you’ve got a whole lot of time (more time than me, because I just did a healthy skim of the page), there’s a world of entertainment buried in that discussion. To an oddball sense of humor like mine, anyway. Start at the Sparta as a World Power section about 1/4 of the way down the page and keep on reading.

It’s also interesting to see how disputes like this get resolved in an open forum like Wikipedia. On the one hand, there’s the idealist mindset of Do Not Feed The Trolls (DNFT), hoping that trollish behavior will eventually just go away. On the other hand, this sort of thing can end up being a huge timesink for the people who are the real caretakers in such a situation, and it’s not necessarily clear whether there’s true trolling going on here or not. It might just be an honest-to-goodness (and very harsh) disagreement.


[ permalink ] [ e-mail me ] [ read/add comments ]

Web Service Consumer in Notes 8 (Sunday, Mar 11)

I haven’t had any time to play with the Notes 8 beta client yet, but I was reading through the Reviewer’s Guide and saw this part on web service consumers in Notes 8:


Lotus Notes and Domino 8 add Web services consumer support, allowing you to call Web services hosted elsewhere. A Web services consumer does not use a Web service design element, because these are used only for publishing Web services. Instead, a Web services consumer uses a special kind of script library (either LotusScript or Java). To call the Web service, an agent or other code must “use” that script library.

In the examples they have, it looks like you just:

  • Import the WSDL of the web service you want to call into a Java or LotusScript Script Library
  • The “stub” code for calling the web service will be generated for you as a class
  • You can then call the class methods from anywhere you can include the script library — agents, actions, etc.

So your call to a web service that gets a stock quote might look like this:

Use "StockQuote WebService Library"

Sub Click (Source As Button)
    Dim q As New StockQuoteClass()
    Messagebox "Current IBM stock price is: " & q.GetQuote("IBM")
End Sub

Looks nice and easy. I can’t wait to try it out.


[ permalink ] [ e-mail me ] [ read/add comments ]

Dell IdeaStorm and the Linux Problem (Thursday, Mar 8)

Crisis = Danger + Opportunity

In yesterday’s blog entry I mentioned that the Linux crowd had kind of taken over the Dell IdeaStorm site. Stephen Hood left a comment that:

Dell would have been better off not doing this if they aren’t going to listen. Their excuse about having to pick one Linux distro… just damages their credibility further — the opposite goal of this initiative… And then to just ignore the #2 request of installing openoffice was even worse.

So, does that make this a failed opportunity? Does that make IdeaStorm a bad idea, unless Dell chooses to follow all of the top requests on the list? (EDITOR’S NOTE: I know that’s not exactly what Stephen was saying in his comment, but I’m making a point here)

No, absolutely not. This gives Dell an opportunity, and as I said in my previous post: don’t fight the users, adapt the system. Here are some of the things that Dell can do in this situation:

  • Clarify their marketing message (especially regarding Desktop Linux and OpenOffice)
  • Post some of their own ideas (on this or another medium) about business-saavy things they can do in response to this demand
  • Restructure the IdeaStorm site to bring the categories or the newest ideas more front-and-center, so that a single special-interest group can’t take over the voting (because people are only going to vote for what’s in front of them, and right now what’s in front of them on the home page is the ideas with the top votes). At the very least, add a Linux category…
  • Add a blog to publicly react to some of the “hot” ideas

If the site remains stale, it will fail (sorry for the rhyme there). Any site that allows that much user interaction will be used in unexpected ways, and if it doesn’t grow and adapt it will become useless.

That’s another lesson to learn when implementing all this social software stuff, I suppose: half the problem is getting people to use it, the other half is making sure it can evolve when people DO start using it. Evolve or die, and all that.


[ permalink ] [ e-mail me ] [ read/add comments ]

Corporate Social Software Examples (Wednesday, Mar 7)

Here are a few interesting examples of “corporate” social software usage:

The Wikipatterns site has some good links on its Resources page too.


[ permalink ] [ e-mail me ] [ read/add comments ]

Setting SOAP Headers Using Stubby (Monday, Mar 5)

DANGER: The programming geekery below may cause drowsiness. Please do not read while operating heavy machinery. Thank you.

I got a question last week about setting SOAP Headers when making web service calls from Lotus Notes using Stubby: the Web Services Slayer (a.k.a. — the Lotus Notes Axis Stub Generator). I figured I should go ahead and document it here, if for no other reason than the fact that I can link back to it from the OpenNTF project site.

A typical SOAP envelope looks something like this:

<SOAP-ENV:Envelope  
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:GetStockInfo xmlns:ns1="urn:thisNamespace">
      <ns1:symbol>FOO</ns1:symbol>
    </ns1:GetStockInfo>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

If you use Stubby to generate the Axis client code for you to use in Lotus Notes, this SOAP envelope will be generated by code similar to the following:

import StockInfoNamespace.*;

StockInfoServiceLocator locator = new StockInfoServiceLocator();
StockInfoService service = locator.getDomino();
service.GetStockInfo("FOO"); 

Sometimes a web service will also require you to include SOAP Header information, usually for login purposes. In the case of explicit headers (that are defined in the WSDL), the SOAP Header information is supposed to be writable directly from the Axis client code. However, if the headers are implicit (not defined in the WSDL), you will have to generate them manually.

There are two kinds of header elements you may have to generate. The first are elements that are simply child nodes of the <Header> element, like so:

<SOAP-ENV:Envelope  
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Header>
    <ns1:UserName xmlns:ns1="urn:thisNamespace">
      John Doe
    </ns1:UserName>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <ns2:GetStockInfo xmlns:ns2="urn:thisNamespace">
      <ns2:symbol>FOO</ns2:symbol>
    </ns2:GetStockInfo>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

This type of envelope can be created with Stubby code similar to this:

import StockInfoNamespace.*;
import lotus.domino.axis.client.Stub;

StockInfoServiceLocator locator = new StockInfoServiceLocator();
StockInfoService service = locator.getDomino();
((Stub) service).setHeader(
    "urn:thisNamespace", "UserName", "John Doe");
service.GetStockInfo("FOO"); 

You can also end up with header elements that are nested, such that there are nodes with subnodes within the <Header> element, like so:

<SOAP-ENV:Envelope  
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Header>
    <ns1:AuthenticationInfo xmlns:ns1="urn:thisNamespace">
      <ns1:UserName>John Doe</ns1:UserName>
    </ns1:AuthenticationInfo>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <ns2:GetStockInfo xmlns:ns2="urn:thisNamespace">
      <ns2:symbol>FOO</ns2:symbol>
    </ns2:GetStockInfo>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

In this case, the <UserName> node is within an <AuthenticationInfo> node within the SOAP Header. This type of envelope can be created with Stubby code similar to this:

import StockInfoNamespace.*;
import lotus.domino.axis.client.Stub;
import lotus.domino.axis.message.SOAPHeaderElement;
import javax.xml.soap.SOAPElement;

StockInfoServiceLocator locator = new StockInfoServiceLocator();
StockInfoService service = locator.getDomino();
SOAPHeaderElement headerElement = new SOAPHeaderElement(
    "urn:thisNamespace", "AuthenticationInfo");
SOAPElement node = headerElement.addChildElement("UserName");
node.addTextNode("John Doe");
((Stub) service).setHeader(headerElement);
service.GetStockInfo("FOO"); 

Note that we’re talking about SOAP Envelope Headers here, not HTTP headers. You can set HTTP headers too if you’d like. The normal reason is to set a session cookie or to use basic authentication. Here is some sample code for that situation:

import StockInfoNamespace.*;
import lotus.domino.axis.transport.http.HTTPConstants;
import lotus.domino.axis.client.Call;

StockInfoServiceLocator locator = new StockInfoServiceLocator();
StockInfoService service = locator.getDomino();
// to set a cookie:
service._setProperty(
    HTTPConstants.HEADER_COOKIE, "AuthToken=abc123");
// to use Basic HTTP Authentication:
service._setProperty(
    Call.USERNAME_PROPERTY, "user name");
service._setProperty(
    Call.PASSWORD_PROPERTY, "password");
service.GetStockInfo("FOO"); 

Speaking of HTTP headers, if a SOAPAction Header was specified in the WSDL file, it will be generated automatically by the client code. No need to worry about that.


[ permalink ] [ e-mail me ] [ read/add comments ]

Irreparable Damage To My Laptop Battery (Saturday, Mar 3)

I’ve noticed for the past few months that my laptop battery doesn’t hold nearly as much charge as it used to. I can only get about an hour of use (or less) out of it anymore.

The Thinkpad Power Manager has a battery maintenance utility that performs a “Reset” on the battery — charging it fully and then discharging it fully — that’s supposed to help, but it wasn’t helping.

Yesterday I noticed that my battery light was flashing amber even though I was plugged in. I checked the Power Manager display, and it told me this:


Damaged Battery Indicator

Yikes! Irreparable damage? That can’t be good…

Although there have been a couple of Lenovo battery recalls recently, mine wasn’t one of them.

Thank goodness for my awesome Thinkpad maintenance plan though. The battery is still under warranty, and all I had to do was tell them what was going on and they said they’d ship out a new one as soon as it’s in stock at the warehouse. No weird diagnostic programs to run, and no dropping off my laptop at a service center and having to wait for someone to assess the problem — just a new battery and that’s that.

That’s the kind of service I was hoping to get when I paid a little extra for the Thinkpad brand in the first place.


[ permalink ] [ e-mail me ] [ read/add comments ]