Creating a java webservice client in Domino using Apache CXF

My client wanted me to develop a webservice consumer that sends it requests to a Documentum webservice.  I had some previous experiences with LotusScript webservice classes generated by Domino automatically, but this turned out to be a non-solution, because I had to access the SOAP header.  I had to enter the Scary Java World for a proper alternative… It became quite a queeste!

scary java

Java solutions I tried and what went wrong (in a nutshell)

Why use CXF?

The short answer: once you get it to work, it’s easier (even for Java virgins), has more possibilities and is up-to-date.  The long answer can be found in Stephan’s interesting post.

Although Stephan’s article was of very great help, for the absolute beginner (me) it lacks some building steps. That’s why I decided to write out my own struggling.

Domino CXF step-by-step

What you need
  1. The latest binary distribution of CXF
  2. Eclipse IDE for Java EE Developers
  3. Java JDK or JRE 6 or higher

Unzip/install them!

Create the CXF Java classes from a WSDL with wsdl2java
  1. Save the wsdl you want to use locally.  For ease of use, copy it to your CXF install directory in the subdirectory bin.
  2. From the command prompt, “cd” yourself to subdirectory bin in your CXF install directory.
  3. Type
    wsdl2java -client -d targetdirectory -exsh true sourcewsdlpathandfilename.wsdl
    dos
    • -client creates an example class that can be a good starting point for your java (agent) code.
    • -exsh true is only needed if you want access to the SOAP headers (f.e. to provide a username/password to the service).
    • If you omit -d targetdirectory the classes are generated directly in the same (bin) folder.
    • If the program throws errors: maybe your %JAVA_HOME% needs to be set:
      • You can test this with echo %JAVA_HOME% at the command prompt.  It should return the directory where you installed the Java JDK/JRE.
      • If it doesn’t, enter SET JAVA_HOME=path-to-SDK at the command prompt.
Create the code in Eclipse (if I can make it there, I’ll make it anywhere)
  1. Create a new Java project (File – New Project – Java Project) and give the child a name.
  2. In Windows – Preferences – Java – Installed JREs add the dominodir\lib\etc directory as standard VM and make it the default. It means you’ll use the Domino Java VM, so you can be sure you don’t use stuff different from the Notes Java distribution.
  3. Choose Project – Properties – Libraries – Add External JARs and add all jar’s from the CXF lib subdirectory.  That way we can use the CXF classes in our project.
  4. We can easily add the CXF classes generated from our wsdl by drag the root folder from the generated classes in the previous chapter, to our Eclipse project:
    eclipse
  5. You should find the example client class in your Eclipse project folder in the subdirectory you just dragged to the project in 4. The classname looks like xxx_Client.java.
  6. Open the class.
  7. In the generated example client the wsdl location is handled differently.  For now, do it like this:
    clientclass
    There are probably better ways to point to the wsdl, but this one is easy enough for now :-).
  8. Scroll down and look for the functions(s) you need.  The function arguments are already there, only they are all set to “” or null.  Adjust the parameters to your needs ( is your friend if you want to see the declarations).
  9. Remove or remark the other functions, we don’t need them now.
  10. Run!

Do not proceed to the next step if you can’t run it in Eclipse yet.  Importing in Domino won’t fix the errors ;-).

Generate the webservice jar
  1. Choose File – Export – Java – JARfile.
  2. Choose next: select only the subdirectory with CXF classes (typically com….).
  3. Select the export destination, leave the rest as is.
    export jar
  4. Finish!
Prepare Domino
On your Domino server, navigate to [Domino program directory]/jvm/lib/security and edit the java.policy file – add this:

grant {
    permission java.lang.RuntimePermission "setContextClassLoader";
    permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};

Finally, a webservice consuming agent
  1.  Create a new agent, type Java.
  2. Import the CXF jar you generated with Import – Archive.
  3. Open JavaAgent.java for editing: copy paste parts of your Eclipse client example code to the agent (this screenshot might help you).
    agent class
    Notice you don’t have to add all imports you needed in Eclipse.  And you still have to add the WSDL_URL.
  4. Also add the function(s) you need.  Start by hardcoding the function arguments.
  5. Important: agent security settings! The runtime security level of the agent should be 3  -Allow restricted operations with full administration rights.
  6. For an easy start, print the results to the console (System.out.println(““)), or debug.  Open Tools – Show Java Debug Console.
  7. Test!

Conclusion

The beauty? We didn’t have to import any external jar files (apart from the CXF generated one) and we don’t have to mess with the lib\ext directory of the Domino server!

I hope I covered most aspects of the process, so that even Java dummies are able to create a client ;-).

7 Comments

  1. I’m glad it worked out. Actually you don’t need Eclipse, since you have it. In Domino Designer simply select Window – Open Perspective – Java and there you are. Saves you the headache to fiddle with the JVM since Domino Designer uses the right one.
    But most developers who do Java have a separate Eclipse install (I have several).
    Your next stop might be a visit to the beauty of BlueJ. It’s the perfect tool to poke around in Java objects while they are alive.
    :-) stw

    Reply
  2. I’ve used the Web Service Client project in Eclipse to generate java code for a web service. It’s also using CXF. Then I exported it to a JAR and imported it in to my nsf. I can then call the web service directly from ssjs. So i dont need any Java agents.

    So my question is if you think there is a way to do this directly in the domino designer without using Eclipse? I think the Web Service Client project is an Eclipse EE module. Does someone know if it’s possible to install and use it in domino designer? And does anyone know if it’s also possible to install the Apache CXF module in the designer as I did in Eclipse? Anny other suggestions on how to use domino designer to generate java for a web service which can be called directly from ssjs on a xpage?

    Reply
    • Johan, thanks for the addition, it’s actually also possible to use the Webservice Client project. What server did you select to accomplish this? I don’t think it’s possible to do this in Designer directly, because it seems like a stripped down version of Eclipse. And I think it’s good practice to do the more advanced stuff in the full version.

      Reply
  3. Lotus Notes products v8.5.2
    Windows server 2008R2
    Windows 7 SP1 64bt
    Java JDK v1.7

    I try to use Apache CXF
    Running from Eclipce was successful (java 1.7), IIS authorises me, web service command executed.

    Running same code from my Lotus designer (java 1.6) sometimes was succsess, but more often results in error in java console:
    javax.xml.ws.WebServiceException: Failed to access the WSDL at: http://x.com/sites/itprojects2/_layouts/EvrazProjects/WS/EvrazWebService.asmx?wsdl. It failed with:
    http://x.com/sites/itprojects2/_layouts/EvrazProjects/WS/EvrazWebService.asmx?wsdl.

    Caused by: java.io.FileNotFoundException: http://x.com/sites/itprojects2/_layouts/EvrazProjects/WS/EvrazWebService.asmx?wsdl
    at COM.ibm.JEmpower.applet.http.HttpURLConnection.getInputStream(HttpURLConnection.java:480)
    at java.net.URL.openStream(URL.java:1011)

    Java Agent code:

    import lotus.domino.*;
    import org.tempuri.*;

    import java.io.File;
    import java.net.MalformedURLException;
    import java.net.URL;
    import javax.xml.namespace.QName;
    import javax.jws.WebMethod;
    import javax.jws.WebParam;
    import javax.jws.WebService;
    import javax.xml.bind.annotation.XmlSeeAlso;
    import javax.xml.ws.RequestWrapper;
    import javax.xml.ws.ResponseWrapper;

    public class JavaAgent extends AgentBase {
    private static final QName SERVICE_NAME = new QName(“http://tempuri.org/”, “CreateSite”);
    public void NotesMain() {
    try {
    String serviceURL = “http://x.com/sites/itprojects2/_layouts/EvrazProjects/WS/EvrazWebService.asmx?wsdl”;
    URL wsdlURL = new URL(serviceURL);
    CreateSite ss = new CreateSite(wsdlURL, SERVICE_NAME);
    CreateSiteSoap port = ss.getCreateSiteSoap();
    port.createProjectSite(“889″, “889”, “Test889″, “889”, “889”, “889”, “889”, “889”);
    } catch(Exception e) {
    e.printStackTrace();
    }
    }
    }
    Agent security level set to 3.
    Agent scheduled for Never.

    Question is: why it working not always?

    Reply
  4. Just found that this error only appears if i open Java console before running Java agent. If open console after agent starts – all works ok!

    Reply
    • Strange… but then again, if it works, it works :-). Glad you found it!

      Reply
  5. Hi Martin,
    I have problem with running web service consumer on Lotus Domino 9. I use CXF library 3.0.10. The code is downloaded from external project on github, so it is proven as working. I have CXF libaries and other 3rd party jar in domino/lib/ext directory. Java policy in java.policy file is setup to grantedAll. When I run code, i get the follwoing error:

    Caused by: java.lang.NullPointerException
    at org.apache.cxf.wsdl11.WSDLServiceFactory.(WSDLServiceFactory.java:85)
    at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:218)
    at org.apache.cxf.jaxws.ServiceImpl.initialize(ServiceImpl.java:161)
    at org.apache.cxf.jaxws.ServiceImpl.(ServiceImpl.java:129)
    at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:101)
    at javax.xml.ws.Service.(Service.java:67)
    at cz.etrzby.xml.EETService.(EETService.java:58)

    WSDL I read this way:
    url = new File(“D:\\temp\\xxx.wsdl”).toURI().toURL();

    When I read wsdl from http, the error is the same.

    Java version i this:

    Java(TM) SE Runtime Environment (build pwi3260sr16fp30-20160726_01(SR16fp30))
    IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 Windows 7 x86-32 jvmwi3260sr16fp30-20
    160725_312906 (JIT enabled, AOT enabled)
    J9VM – 20160725_312906
    JIT – r9_20160725_121766
    GC – GA24_Java6_SR16_20160725_1417_B312906)
    JCL – 20160719_01

    Please could you help me?

    Thank you very much….

    Reply

Leave a Reply to Lukas Kucera Cancel reply

Your email address will not be published. Required fields are marked *

6 + 1 =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>