Monday, October 17, 2011

Tivoli Directory Integrator Web Services Revisited

I really wanted to talk about two issues that have presented themselves to me recently when hacking my way around Tivoli Directory Integrator's implementation of web services functionality using the Apache Axis framework.

It has struck me, however, that the issues weren't really TDI issues at all. They were pure Axis issues that have been documented elsewhere on the web. That said, it can be difficult to find the information, and even more difficult to use the information in a TDI context. So, despite repeating what others have already found, I thought I'd share the solutions with you.

Integrated Windows Authentication
I like the idea that the WWW is fairly platform agnostic and encourages the use of open standards. But things don't always work out that way. Finding that a WSDL is being served by some Microsoft technology isn't necessarily a bad thing but when the server providing the service insists on the client using Integrated Windows Authentication to authenticate, then I start to scratch my head in a "why would someone do that" manner.

They do, though. And the Axis implementation within TDI won't perform Integrated Windows Authentication without some "tweakage".

That "tweakage" requires Axis to make use of the CommonsHTTPSender method as an HTTP transport rather than the default HTTPSender method. How did I find this out? I Googled it! Great news. Hurrah. But how do we tell Axis to make use of the CommonsHTTPSender method?

Axis 1.4 will search for a file called client-config.wsdd in the current working directory and this file contains the necessary parameters which tell Axis how to behave and more importantly, what transport to use. I figured that placing such a file somewhere in the Classpath would suffice, but I only managed to get Axis to load up the contents of my client-config.wsdd by placing it in the TDI home directory. In my case, that was:

c:\Program Files\IBM\TDI\V7.1\client-config.wsdd

And what were the contents of this file you might ask? Thankfully, I found one already on my system hidden in the bowels of the WebSphere file structure. A change of HTTPSender to CommonsHTTPSender resulted in this:

<?xml version=”1.0” encoding=”UTF-8”?>
    <parameter name=”disablePrettyXML” value=”true”/>
    <parameter name=”enableNamespacePrefixOptimization” value=”false”/>
  <handler name=”WSSResponseConsumerHandler” type=””/>
  <service name=”Trust” provider=”java:RPC” style=”document user=”literal”>
      <handler type=”WSSResponseConsumerHandler”/>
  <transport name=”http” pivot=”java:org.apache.axis.transpotr.http.CommonsHTTPSender”/>
  <transport name=”local” pivot=”java:org.apache.axis.transpotr.http.LocalSender”/>
  <transport name=”java” pivot=”java:org.apache.axis.transpotr.http.JavaSender”/>

A restart of TDI, and hey-presto! Without any further code changes, I was able to connect to my target web-service and authenticate using Integrated Windows Authentication.

Java Object Clashes
Another problem I had, however, was an issue with Complex Types. I've already spoken at length on this blog on Complex Types and how easy they are to handle and I staill maintain that this is true despite the issue I faced.

The target namespace listed in the WSDL I was pointing at had a URL style construction like such:


Now, generating complex types was throwing an error within my TDI console and the root cause was the namespace above and the fact that it was attempting to create a package called LARGECOMPANY.APPLICATION.SecurityManager.

Some head-scratching and a tweak of the WSDL so that SecurityManager read securitymanager instead resulted in my complex type jar file being created successfully? Why would this be the case, you might ask? I think it may have something to do with java.lang.SecurityManager and a clash of names!

Tweaking the WSDL is fine for solving the problem, but it didn't seem like a sensible approach to me. Asking the owner of the WSDL if they would mind changing the namespace resulted in a "Computer Says No" response. (Actually this is unfair - it resulted in a perfectly valid response explaining that many other clients were using the web-services in this state!)

Looking at the TDI console and the Complex Type Generator function reveals the WSDL2Java Options attribute and a blank value! Using the -p option here got me around the problem quite nicely as such:

-p bigcorpsecurity

The -p option overrides the namespace to package mappings and ensures that Axis will use the value assigned to this option as the package name. Details on all the WSDL2Java Options can be found on the Apache Axis website and it's worth a read if you ever come unstuck attempting to use the Complex Types Generator.