How to Do a Soap Web Service Call from Java Class

How to do a SOAP Web Service call from Java class?

I understand your problem boils down to how to call a SOAP (JAX-WS) web service from Java and get its returning object. In that case, you have two possible approaches:

  1. Generate the Java classes through wsimport and use them; or
  2. Create a SOAP client that:

    1. Serializes the service's parameters to XML;
    2. Calls the web method through HTTP manipulation; and
    3. Parse the returning XML response back into an object.


About the first approach (using wsimport):

I see you already have the services' (entities or other) business classes, and it's a fact that the wsimport generates a whole new set of classes (that are somehow duplicates of the classes you already have).

I'm afraid, though, in this scenario, you can only either:

  • Adapt (edit) the wsimport generated code to make it use your business classes (this is difficult and somehow not worth it - bear in mind everytime the WSDL changes, you'll have to regenerate and readapt the code); or
  • Give up and use the wsimport generated classes. (In this solution, you business code could "use" the generated classes as a service from another architectural layer.)

About the second approach (create your custom SOAP client):

In order to implement the second approach, you'll have to:

  1. Make the call:

    • Use the SAAJ (SOAP with Attachments API for Java) framework (see below, it's shipped with Java SE 1.6 or above) to make the calls; or
    • You can also do it through java.net.HttpUrlconnection (and some java.io handling).
  2. Turn the objects into and back from XML:

    • Use an OXM (Object to XML Mapping) framework such as JAXB to serialize/deserialize the XML from/into objects
    • Or, if you must, manually create/parse the XML (this can be the best solution if the received object is only a little bit differente from the sent one).

Creating a SOAP client using classic java.net.HttpUrlConnection is not that hard (but not that simple either), and you can find in this link a very good starting code.

I recommend you use the SAAJ framework:

SOAP with Attachments API for Java (SAAJ) is mainly used for dealing directly with SOAP Request/Response messages which happens behind the scenes in any Web Service API. It allows the developers to directly send and receive soap messages instead of using JAX-WS.

See below a working example (run it!) of a SOAP web service call using SAAJ. It calls this web service.

import javax.xml.soap.*;

public class SOAPClientSAAJ {

// SAAJ - SOAP Client Testing
public static void main(String args[]) {
/*
The example below requests from the Web Service at:
https://www.w3schools.com/xml/tempconvert.asmx?op=CelsiusToFahrenheit

To call other WS, change the parameters below, which are:
- the SOAP Endpoint URL (that is, where the service is responding from)
- the SOAP Action

Also change the contents of the method createSoapEnvelope() in this class. It constructs
the inner part of the SOAP envelope that is actually sent.
*/
String soapEndpointUrl = "https://www.w3schools.com/xml/tempconvert.asmx";
String soapAction = "https://www.w3schools.com/xml/CelsiusToFahrenheit";

callSoapWebService(soapEndpointUrl, soapAction);
}

private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException {
SOAPPart soapPart = soapMessage.getSOAPPart();

String myNamespace = "myNamespace";
String myNamespaceURI = "https://www.w3schools.com/xml/";

// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration(myNamespace, myNamespaceURI);

/*
Constructed SOAP Request Message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:myNamespace="https://www.w3schools.com/xml/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<myNamespace:CelsiusToFahrenheit>
<myNamespace:Celsius>100</myNamespace:Celsius>
</myNamespace:CelsiusToFahrenheit>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
*/

// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("CelsiusToFahrenheit", myNamespace);
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("Celsius", myNamespace);
soapBodyElem1.addTextNode("100");
}

private static void callSoapWebService(String soapEndpointUrl, String soapAction) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();

// Send SOAP Message to SOAP Server
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(soapAction), soapEndpointUrl);

// Print the SOAP Response
System.out.println("Response SOAP Message:");
soapResponse.writeTo(System.out);
System.out.println();

soapConnection.close();
} catch (Exception e) {
System.err.println("\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n");
e.printStackTrace();
}
}

private static SOAPMessage createSOAPRequest(String soapAction) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();

createSoapEnvelope(soapMessage);

MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", soapAction);

soapMessage.saveChanges();

/* Print the request message, just for debugging purposes */
System.out.println("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println("\n");

return soapMessage;
}

}

About using JAXB for serializing/deserializing, it is very easy to find information about it. You can start here: http://www.mkyong.com/java/jaxb-hello-world-example/.

SOAP request to WebService with java

A SOAP request is an XML file consisting of the parameters you are sending to the server.

The SOAP response is equally an XML file, but now with everything the service wants to give you.

Basically the WSDL is a XML file that explains the structure of those two XML.


To implement simple SOAP clients in Java, you can use the SAAJ framework (it is shipped with JSE 1.6 and above):

SOAP with Attachments API for Java (SAAJ) is mainly used for dealing directly with SOAP Request/Response messages which happens behind the scenes in any Web Service API. It allows the developers to directly send and receive soap messages instead of using JAX-WS.

See below a working example (run it!) of a SOAP web service call using SAAJ. It calls this web service.

import javax.xml.soap.*;

public class SOAPClientSAAJ {

// SAAJ - SOAP Client Testing
public static void main(String args[]) {
/*
The example below requests from the Web Service at:
http://www.webservicex.net/uszip.asmx?op=GetInfoByCity

To call other WS, change the parameters below, which are:
- the SOAP Endpoint URL (that is, where the service is responding from)
- the SOAP Action

Also change the contents of the method createSoapEnvelope() in this class. It constructs
the inner part of the SOAP envelope that is actually sent.
*/
String soapEndpointUrl = "http://www.webservicex.net/uszip.asmx";
String soapAction = "http://www.webserviceX.NET/GetInfoByCity";

callSoapWebService(soapEndpointUrl, soapAction);
}

private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException {
SOAPPart soapPart = soapMessage.getSOAPPart();

String myNamespace = "myNamespace";
String myNamespaceURI = "http://www.webserviceX.NET";

// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration(myNamespace, myNamespaceURI);

/*
Constructed SOAP Request Message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:myNamespace="http://www.webserviceX.NET">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<myNamespace:GetInfoByCity>
<myNamespace:USCity>New York</myNamespace:USCity>
</myNamespace:GetInfoByCity>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
*/

// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("GetInfoByCity", myNamespace);
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("USCity", myNamespace);
soapBodyElem1.addTextNode("New York");
}

private static void callSoapWebService(String soapEndpointUrl, String soapAction) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();

// Send SOAP Message to SOAP Server
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(soapAction), soapEndpointUrl);

// Print the SOAP Response
System.out.println("Response SOAP Message:");
soapResponse.writeTo(System.out);
System.out.println();

soapConnection.close();
} catch (Exception e) {
System.err.println("\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n");
e.printStackTrace();
}
}

private static SOAPMessage createSOAPRequest(String soapAction) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();

createSoapEnvelope(soapMessage);

MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", soapAction);

soapMessage.saveChanges();

/* Print the request message, just for debugging purposes */
System.out.println("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println("\n");

return soapMessage;
}

}

How to Make a SOAP Call using SOAP UI Generated code?

Since you mention you are out of your depth here, I'll start with an introduction.

A SOAP web service is just an API exposed over the web that can be invoked with HTTP POST methods by sending (and then receiving) an XML message as payload. This XML message must have a specific form, specified by both the SOAP protocol as well as the documentation of the web service, commonly also in machine readable format as a WSDL.

You can build these messages yourself by whatever way available (even string concatenation can work), and then make HTTP requests with whatever HTTP library you prefer. But you then must also parse the XML response you receive from the web service to extract the useful values out of it. And that's a pain in the butt.

Because SOAP is a protocol with defined rules, and the WSDL describes the web service contract, you can use the WSDL to generate client code that handles these things for you. It will build the XML request messages and parse the XML response messages, and will invoke the operations of the service by making appropriate HTTP calls for you. What you will get from your client will be familiar Java objects and methods that you can work with without concern for what happens on the wire.

You did this with SoapUI, but I'm not sure what kind of client code you got back from that. You are showing an interface, but that's not enough to call the service. It just defined the contract with all of the operations of the service. Those annotations just add metadata about the operations. They don't invoke the methods. For that you need a proper client not just a contract.

The annotations shown in your question are part of the JAX-WS specification. You need a JAX-WS implementation of the client to handle the call to the service for you. Something like Apache CXF for example.

I would suggest you don't use SoapUI to generate code. Use your implementation of choice to generate the code from the WSDL. For example, Apache CXF has a command line tool (also a Maven plugin) called wsdl2java that can generate the client code for you. Then it's a matter of just instantiating the generated client and call methods on it like any Java object. The methods will receive Java objects and return java objects. Everything else related to SOAP or HTTP requests is handled by the client for you.

For example:

wsdl2java -client -keep -d C:\temp http://www.dneonline.com/calculator.asmx?WSDL

Will generate a bunch of classes for this online demo web service: http://www.dneonline.com/calculator.asmx?WSDL

Add.java
AddResponse.java
Calculator.java
CalculatorSoap.java
CalculatorSoap_CalculatorSoap12_Client.java
CalculatorSoap_CalculatorSoap_Client.java
Divide.java
DivideResponse.java
Multiply.java
MultiplyResponse.java
ObjectFactory.java
package-info.java
Subtract.java
SubtractResponse.java

The files contain a client class with a main() method inside that shows how you can invoke the service operations. For example:

private static final QName SERVICE_NAME = new QName("http://tempuri.org/", "Calculator");

public static void main(String args[]) throws java.lang.Exception {
URL wsdlURL = Calculator.WSDL_LOCATION;

// ...

Calculator ss = new Calculator(wsdlURL, SERVICE_NAME);
CalculatorSoap port = ss.getCalculatorSoap();

// ...

System.out.println("Invoking add...");
int _add_intA = 0;
int _add_intB = 0;
int _add__return = port.add(_add_intA, _add_intB);
System.out.println("add.result=" + _add__return);

// ...
}

These generated classes extend classes from the Apache CXF framework and handle the calls for you.

This particular example contains two client classes because the demo service I've used to explain this has two bindings, for SOAP 1.1 and SOAP 1.2. The client code to invoke the service over the two SOAP versions is almost the same, you just need to select the desired port first.

Hope this explains things enough so that you now understand what you need to do to call your service.

Send Soap request with Java

Below there's a demo of how you could do it. Basically you call addChildElement and addTextNode for each element you need.

Make sure you change the endpoint URL and SOAP Action in the main method before calling.

import javax.xml.soap.*;

public class SOAPClientSAAJ {

// SAAJ - SOAP Client Testing
public static void main(String args[]) {
String soapEndpointUrl = "https://www.w3schools.com/xml/tempconvert.asmx"; // CHANGE ME
String soapAction = "https://www.w3schools.com/xml/CelsiusToFahrenheit"; // CHANGE ME

callSoapWebService(soapEndpointUrl, soapAction);
}

private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException {
SOAPPart soapPart = soapMessage.getSOAPPart();

String myNamespace = "tem";
String myNamespaceURI = "http://tempuri.org/";

// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration(myNamespace, myNamespaceURI);

// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("pay", myNamespace);

SOAPElement merchantId = soapBodyElem.addChildElement("merchantId", myNamespace);
merchantId.addTextNode("7507231");

SOAPElement branch = soapBodyElem.addChildElement("branch", myNamespace);
branch.addTextNode("Licensed Branch Name");

SOAPElement alias = soapBodyElem.addChildElement("alias", myNamespace);
alias.addTextNode("Service alias Name");

SOAPElement paymentId = soapBodyElem.addChildElement("paymentId", myNamespace);
paymentId.addTextNode("merchants payment idetificator");

SOAPElement data = soapBodyElem.addChildElement("data", myNamespace);
SOAPElement dataParam = data.addChildElement("param", myNamespace);
SOAPElement dataParamKey = dataParam.addChildElement("key", myNamespace); dataParamKey.addTextNode("account");
SOAPElement dataParamValue = dataParam.addChildElement("value", myNamespace); dataParamValue.addTextNode("account cridentials");

SOAPElement hash = soapBodyElem.addChildElement("hash", myNamespace);
hash.addTextNode("?");
}

private static void callSoapWebService(String soapEndpointUrl, String soapAction) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();

// Send SOAP Message to SOAP Server
SOAPMessage soapRequest = createSOAPRequest(soapAction);
SOAPMessage soapResponse = soapConnection.call(soapRequest, soapEndpointUrl);

// Print the SOAP Response
System.out.println("Response SOAP Message:");
soapResponse.writeTo(System.out);
System.out.println();

soapConnection.close();
} catch (Exception e) {
System.err.println("\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n");
e.printStackTrace();
}
}

private static SOAPMessage createSOAPRequest(String soapAction) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();

createSoapEnvelope(soapMessage);

MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", soapAction);

soapMessage.saveChanges();

/* Print the request message, just for debugging purposes */
System.out.println("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println("\n");

return soapMessage;
}

}

Common request/response objects between 2 SOAP webservices in Java

It's a bit complex, but you can specify (when applying wsdl2java) a "binding file" that will allow you, via XJC, to customize the way Java classes are generated (eg the package names, the type mapping, etc...)

In your particular case, you should look at "episode":

A .episode file is generated by the XJC (XML Schema to Java) compiler.
It is a schema bindings that associates schema types with existing
classes. It is useful when you have one XML schema that is imported by
other schemas as it prevents the model from being regenerated.

(Old but) Interesting article:

https://dzone.com/articles/reusing-generated-jaxb-classes

Working Soap client example

To implement simple SOAP clients in Java, you can use the SAAJ framework (it is shipped with JSE 1.6 and above, but removed again in Java 11):

SOAP with Attachments API for Java (SAAJ) is mainly used for dealing directly with SOAP Request/Response messages which happens behind the scenes in any Web Service API. It allows the developers to directly send and receive soap messages instead of using JAX-WS.

See below a working example (run it!) of a SOAP web service call using SAAJ. It calls this web service.

import javax.xml.soap.*;

public class SOAPClientSAAJ {

// SAAJ - SOAP Client Testing
public static void main(String args[]) {
/*
The example below requests from the Web Service at:
http://www.webservicex.net/uszip.asmx?op=GetInfoByCity

To call other WS, change the parameters below, which are:
- the SOAP Endpoint URL (that is, where the service is responding from)
- the SOAP Action

Also change the contents of the method createSoapEnvelope() in this class. It constructs
the inner part of the SOAP envelope that is actually sent.
*/
String soapEndpointUrl = "http://www.webservicex.net/uszip.asmx";
String soapAction = "http://www.webserviceX.NET/GetInfoByCity";

callSoapWebService(soapEndpointUrl, soapAction);
}

private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException {
SOAPPart soapPart = soapMessage.getSOAPPart();

String myNamespace = "myNamespace";
String myNamespaceURI = "http://www.webserviceX.NET";

// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration(myNamespace, myNamespaceURI);

/*
Constructed SOAP Request Message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:myNamespace="http://www.webserviceX.NET">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<myNamespace:GetInfoByCity>
<myNamespace:USCity>New York</myNamespace:USCity>
</myNamespace:GetInfoByCity>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
*/

// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("GetInfoByCity", myNamespace);
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("USCity", myNamespace);
soapBodyElem1.addTextNode("New York");
}

private static void callSoapWebService(String soapEndpointUrl, String soapAction) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();

// Send SOAP Message to SOAP Server
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(soapAction), soapEndpointUrl);

// Print the SOAP Response
System.out.println("Response SOAP Message:");
soapResponse.writeTo(System.out);
System.out.println();

soapConnection.close();
} catch (Exception e) {
System.err.println("\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n");
e.printStackTrace();
}
}

private static SOAPMessage createSOAPRequest(String soapAction) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();

createSoapEnvelope(soapMessage);

MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", soapAction);

soapMessage.saveChanges();

/* Print the request message, just for debugging purposes */
System.out.println("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println("\n");

return soapMessage;
}

}


Related Topics



Leave a reply



Submit