Archive for October, 2007

Java to SharePoint Integration – Part I

SharePoint (MOSS) or Windows SharePoint Services (WSS) seem to be everywhere now..but what is the story around integrating these products with Java applications?

Well…from my investigations, that depends on a number of things:

  • What version of Java is being used ?
  • What version of MOSS/WSS is being used ?
  • What level of integration is required ?

For the purposes of this integration exercise we will assume Java 1.4 (J2EE 4) and SharePoint 2007/WSS 3.0 are being used (typical scenario when integrating existing Java applications to new SharePoint/WSS services).

While it’s difficult to say where this will ultimately end up, one of the objectives of this exercise is to produce a matrix of the appropriate integration approach to use across the various Java and MOSS/WSS versions.

Key Requirements

The key requirements (made up for this exercise) that must be kept in mind are :

  1. Support for IIS authentication schemes (NTLM V1 for this exercise)
  2. Support for SharePoint/WSS remote access protocols
  3. Support for highest possible level of integration
  4. LAN based integration (no Internet specific transport required)

SharePoint/WSS Service Access Options

Fortunately MOSS/WSS products come with a number of service based access options, depending on the version. With MOSS 2007/WSS 3.0 the following are the main options. Please keep in mind that previous versions exposed less capabilities on these interfaces, so check the specific capabilities you need before choosing please:

  • WS-* SOAP web service interface
  • XML-RPC interface on object API

Java Options

Depending on what version of Java is being used, the integration options vary.

Java 1.4 (J2EE 4):

In version 1.4 of the Java platform, very limited support for WS-* based services exists in the base distribution. To support for WS-* SOAP web services interfaces to MOSS/WSS, additional web service framework may be required. While there are a number of possible java web service frameworks that could be used, I have selected Axis2 as it supports NTLM V1 as per the above requirements. Support for IIS authentication schemes is a key consideration! XML-RPC support is in the base distribution.

Java 1.5 (J2EE 5):

In version 1.5 of the Java platform, full support for WS-* based web services and XML-RPC interfaces is supported out of the box (including NTLM V1 authentication). I may look at an actual implementation using this later in the series.

Java 6:

Not considered in this series although full WS-* and XML-RPC support are in the base distribution and support NTLM V1 authentication.

 

Java 1.4 To SharePoint 2007 WS

Given the above background information, lets proceed with some coding. I have setup a SharePoint 2007 instance on my local machine to test against, however, the following code should work equally well against a WSS 3.0 installation.

While I have chosen to work with the NetBeans IDE (V5.5.1 – V6 out now) for this series, everything should work in other Java IDEs (and maybe we’ll try some later?). While I am not using a Java Application server in Part I, we will be looking at the Sun application server for J2EE 4 and 5 (and may look at the GlassFish distribution for J2EE 6 if I get that far in this series).

As I am using Axis2 V1.3, you can find an architectural overview of Axis2 here: Axis2 Architecture Overview. We do not need the full Axis2 server side stuff, so follow the instructions here for a simple binary distribution installation Axis2 Installation. The full user guide for Axis2 can be found here Axis2 User Guide. You need to download and install the binary distribution and setup the AXIS_HOME environment variable.

So to get this started, I created a new project in NetBeans. I’ve used a Java Class Library so that I can create a number of classes that encapsulate the web service interface to SharePoint and present a simple method based interface for the Java application (the methods defined will align with the functional capabilities of the interface). As SharePoint exposes a number of services (for functional service areas,, e.g Lists service provides a functions for managing SharePoint lists), we will align each service with a client class. Obviously, you may decide to do this differently, but from experience this pattern provides a simple to use client, hiding all web service complexity from the main Java application.

The next step is to use the Axis2 tools to generate the client proxy class. In order to do this, you need to first grab the WSDL produced by the service you wish to interface to. Simply type the URL of the service followed by ?wsdl into the address bar in your web browser (e.g. http://mymachine.com.au/_vti_bin/Lists.asmx?wsdl) and save the resulting XML/WSDL to a file on your local machine. I suggest you create a sub-folder for your project such as resources/META-INF/. For clarity I have saved the WSDL as Lists.asmx.wsdl.

Axis2 provides a number of options for generating client proxy code, depending on which SOAP data binding framework you wish to use:

  1. AXIOM client – Generic client proxy classes (not dedicated databound classes), does not data bind SOAP to java classes. Uses generic AXIOM classes for accessing web services. Must work with raw XML.
  2. Axis Data Binding. Default data binding framework but only really works with Axis2 web services. Defaults to AXIOM classes when used against SharePoint. Won’t work with all SOAP features.
  3. XMLBeans. Fully functional schema compiler, works with most WS compatible web services. More classes and more complex object model than ADB.
  4. JiBX. Full schema support, flexible but more complicated to setup.

We’ll try each of them and see where we end up.

To generate the client proxy classes using ADB, use the following command (run in the directory where the wsdl file is):

%AXIS2_HOME%\bin\WSDL2Java -Uri Lists.asmx.wsdl -p java2sharepoint.axisadb -d adb -s

This uses the WSDL2Java code generator to create the client proxy classes (ListsStub.java) in the package java2sharepoint.axisadb, using Axis Data Binding and outputting source files.

Next create the SharePoint interface wrapper class in java2sharepoint package and be sure the ListsStub code is being compiled into the project.

At this point I have decided to shortcut around the wrapper class and have created a Java console application that calls the web service directly. The code (Main.java) for this test application is as follows:

/*
 * Main.java
*/

package java2sharepoint;

import java2sharepoint.axisadb.ListsStub.GetListCollection;
import java2sharepoint.axisadb.ListsStub.GetListCollectionResponse;
import java.util.ArrayList;
import java.util.List;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.databinding.ADBException;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.axis2.util.JavaUtils;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.auth.AuthPolicy;

public class Main {

    /** Creates a new instance of Main */
    public Main() {
    }

    public static void main(String[] args) {
        try {
            // Setup Authentication parameters
            String username = "Derek.Miller";
            String password = "mypassword";
            String host = "moss.syddev01.mymachine.com";   // NOTE: Important to ensure fully qualified domain name is used 
            String domain = "syddev01";
            String realm = "syddev01";
            int port = 80;

            // Configure authenticator
            HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
            auth.setUsername(username);
            auth.setPassword(password);
            auth.setDomain(domain);
            auth.setHost(host);

           // Ensure NTLM authentication used
            List authPrefs = new ArrayList(1);
            authPrefs.add(AuthPolicy.NTLM);
            auth.setAuthSchemes(authPrefs);

           // Get stub
            ListsStub lists = new ListsStub("http://moss.syddev01.mymachine.com/_vti_bin/Lists.asmx");

                    // Set authenticator
                    lists._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, auth);
                    // Get request and execute
                    GetListCollection req = new GetListCollection();
                    GetListCollectionResponse res = lists.GetListCollection(req);
                    DisplayResult(req, res);
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("\n\n\n");
        }
    }

    protected static void DisplayResult(GetListCollection req, GetListCollectionResponse res) throws ADBException, XMLStreamException {
            System.out.println("Result OK : " + res.localGetListCollectionResultTracker + "\n");
            System.out.println("Result – Local Name:" + res.getGetListCollectionResult().getExtraElement().getLocalName() + "\n");
            // TODO: Parse out XML and look at results

    }
}

 

Since that seems to work, the next steps will be to pull out the results and have a look at what comes back. NOTE that although we used ADB, no real databinding is happening and it’s defaulting back to AXIOM classes. We’ll get into this in a future post.

 

 

del.icio.us Tags: