Saturday, March 5, 2011

Spring Web Services 2 - Part II ( Marshalling , UnMarshalling using JAXB)

In second part of the series, we will talk about how to use Marshaller's in order to automatically convert your request and response object to the SOAP Body XML (of request n response ) with the corresponding Namespace defined in the Java Source files.
Just like the first part, we will use Spring WS2- Part I we will use the same web service hosted at W3Schools.com but this time, with a very short code, as compared to Part-I .
Spring Web Services 2 makes use of a number of marshallers and unmarshallers in order to perform the tasks that include Spring OXM, Castom, Jaxb2. As JAXB 2 is the specification, so we will go by that only.

Note: Please add Jaxb libraries in your classpath while performing the action during this tutorial.

Configuration: So we will directly delve in the spring configuration (acjaxb.xml) as required for this tutorial.



    
    
    
    
        
       
            

                springwsjxb.CelsiusToFahrenheit
                springwsjxb.CelsiusToFahrenheitResponse
                
            
        
  
        
            
                
            
        
    

    
        
    

     
     
        
        
        
        
        
    



As our current configuration describes that we are using two classes CelsiusToFahrenheit and CelsiusToFahrenheitResponse present in the springws packagejxb. Here is the corresponding source code for both of them. The Source code includes the Namespace details also, it becomes very important once we need to generate the XML, in any case if we missed out the namespace the coressponding web service will not be able to parse it and will throw an exception.
CelsiusToFahrenheit.java


package springwsjxb;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author PankajB
 */
@XmlType(name="tem")
@XmlRootElement(name="CelsiusToFahrenheit",namespace="http://tempuri.org/")
public class CelsiusToFahrenheit {

    private int celsius;
   

    @XmlElement(name="Celsius",namespace="http://tempuri.org/")
    public int getCelsius() {
        return celsius;
    }

    public void setCelsius(int celsius) {
        this.celsius = celsius;
    }
}

CelsiusToFahrenheitResponse.java



package springwsjxb;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name="CelsiusToFahrenheitResponse",namespace="http://tempuri.org/")
public class CelsiusToFahrenheitResponse {

    private int result;

    //CelsiusToFahrenheitResult is the name of the XML Element which is being returned from the Web service and belongs to namespace "http://tempuri.org/"

    @XmlElement(name="CelsiusToFahrenheitResult",namespace="http://tempuri.org/")
    public int getResult() {
        return result;
    }

    public void setResult(int result) {
        this.result = result;
    }

}

As per the requirements of the web service, we had kept only those variables here in our objects.
Now our Main.java file which will be responsible for invoking the web service and give us the response object.
Main.java


package springwsjxb;

import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.SoapMessage;

/**
 *
 * @author PankajB
 */
public class Main {

   
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        try
        {
   // Load the spring web service configuration file
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springwsjxb/acjaxbb.xml");
        WebServiceTemplate webServiceTemplate = (WebServiceTemplate)applicationContext.getBean("webServiceTemplate");       
        // Creating the Request Object and setting it properties
        CelsiusToFahrenheit celsiusToFahrenheit=new CelsiusToFahrenheit();
        celsiusToFahrenheit.setCelsius(100);
        // Invoking the web service and getting the response back.
                CelsiusToFahrenheitResponse c=(CelsiusToFahrenheitResponse)webServiceTemplate.marshalSendAndReceive(celsiusToFahrenheit,new WebServiceMessageCallback() {

     // Setting the SOAP Action
        public void doWithMessage(WebServiceMessage message) {
            ((SoapMessage)message).setSoapAction("http://tempuri.org/CelsiusToFahrenheit");
        }
    });


               System.out.println("THE RESPONSE From Web Service IS "+ c.getResult());

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

}
The code is pretty self explanatory, except at one point where we need to cast the object to our corresponding response, as the web service template does not provide any way to specify in the parameter list about the kind of response object we are expecting to receive.

Once it gets executed we will receive the result on to our console.
Someetimes our web servie is accessible only through HTTPS protocol, however the tried to just replace the URI Of my web services template, and it seems to work without any added configurtion. It might be possible that we need to install the certificate on our system either manually or through a software called PORTECLE.
So that's all for the time.
 In the next part we will see how to create a web service through spring ws 2 and implement the same endpoint for both SOAP 1.1 & SOAP 1.2 i.e. we will not bother about whether client is invoking through text/xml or application/soap+xml (SOAP 1.2). Really Spring WS makes it so easy.
 Thanks Arjen Postuma.


7 comments:

  1. I need to create a web service through spring ws with both SOAP 1.1 and 1.2 bindings. You mentioned that, will be posting the same later. Can you please let me know your plans? Otherwise if you can provide some inputs on how to achieve this?

    thanks
    Ravi

    ReplyDelete
  2. hi Ravi,
    Apologies, for not updating the series with 3 (last) part, i will be able to post it by Saturday evening by 5PM IST.

    ReplyDelete
  3. It's there .......Adam and Anish..

    ReplyDelete
  4. If you see following error: http://springwstemplatejax2bxmlrootmissing.blogspot.com/ while spring WebService Template, try this out: http://springwstemplatejax2bxmlrootmissing.blogspot.com/

    ReplyDelete
  5. Thanks!! I am new to Spring, Java Web Services and XML Marshalling, etc. Almost every tutorial out there - including most of the books I've bought! - assume that you already know how to do this stuff and give overly complex examples...many including maven plugins to build code, etc.

    While I appreciate those kinds of examples, before I turn it over to a blackbox process I like to understand how it works and how to tweak it.

    Your examples are clear, concise, and to the point. No fluff. This is great stuff!!

    ReplyDelete
    Replies
    1. Thanks Roger. Gud to see it is helpful for you.

      Delete