SharePoint Web Services, Spring, and NTLM authentication

SharePoint is widely known among .NET developers, but not so recognized in the group of JVM worshippers. Yet, sometimes integration between these two universes is required and one of possible choices to perform the connection is the set of SOAP web services exposed by the platform. It this article you’ll learn how to communicate your Spring application with a SharePoint instance.

Advertisement

1. Dependencies

So you have just created a brand new Spring application or you already had one and now you want to integrate it with some existing SharePoint server. First, you need to declare mandatory dependencies in your pom.xml, which are Spring WS as a base abstraction for SOAP and httpclient required for NTLM authentication implemented in the product of Microsoft.

<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core</artifactId>
    <version>2.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>

2. Download WSDL and generate client code

A WSDL file with the API definition that you want to use is the next thing you need. SharePoint exposes several contracts and each of them groups common operations. As an example, we’re going to pick the DWS web service, which allows basic operations when dealing with Document Workspaces. Where can you get the WSDL file? You need to know the address of the service that you want to call. Once you have the base URL of the server, append _vti_bin/dws.asmx?wsdl to see the WSDL file in your browser.

Here’s a sample of the full URL. If you work with a SharePoint site, you should give its whole address.

http://spserver.com/_vti_bin/dws.asmx?wsd

Later, save the WSDL file in your project under the resources/wsdl directory. We’re going to use maven-jaxb2-plugin to generate Java client code based on the file. The Maven configuration of the plugin is presented below. After running the build all generated classes will be placed under target/generated-sources/xjc.

<build>
    <plugins>
        <plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <version>0.13.1</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <schemaDirectory>src/main/resources/wsdl</schemaDirectory>
                <schemaIncludes>
                    <include>*.wsdl</include>
                </schemaIncludes>
                <removeOldOutput>true</removeOldOutput>
            </configuration>
        </plugin>
    </plugins>
</build>

3. Spring WS and NTLM configuration

Authentication to the SharePoint server requires credentials and your domain name. For clarity of the guide, we use plain values stored in application.properties loaded by Spring, but in your real project you should at least encrypt the data.

sharepoint.username=login
sharepoint.password=MySecretPassword
sharepoint.domain=COMPANYDOMAIN

Next, we need to create three beans in your Spring configuration. First one is a message sender, which aggregates authentication details from the properties file. The following sample contains all required values injected into the configuration class. These fields are passed to the NTCredentials class constructor, which creates object used for the SharePoint authentication process.

import org.apache.http.auth.NTCredentials;
import org.springframework.ws.transport.http.HttpComponentsMessageSender;

@Configuration
public class SharePointConfiguration {

    @Value("${sharepoint.username}")
    private String username;
    @Value("${sharepoint.password}")
    private char[] password;
    @Value("${sharepoint.domain}")
    private String domain;

    @Bean
    public HttpComponentsMessageSender httpComponentsMessageSender() {
        HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();
        NTCredentials credentials = new NTCredentials(username, String.valueOf(password), null, domain);
        httpComponentsMessageSender.setCredentials(credentials);
        return httpComponentsMessageSender;
    }

}

The second bean, presented below, is a marshaller object, which is responsible for conversion of transmitted data into and from Java classes. You might be wondering why we set packageToScan to com.microsoft.schemas.sharepoint.soap. This is the package which is generated by Maven plugin based on schema targetNamespace attribute in the WSDL file. Thanks to the property the marshaller object knows where to look for mapping classes.

@Bean
public Jaxb2Marshaller marshaller() {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setPackagesToScan("com.microsoft.schemas.sharepoint.soap");
    return marshaller;
}

The last bean is WebServiceTemplate, which aggregates previously defined objects and acts as the main bridge between the application and web services.

@Bean
public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller, WebServiceMessageSender messageSender) {
    WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marshaller, marshaller);
    webServiceTemplate.setMessageSender(messageSender);
    return webServiceTemplate;
}

4. Web Service client

Now it’s time to make use of configured beans and classes generated by the Maven plugin. Create a service class and inject the configured WebSericeTemplate instance. To call SharePoint web service you need its URL, the same one that you used to fetch the WSDL definition, and a SOAP action callback object, which allows choosing a particular service operation by setting the action header on a transported message. For demonstration purpose, we’re going to focus on the CreateFolder operation as it’s one of the simplest exposed by SharePoint.

@Service
public class SharePointDwsClient {

    private static final String WS_URL = "http://spserver.com/_vti_bin/dws.asmx";
    private static final SoapActionCallback CREATE_FOLDER_SOAP_ACTION = new SoapActionCallback("http://schemas.microsoft.com/sharepoint/soap/dws/CreateFolder");

    private WebServiceTemplate webServiceTemplate;

    @Autowired
    public SharePointDwsClient(WebServiceTemplate webServiceTemplate) {
        this.webServiceTemplate = webServiceTemplate;
    }

}

In production code it would be advised to put the address of the server in the properties file, but since this is just an example I hope you turn a blind eye to it 😉 Next, you need to create a request with a mandatory parameter and send it using WebServiceTemplate in the company of the URL and the SOAP action. Note that we use classes from the com.microsoft.schemas.sharepoint.soap.dws package generated in the Step 2. The result should be cast to an appropriate type for further verification.

public void createFolder(String path) {
    CreateFolder request = buildCreateFolderRequest(path);
    CreateFolderResponse response = (CreateFolderResponse) webServiceTemplate.marshalSendAndReceive(WS_URL, request, CREATE_FOLDER_SOAP_ACTION);
    // verify response.getCreateFolderResult()
}

private CreateFolder buildCreateFolderRequest(String path) {
    CreateFolder request = new CreateFolder();
    request.setUrl(path);
    return request;
}

5. Calling SharePoint Web Service

The setup has been finished. We can now make an actual request to the web service using the written client. Inject the SharePointDwsClient object to your application and call the createFolder method with your desired folder path.

dwsClient.createFolder("Spring WS");

And voilà!

sharepoint-result

Congratulations!

You’ve just made your first successful web service call to SharePoint web service. Thanks to Spring WS authentication logic and data marshalling is almost completely hidden from sight. The small demo application can be downloaded using this link. If you have any question, suggestion or something isn’t clear enough, please don’t hesitate to write a comment or contact me via e-mail.

Facebooktwittergoogle_plusredditlinkedinmail
Advertisement

2 Replies to “SharePoint Web Services, Spring, and NTLM authentication”

  1. Hi, thanks a lot for this tutorial.
    I adapted your project. Works great but I have some problem for unit testing your service.
    Did you managed to do it and if you did, how did you manage to inject the proper configuration ?

  2. Hi Daniel, it is very good article covering the NTLM Auth mechanism. Wanted to check if we can use Kerberos instead of NTLM? How to go about for the same stack of Spring boot + SOAP Webservices?

Leave a Reply