How to send a SOAP request using WebServiceTemplate?
Asked Answered
J

5

29

I am trying to send a request to a SOAP webservice. I read this tutorial and prepared the following code. However, I am going to send different requests to multiple SOAP webservices, whereas the tutorial focused on one request. How can I send SOAP request using WebserviceTemplate?

WebServiceTemplate

    SoapMessage soapMsg = new SoapMessage();
    soapMsg.setUsername("Requester");
    soapMsg.setPassword("Pass");
    soapMsg.setLanguageCode("EN");
    Request request = new Request();
    request.setDeparture("FDH");
    request.setDestination("HAM");
    Date date = new Date();
    SimpleDateFormat frm2 = new SimpleDateFormat("yyyy-MM-dd");
    request.setDepartureDate(frm2.parse(frm2.format(date)));
    request.setNumADT(1);
    request.setNumCHD(0);
    request.setNumInf(0);
    request.setCurrencyCode("EUR");
    request.setWaitForResult(true);
    request.setNearByDepartures(true);
    request.setNearByDestinations(true);
    request.setRronly(false);
    request.setMetaSearch(false);
    soapMsg.setRequest(request);
    WebServiceTemplate webServiceTemplate = new WebServiceTemplate().  //how to create object and send request!
    Object response = webServiceTemplate.marshalSendAndReceive(
            "https://aaa5.elsyarres.net", soapMsg);
    Response msg = (Response) response;
    System.err.println("size of results of wogolo:"
            + msg.getFlights().getFlight().size());
Jamilla answered 19/12, 2015 at 6:29 Comment(2)
Do you have a good reason for doing this manually? You can generate a web service proxy if you have the services wdsl file. Here are instructions for how to do this in eclipse.Gestate
@Pétur The issue is that I do not have wsdl, also I am going to send SOAP requests to multiple SOAP based webservices.Jamilla
C
21

You can use following code, you do not need to define anything in xml file.

  try {
            SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(
                    MessageFactory.newInstance());
            messageFactory.afterPropertiesSet();

            WebServiceTemplate webServiceTemplate = new WebServiceTemplate(
                    messageFactory);
            Jaxb2Marshaller marshaller = new Jaxb2Marshaller();

            marshaller.setContextPath("PACKAGE");
            marshaller.afterPropertiesSet();

            webServiceTemplate.setMarshaller(marshaller);
            webServiceTemplate.afterPropertiesSet();

            Response response = (Response) webServiceTemplate
                    .marshalSendAndReceive(
                            "address",
                            searchFlights);

            Response msg = (Response) response;
        } catch (Exception s) {
            s.printStackTrace();
        }
Constrictive answered 8/1, 2016 at 10:49 Comment(3)
if i don't set unmarshaller i get 'java.lang.IllegalStateException: No unmarshaller registered. Check configuration of WebServiceTemplate.' You can pass this exception with 'webServiceTemplate.setUnmarshaller(marshaller);'Kinase
What to put instead of PACKAGE?Dumond
@HerilMuratovic I'm using setPackagesToScan instead. Documentation says: Set the packages to search for classes with JAXB2 annotations in the classpath. This is using a Spring-bases search and therefore analogous to Spring's component-scan featureSakhuja
H
8

To send different SOAP requests to different SOAP services, you just need to make your WebServiceTemplate aware of all requests and responses it will have to process.

Create a Java class for each request and response like so:

package models;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;

@XmlRootElement
public class FlyRequest implements Serializable {

    private boolean nearByDeparture;

    public FlyRequest() {}

    public boolean isNearByDeparture() {
        return nearByDeparture;
    }

    public void setNearByDeparture(boolean nearByDeparture) {
        this.nearByDeparture = nearByDeparture;
    }
}

(The @XmlRootElement is because we use JAXB marshaller below; see Jaxb reference for more info).

The setup of the template is done for example like so:

    SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(MessageFactory.newInstance());
    messageFactory.afterPropertiesSet();

    WebServiceTemplate webServiceTemplate = new WebServiceTemplate(messageFactory);
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setContextPath("models");
    marshaller.afterPropertiesSet();

    webServiceTemplate.setMarshaller(marshaller);
    webServiceTemplate.afterPropertiesSet();

"models" is the name of the package where the Request/Responses classes are, so that jaxb can find them.

Then you just instantiate the request of the class you want to perform the call, like so:

    // call fly service:
    FlyRequest flyRequest = new FlyRequest();
    flyRequest.setNearByDeparture(false);
    Object flyResponse = webServiceTemplate.marshalSendAndReceive("https://example.net/fly", flyRequest);

    // call purchase service:
    PurchaseRequest purchaseRequest = new PurchaseRequest();
    purchaseRequest.setPrice(100);
    Object purchaseResponse = webServiceTemplate.marshalSendAndReceive("https://example.net/purchase", purchaseRequest);

Similarly, you can cast the response objects into your JAXB classes defined above.

Humism answered 23/12, 2015 at 10:31 Comment(1)
I used the code but it returns following Caused by: javax.xml.bind.JAXBException: "my.project.flights.wegolo" doesnt contain ObjectFactory.class or jaxb.indexJamilla
K
3

Here is an Example what you should be looking for

Soap has a lot of restriction unlike REST, It follows some standards which have to be meet before you get Network call to work,

But unlike Rest, in Soap if you have WSDL URL you can get all the information needed to call the Soap call

private final String NAMESPACE = "http://www.w3schools.com/webservices/";
private final String URL = "http://www.w3schools.com/webservices/tempconvert.asmx?WSDL";
private final String SOAP_ACTION = "http://www.w3schools.com/webservices/CelsiusToFahrenheit";
private final String METHOD_NAME = "CelsiusToFahrenheit";

this code was written in Android so you can ignore some part of it but I still kept it in answer so someone from android background can put a good use to it

Open [WSDL][1] in browser and check for the things which matter to call a remote method on server.

1 you will see an attribute targetNamespace whose value would be Namespace which you will use in this case Namespace is http://www.w3schools.com/webservices/

2 Now you require the name of the method this WSDL has four method each of the are int attribute s:element with the value is the name of the Method in this case four methods are FahrenheitToCelsius, FahrenheitToCelsiusResponse, CelsiusToFahrenheit, CelsiusToFahrenheitResponse

3 Now you have to fure out the SOAP Action which is NAMESPACE+METHOD but WSDL also gives information about that as well, look for the tag soap:operation and it's soapAction attribute havs the Soap action as it's value in this case which we want to call is http://www.w3schools.com/webservices/CelsiusToFahrenheit

private class MyTask extends AsyncTask<Void, Void, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog.show();
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            SoapObject soapObject = new SoapObject(NAMESPACE, METHOD_NAME);

            soapObject.addProperty("Celsius","12");


            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(soapObject);
            HttpTransportSE httpTransportSE = new HttpTransportSE(URL);

            httpTransportSE.call(SOAP_ACTION, envelope);
            SoapPrimitive soapPrimitive = (SoapPrimitive)envelope.getResponse();
            Log.d("TAG", "doInBackground: "+soapPrimitive.toString());

            return soapObject.toString();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(String aVoid) {
        super.onPostExecute(aVoid);
        progressDialog.dismiss();
        textView.setText(""+aVoid);
    }
}
Korea answered 19/12, 2015 at 7:41 Comment(5)
It seems it is not using WebServiceTemplate of Spring framework am I right? I am interested in learning about SOAP support of Spring frameworkJamilla
are you using soap:soap:2.3.1 library to make the soap callKorea
@Jack, if possible, Kindly provide WSDL url, I will update the answer so that you can checkKorea
The problem is, I do not have WSDL.Jamilla
URL is now: w3schools.com/xml/tempconvert.asmx?wsdlFerrocyanide
S
2

Assuming that your SoapMessage is marhsallable

To send the same message to multiple endpoints you only need to loop on the sending code and the request handler.

Something like this:

{
    String endpoint = "https://aaa5.elsyarres.net"
    WebServiceTemplate webServiceTemplate = new WebServiceTemplate().
    webServiceTemplate.setDefaultUri(endpoint);
    Object response = webServiceTemplate.marshalSendAndReceive(soapMsg);
    // handle you are response as you are currently doing.
    // Loop changing the endpoint as you need.
}

This code uses the Spring WebServiceTemplate

Salivation answered 7/1, 2016 at 14:43 Comment(0)
K
-1

I tried many options and finally below one worked for me if you have to send soap header with authentication(Provided authentication object created by wsimport) and also need to set soapaction.

public Response callWebService(String url, Object request)

{
    Response res = null;
    log.info("The request object is " + request.toString());

    try {
        
        

        res = (Response) getWebServiceTemplate().marshalSendAndReceive(url, request,new WebServiceMessageCallback() {
                 @Override
                  public void doWithMessage(WebServiceMessage message) {
                    try {
                      // get the header from the SOAP message
                      SoapHeader soapHeader = ((SoapMessage) message).getSoapHeader();

                      // create the header element
                      ObjectFactory factory = new ObjectFactory();
                      Authentication auth =
                          factory.createAuthentication();
                      auth.setUser("****");
                      auth.setPassword("******");
                     ((SoapMessage) message).setSoapAction(
                                "soapAction");

                      JAXBElement<Authentication> headers =
                          factory.createAuthentication(auth);

                      // create a marshaller
                      JAXBContext context = JAXBContext.newInstance(Authentication.class);
                      Marshaller marshaller = context.createMarshaller();

                      // marshal the headers into the specified result
                      marshaller.marshal(headers, soapHeader.getResult());
                      
                    } catch (Exception e) {
                      log.error("error during marshalling of the SOAP headers", e);
                    }
                  }
                });

        
    } catch (Exception e) {
        e.printStackTrace();
    }
    return res;

}
Kindling answered 10/7, 2020 at 19:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.