« Help Needed: Web service is unable to create LotusScript object. | Main| A Modern Parable »

Simple Solution for Web service is unable to create LotusScript object.

QuickImage Category Show-n-Tell Thursday Technical

Wherein I present the solution to an R7 conundrum

After a flurry of Yellow Bleeder chats and phone calls following yesterdays post, the true issue, and it's solution, have become apparent.

The issue is An LotusScript Class cannot be directly surfaced through an R7 Web Service running on a server. The class can however, be surfaced when the web service is running on a client machine.

This subtle difference is an important one, in that it can sneak up on an unwary developer and bring his or her work to a grinding halt. The reason is fairly simple. When you create a Web Service, you must define the Port Type class for the Web Service. The Port Type class is used as the basis for the WSDL generated by the service. If the method signatures of the Port Type class are changed in any way, the WSDL must be re-generated in order to incorporate the change(s).

When a developer is working on a Notes / Domino Web Service, the developer is using the Notes Designer client. When testing the Web Service on the local machine, the Designer Client will automatically regenerate the WSDL for the Web Service.

When testing the Web Service on a server, this regeneration never occurs. Which means that the Web Service attempting to surface a Port Type class defined in a LotusScript library breaks, without throwing any internal errors (ouch). The only error information available is passed back to the invoking client (the code attempting to connect to the Web Service), and is similar to this:

Web service SimpleEcho is unable to create LotusScript object for SimpleEcho datatype in method ECHO

Luckily, the solution is ridiculously simple.

Use a wrapper class in your Web Service.

Set this wrapper class as the Port Type class for the Web Service, include the LotusScript class library (Use "my class library"), and you're good to go. The code below should help out:

LotusScript Script Library

Option Public
Option Explicit

Class
Bar
    Sub New ()
        Messagebox |Creating new instance of Bar |
    End Sub ' New

    Function Echo (source As String) As String
        Dim result As String

        result = |Echo: | & source
        Messagebox |Library BarClass | & result

        Echo = result
    End Function ' Echo
End Class 'Bar

LotusScript Web Service

Option Public
Option Explicit
Use
"BarClass"

Class Foo

    Private
myBar As Bar

    Sub New ()
        Messagebox
|Creating new instance of Foo |
        Set myBar = New Bar()
    End Sub ' New

    Function Echo (source As String) As String
        Dim result As String

        result = myBar.Echo(source)
        Messagebox
|Web Service Foo | & result

        Echo = result
    End Function ' Echo
End Class 'Foo

I've placed a sample nsf here: SimpleEcho.zip. (File is also available on my downloads page).


Important Note: This issue does not exist in R8.

IBM / Lotus put a huge amount of effort into R8, and Web Services in particular. Unless you have a compelling reason to stay on R7; if you are using Web Services, I strongly urge you to upgrade to R8.

Recommended Reading

* special thanks to the Yellow Bleeders community for helping out.

Hope this helps!

-Devin

Comments

Gravatar Image1 - Out of sheer morbid curiosity, would a derived class suffice? For example, if you just listed Class Foo As Bar and left it at that? Reason I ask is, if the method signatures of the base class changed, you'd have to generate a fresh WSDL anyway (even in 8). But the whole point of WSDL (and OOP itself, in some respects) is that the actual internals of the methods can change ad infinitum with no consumer impact as long as the method signatures (the API) remain unchanged.

Gravatar Image2 -

Very good question Tim. And the answer is yes, as long as the signature methods are explicitly defined within the Web Service code itself.
I've done some additional testing, and the following code sample should explain this (use this code instead of code in my post above):

LotusScript Web Service

Option Public
Option Explicit
Use
"BarClass"

Class Foo As Bar
    Sub New (), Bar() ' calls the parent's New() method, similar to New Bar()
    End Sub ' New

    Function Echo (source As String) As String
        Echo = Bar..Echo(source) ' double dot (..) notation calls method from base class, similar to Bar.Echo()
    End Function ' Echo
End Class 'Foo
-Devin

Gravatar Image3 - Just like when you asked the question, as soon as I read the blog entry, my eyes started to glaze over...

Man, I need a beer... and another one... and another one... (you get the idea)... Emoticon

Search

Wowsers! A Tag Cloud!

Links

MiscLinks