Main Contents

Web Services, SOAP, Domino, and Java 6

March 9, 2009

A while back I made a brief attempt to embark on a voyage of Web Services discovery via JAX-WS. The problem was simple enough: I had a Java program running on server A which had an object. I wanted to send that object to a Domino server running on machine B.

Domino has a nifty Web Services feature these days, so it took about 2 minutes to create the SOAP-based Web Service. I’m not exaggerating, it’s literally a two minute task. You just create a class with one or more methods that take arguments of whatever types are appropriate. Domino builds the WSDL and makes the whole thing accessible at a couple of standard URLs, handling authentication, session management, parsing, and everything else you don’t want to have to care about.

So, I had a Web Service. I thought that should have been the tough part; after all, Java is great for web programming, right? So I tried finding out how to access my Web Service from Java.

The standard API for Web Services clients is JAX-WS, which is included in Java 6. As usual, the JavaDoc is utterly useless unless you already know how to use the API, and the most useful thing on the project page is pointers to random web articles and blog postings written by other poor suckers who have worked out what the heck it does.

I eventually found out how you start developing a Java client program given some WSDL, and fed Domino’s WSDL to the wsimport program in the hope that it would generate a stub I could pull into Eclipse and annotate with a suitable @WebServiceRef.

Fat chance. The wsimport program churned away for a couple of seconds, and spat out an error: “error: rpc/encoded wsdls are not supported in JAXWS 2.0.”

It turns out that although Sun says JAX-WS is supposed to replace JAX-RPC as the way to do Web Services, it doesn’t actually support all the stuff the older API supports. In particular, it doesn’t support SOAP encoding or RPC encoding, even though Java still has full support for RPC, and even though the encodings still seem to be part of the SOAP standards.

So, you can get stuck with SOAP 1.1 and a legacy API; or you can retool all your Web Services to get rid of RPC and SOAP encoding; or you can do some horrible hackery which ruins the simplicity all this SOAP and WSDL stuff was supposed to give us in the first place.

There’s a workaround. Domino lets you change the encoding used for the SOAP messages. It doesn’t seem to be mentioned in any of the tutorials I can find, but in the penultimate tab of the Web Service property inspector there’s a drop-down list. Instead of RPC/encoded, you can use RPC/literal. Sun’s wsimport will then accept the Domino-generated WSDL and create a stub, and you can connect to the service via JAX-WS 2.x. The tricky bit is authentication, but even that is pretty simple. The whole thing ends up being about ten lines of code; the trick is knowing what those ten lines have to look like, as there seems to be a dearth of up-to-date sample code out there.

Imagine your remote Domino Web Service is called Foo, and you’re encapsulating everything in an object. It’ll look something like this:

public class WSInterface {

  private FooService service;
  private Foo foo;
  private BindingProvider binding;

  void setupConnection() {
    try {
      this.service = new FooService(new URL(SERVICE_URL), new QName("urn:DefaultNamespace", "FooService"));
    } catch (MalformedURLException e) {
      logger.severe("Malformed WSDL URL " + SERVICE_URL + " - cannot continue");
      System.exit(1);
    }
    this.foo = this.service.getDomino();
    this.binding = (BindingProvider) this.foo;
    this.context = this.binding.getRequestContext();
    this.context.put(BindingProvider.USERNAME_PROPERTY, USER_NAME);
    this.context.put(BindingProvider.PASSWORD_PROPERTY, PASSWORD);
  }
}

Once that’s done, you can access one of the functions of the Domino Web Service–call it bar(x,y)–by just calling it as a method on your Foo object:

this.foo.myfunction("Hello","world");

So my code was all working—until I discovered a big catch with SOAP.

If you change something in your Web Service API–even a change which should be invisible to clients, like removing an API call nobody is using–you need to regenerate the client code from the changed WSDL. Even if the actual logic is identical before and after, you still need to download the WSDL, regenerate Java stubs with wsimport, and recompile.

So that’s probably the last time I use SOAP, simple or not. From now on it’s REST all the way.

Filed under: Domino, Java | Comments (0)

Leave a comment

Login