Sunday, May 08, 2011

Tivoli Directory Integrator Web Services

Tivoli Directory Integrator has supported web services for quite some time but the AxisEasyInvokeSoapWebServiceFunctionComponent sounds like it should be a straightforward drag, drop and point at a WSDL in order to enable TDI to call a web service without any knowledge of how web services work.

Of course, the reality is quite different and the word Easy in the middle of that component string is a tad misleading.

Let's construct a TDI web service client to retrieve a stock quote. Those nice people at webservicex.net have made a stockquote service available at http://www.webservicex.net/stockquote.asmx?wsdl.

Complex Types
Invoking a web service normally means that some data needs to be provided to the service and the service will respond with some data. The data involved is normally wrapped up in what is called a complex type. In other words, a data object which can have one or more data elements.

Supplying complex types to a Function Component is straightforward, but not in the traditional way of building an input or output map the way we do for most other components.

Thankfully, TDI comes with a "Complex Types Generator". Drop a Complex Types Generator function component into your assembly line, point it at the http://www.webservicex.net/stockquote.asmx?wsdl WSDL, provide a JAR file to collect the necessary Java code that will construct the Complex Types as such:


Click on "Generate Complex Types" and you should get the following result:

The JAR file should now be copied to your {TDI_HOME}\jars directory. I create a WSDL directory under 3rdparty for such JAR files - you might like to do something similar.

To make use of the JAR file, TDI should be restarted!

We can disable the Complex Types Generator component as it won't be required at runtime. Now, we can make use of our JAR file and call the web service.

I use the excellent Java Decompiler to look inside the JAR file which helps me determine the full names of the Complex Types and the methods I can use on them:

Now, with a JAR file and the knowledge of what's inside the JAR file, we can build a web service call. For ease of understanding, I'm going to create three components/connectors:

Component/Connector 1: Script
First, we create a script component which will build our complex type. The code is:

var GQ = NET.webserviceX.www.GetQuote();
GQ.setSymbol("MSFT");
work.setAttribute("GetQuote", GQ);

What this is doing is creating a complex type called GetQuote containing a Symbol attribute with a value of MSFT.

Component/Connector 2: AxisEasyInvokeSoapWebServiceFunctionComponent
Now we can make the call to the service with our next connector. Pointing the AxisEasyInvoke.... component at  http://www.webservicex.net/stockquote.asmx?wsdl WSDL we can select the GetQuote operation by clicking on Operations. The parameter to be supplied to the component (Operation Parameters) will be GetQuote and we specify our input and output complex types in the Advanced Pane as NET.webserviceX.www.GetQuote and NET.webserviceX.www.GetQuoteResponse as such:

Our Output Map should map the GetQuote work object as such:

Our Input Map should map the supplied Return object as such:

Component/Connector 3: The Result
Finally, we are going to insert a script to decrypt the information retrieved from the AxisEasyInvoke.... component:

var myReturn = work.getAttribute("return").getValue(0);
task.logmsg("INFO", myReturn.getGetQuoteResult().toString());

And when we run the Assembly Line, this is what we should get:

23:19:40,789 INFO  - CTGDIS087I Iterating.
23:19:40,790 INFO  - CTGDIS086I No iterator in AssemblyLine, will run single pass only.
23:19:40,790 INFO  - CTGDIS092I Using runtime provided entry as working entry (first pass only).
23:19:41,242 INFO  - [AxisEasyInvokeSoapWebServiceFunctionComponent] CTGDIZ601I Web service called successfully.
23:19:41,246 INFO - <StockQuotes>;<Stock>;<Symbol>;MSFT</Symbol>;<Last>;25.87</Last>;<Date>;5/6/2011</Date>;<Time>;4:00pm</Time>;<Change>;+0.08</Change>;<Open>;26.01</Open>;<High>;26.22</High>;<Low>;25.75</Low>;<Volume>;55993640</Volume>;<MktCap>;218.2B</MktCap>;<PreviousClose>;25.79</PreviousClose>;<PercentageChange>;+0.31%</PercentageChange>;<AnnRange>;22.73 - 29.73</AnnRange>;<Earns>;2.517</Earns>;<P-E>;10.25</P-E>;<Name>;Microsoft Corpora</Name>;</Stock>;</StockQuotes>;
23:19:41,247 INFO  - CTGDIS088I Finished iterating.
23:19:41,247 INFO  - CTGDIS100I Printing the Connector statistics.
23:19:41,248 INFO  -  [BuildComplexType] Calls: 1
23:19:41,249 INFO  -  [AxisEasyInvokeSoapWebServiceFunctionComponent] CallReply:1
23:19:41,250 INFO  -  [DecodeReturn] Calls: 1
23:19:41,250 INFO  - CTGDIS104I Total: CallReply:1.
23:19:41,251 INFO  - CTGDIS101I Finished printing the Connector statistics.
23:19:41,252 INFO  - CTGDIS080I Terminated successfully (0 errors).


I leave the parsing of the result to you and wish you all the best with your future Web Services' adventures.

5 comments:

Aditya said...

Hi Mr Stephen
I've been reading Your blogs for quite some time and I really appreciate Your content and kudos to Your subject-matter-expertise yet presented in a lucid style.
I just wanted to share something about this specific component.It looks like it is a limitation of the "Axis Easy Invoke WebService Function component" that one cannot use a proxy server to connect to the internet unlike the HTTP connector which has the parameter "ProxyServer" which takes the host and port.
This looks like a major limitation because in organizations typically one needs to connect to a proxy.

Thanks again for a fabulous writeup.

Cheers,
Aditya

Stephen Swann said...

Aditya, you are far too kind.

Glad you enjoy the blog. Hopefully I'll find some more time to add to it as I've been otherwise occupied over the summer!

mani said...

Hi,nice one. I am getting followng exception in TDI when i click generate complex type, Please advise

java.lang.Exception: java.lang.Exception: warning: [options] bootstrap class path not set in conjunction with -source 1.4
java.lang.Exception: warning: [options] bootstrap class path not set in conjunction with -source 1.4




Unknown said...

Hi Mr. Stephen,

Thank you very much for sharing the content.

I am also trying to use "ComplexTypesGenerator" Function Component in TDI. I provided the WSDL URL, Jar file name and JDK path (using jdk1.6.0_18). When I click on "Generate complex types", it is giving the following error.

com.ibm.jscript.InterpretException: Scrip interpreter error, line=23, col=22: Reference error: 'util' not found

I would really appreciate for your help.

Thanks,
Amit

Unknown said...

Hi Mr. Stephen,

Thank you very much for sharing the content.

I am also trying to use "ComplexTypesGenerator" Function Component in TDI. I provided the WSDL URL, Jar file name and JDK path (using jdk1.6.0_18). When I click on "Generate complex types", it is giving the following error.

com.ibm.jscript.InterpretException: Scrip interpreter error, line=23, col=22: Reference error: 'util' not found

I would really appreciate for your help.

Thanks,
Amit