Thursday, February 7, 2019

How to consuming a soap endpoint in java

A soap end point looks something like
http://xyzcode.xyz/quote
usually the wsdl file can be download from
http://xyzcode.xyz/quote?wsdl

The wsdl file will give the instruction about how to consume the soap web service, that is all you needed to know in order to talk to soap api besides the user/pass for authentication.

Start with a wsdl file such as quote.wsdl, you can import the file into third-party gui tools such as soapUI, then you fill up all the fields for the request in xml format, and press send then wait, the soapUI will send your request to the remote endpoint with soap protocol, then get the response, then print the output in xml format.

Instead of manually filling the request fields in SoapUI GUI, you can have a java program to automatically fill all the needed fields, construct the request object, serialize it, have a SAAJ client send the request down to the wire with soap protocol, then wait for the SAAJ client to get the soap response back, then deserialize the response into response object.

The following tools and packages are what you need to make it happen.

1. apache wsdl2java.
Once you downloaded the tool from apache site, you can issue the following command to convert the wsdl file into corresponding java files.
The command is:
wsdl2java quote.wsdl

You most likely end up with 2 folder generated: com and org, within which, your wsdl generated java files reside.

An important thing to note is: the tool generated many ObjectFactory.java files for serializer and deserializer to consume. You can find the location of those OjectFactory.java by the following command:

find . -name ObjectFactory.java

the output could be something like:

./com/yourinventit/processing/android/serial/ObjectFactory.java
./com/yourinventit/processing/android/ObjectFactory.java
./org/helloexample/ObjectFactory.java

2. SAAJ client
The SOAP with Attachments API for Java or SAAJ provides a standard way to send XML documents over the Internet from the Java platform.

The maven saaj dependency is:
<dependency>
    <groupId>com.sun.xml.messaging.saaj</groupId>
    <artifactId>saaj-impl</artifactId>
    <version>1.5</version>
</dependency>

With saaj you can create soap calls like the following. In order to request, we need to create the Request message. Follow the same way we used to fill the request form in soapUI GUI, here we need to fill many fields in the request SOAPMessage object as well. We fill these fields with the help of wsdl generated classes.

SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection connection = soapConnectionFactory.createConnection();
URL endpoint = new URL("http://xyzcode.xyz/quote");
MyPayload payload = business.getRequest();  //pass in from call param
SOAPMessage  message = funcCreateRequest(payload);  //use wsdl generated classes
SOAPMessage response = connection.call(message, endpoint);
connection.close();

3. jaxb
We said that we fill soap request fields with the help of wsdl generated classes. In fact, there are java library to help serialize and deserialize your soap request and response. The tool for that is jaxb.
You can include jaxb using maven.

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.12</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.11</version>
</dependency>

Once you have jaxb, you need to tell JAXBContext where to find the ObjectFactory.java files in order to serialize and deserialize soap objects generated by the wsdl file.
With the above example, your initialization will looks like:

JAXBContext jc = JAXBContext.newInstance("com.yourinventit.processing.android.serial:com.yourinventit.processing.android:org.helloexample:org.helloexample");

Once you have the JAXB initialized, you can convert between object and xml string.
For request

MyPayload payload = business.getRequest();  //pass in from call param
Marshaller m = jc.createMarshaller();
StringWriter w = new StringWriter();
xsw = XMLOutputFactory.newInstance().createXMLStreamWriter(w);
m.marshal(payload, xsw);  //consume objects specified in ObjectFactory.java
String requestString = w.getBuffer().toString();
SOAPMessage soapMessage = funcBuildSoapRequest(requestString);

For response
Node payload = soapMessage.getSOAPBody().getFirstChild();
String responseString  = funcConvertPayloadToString(payload);
Unmarshaller u = jc.createUnMarshaller();
xsr = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(responseString));
Object o = unmarshaller.unmarshal(xsr);  //consume objects specified in ObjectFactory

The "Object o" can be cast to one of the wsdl object, then you can pass the object around in your program.



No comments:

Post a Comment

Why I stopped publishing blog posts as information provider

Now the AI can generate content. Does that mean the web publishing industry reaches the end? ChatGPT said: ChatGPT Not at all. While AI can ...