Tuesday, May 15, 2012

Spring MVC - REST ( JSON/XML) - Configuration



This post is an compilation of the problems that i have faced while configuring an Spring MVC Application that will acts as an API server providing all the services in an REST based manner.
It is an simple task to configure the whole environment and to make services available. However i have faced the following set of problems, which are little different in nature->

  1. Use JAXB annotations for the keys of the JSON that is being returned from the server (by default the JACKSON processor will take the variables names and will associate them as the keys in the returned JSON.
  2. Use same keys (in json) / tags (in xml) to receive the request (in POST/PUT).
  3. Apply Hibernate Validator by making use of Spring validation.
Guys at VMWare spring has done a fabulous jobs and all of the above mentioned requirements will be collated into a single line of XML that you need to declared in your dispatcher-servlet.xml (or any of the other spring application context file you are importing to build your app context
).
&
lt;mvc:annotation-driven/>
This line does a number of things
  1. Automatically add all types of interceptors like XML Based interceptors, String, Form based interceptors.
  2. Will provide automatic marshalling of your response/value object in XML/JSON
  3. Will provide the validation of your request VO, if you have enabled the @ExceptionHandler annotation on some method in your controller.
The problem that i had faced is that i could not be able to use my JAXB annotations as the KEYS in my request/response, because when i declared a different Jackson processor and added it to the AnnotationHandlerAdapter provided by spring, it is being ignored brutally by Spring under the wraps. And the one defined by the <mvc:annotation-driven/> one will take priority. As soon as the remove this annotation to make my JSON (with jaxb annotations you required another library JACKSON-XC.jar) the validation thing ceases to stopped. This all forces me to look onto the varous JIRA bugs raised against this annotation and finally i will be able to solve the problem with the help of Spring 3.1.

Note:- In case you are using spring 3.0 jar, please replace them with Spring 3.1 jar and use 3.1.xsd everywhere in your application context xml files (because the configuration which is represented below will only work it the XSD of 3.1 is being used as 3.0 does not allow any attribute and sub-element within the <mvc:annotation-driven/> option.
Following is the configuration which will allow use to solve the above three problems.
(Please make sure before running the code you must have all the bindings and jar files available in your classpath, Here is a brief listing of those.
-> For Validation: Hibernate-validator 4.2.0.Final.jar, javax.validation.api (JSR 303)
-> For Jackson : Jackson-core.jar, jackson-mapper-asl.jar, jacakson-xc.1.7.5.jar
-> For JaxB -> Jaxb API and Impl . jar

Configuration code:



 
 
 
 
   
   
 
    
  
  
    
  
   
    
    com.mycompany..CreateEmployeeRequestVO
    com.mycompany..CreateEmployeeResponseVO
   
  
  
     

 
 
      


  
  
   
     
      
     
      
       
        
        
        
       
      
     
   
   
    
    
     
      
       
       
       
                                               
     
    
   
   
  


NOTE: Please note that in above xml the last line has only one </beans> and nothing else. The three </bean> is being printed wrongly by the javascript library, i am using.

Here is the description of the components of XML file

  • Line 1-5 simply declares the XML namespaces and the various XSD files we are going to use.
  • Line 10-15 will register the JAXB Annotation Introspecter and associate itself with the ObjectMapper of the jackson library. (Many of the blogs will show directly mapping this to annotationIntrospector property of the objectmapper, but it has been changed, with the introduction of new API, now the annotationIntrospector is present in the serializationConfig and deserializationConfig object of the Object Mapper). This is the key to use JAXB annotations in the JSON Processing.
  • Line 18-27 registers the JAXB2 Marshaller taken from the OXM Library. here we can register the varous classes that we have to use either for taking the input or in generating the output i.e. RequestValueObject and ResponseValueObject. However, i found that there is no way through which you can give directly a packagename or a list of packages. The Other option that we have is to use eitehr the contextPath property or the jaxb.index thing.
  • LIne 31-32 will intialize the Spring Validator and the conversion service factory bean, which will automatically going to use the hibernate validator present on the classpath. The advantage of using hibernate validator is that the availablity of extra custom annotations like NotEmpty etc. It provides an way through which we can remove the annotations from our value objeect and place at in an XML file and at run time, the validator picks that file to perform the listed constraints on the various attributes of the request Value object.
  • Line 34-62 is the meat of the whole subject and contains all the necesseary plumbing to make the things work. (Note: for this to work we must have to include Spring 3.1 xsd otherwise Spring will throw an error that no element or attribute will be alloweed with ). IT does two things:
    • Registeres the custom XML marshaller converter with the automatically registered AnnotationHandlerAdapter by replacing the existing default converter.
    • Registers the custom JSON mapping converter, where we are using new created jacksonObjectMapper rather then the one which is avaiable by default. This also will displace the default registered converter with AnnotationHandlerAdapter with this one.
And that's all. Voila.. all of our test cases are running and our JSON/XML are being generated/consumed properly. In order to achieve this, i had taken help from various links, which i had mentioned below. And at last thanks to Juergen Holler and the team for the clear explanation on the JIRA.

https://jira.springsource.org/browse/SPR-6306
https://jira.springsource.org/browse/SPR-7504
https://jira.springsource.org/browse/SPR-7967
https://jira.springsource.org/browse/SPR-6817
https://jira.springsource.org/browse/SPR-6524

http://www.aviyehuda.com/2010/04/using-hibernate-validator-to-cover-your-validation-needs/
http://java.dzone.com/articles/using-hibernate-validator
http://stackoverflow.com/questions/8679122/custom-httpmessageconverters-does-not-take-precedence-for-string-objects-in-spri
http://stackoverflow.com/questions/7199652/mvcannotation-driven-with-un-annotated-controllers
http://forum.springsource.org/showthread.php?106594-complete-XML-for-mimicing-annotation-driven
http://stackoverflow.com/questions/6177913/configuring-the-jacksonobjectmapper-not-working-in-spring-mvc-3
http://scottfrederick.blogspot.in/2011/03/customizing-spring-3-mvcannotation.html
http://stackoverflow.com/questions/3693397/howto-get-rid-of-mvcannotation-driven
http://forum.springsource.org/showthread.php?101450-lt-mvc-annotation-driven-gt-issues

I hope, it will prove useful for the developer community.







Thursday, July 28, 2011

MySql - ( Tomcat, Spring, C3P0) - Communication Link Failure Error & Explanation

This blog explains the famous mysql “communication Link Failure” error, and provide the working example of the code that works finally. The blog post is just a result of the all ideas & findings that I went through while looking the cause for this error on blogosphere and documentation. I have applied many techniques that are being mentioned, however none of the approach works finally and some R&D has resulted in the successfully behavior, as required.

Environment & Softwares:
Windows XP, Apache Tomcat 6.0.32, Spring 3.0.3, Hibernate 3.5, C3p0-0.9.11, MySql 5
Error:
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
Last packet sent to the server was 0 ms ago.

Reason: The error comes because the connections in our connection pool goes stale and mysql removes the connection also from his own internal pool through a thread which get invokes after WAIT_TIMEOUT as being configured in the MySQL Server.

Example: Suppose our web based application is being configured to take a fixed number of connections from the database at the start of the application, however as we progress through time and reached a limit where a connection in the pool has not been used more than WAIT TIMEOUT configured in the mysql server. If we hit any SQL/HQL statement through that pool, we are going to get the above error with a message “Last packet was sent to the server was x ms ago”.

Properties involed: Solution of the above problem will involve only three properties one on mysql side and two on the coding side (configured through application-dao.xml).

WAIT_TIMOUT (on mysql side, this can easily be configured through the mysql administrator and should be around 10 minutes, by default the value is 28800 which is very high, because the stale connection can remain in mysql pool for 8 hours). For Testing I reduced it to 30 seconds.
IDLECONNECTIONTESTPERIOD: This property of C3p0 specifies the after how much time the library should check for the validity of the connection in connection pool. This should be set less then the wait_timeout period configured above. For testing I set it to 20 seconds
MAXIDLETIME: This C3p0 property signifies how long an idle connection can remain in the pool. For testing I set it to 25 seconds.

NOTE: we always have to remember that the value of idleTestConnectionTestPeriod should be less then that of maxIdleTime and the value of both of these properties should be less than that of wait_timeout as being configured on the DB server.

However, while configuring the datasource  (C3P0 datasource) through the spring property files, we have to make sure, that we are setting these properties in C3p0 datasource and not in the session factory. The reason is plain simple unless you are using hibernate-c3p0 (check out for correct version of C3p0 for a specific Hibernate version) Provider, it is not going to work. For this you need to set the following property in the session factory “properties” attribute.
hibernate.connection.provider_class = org.hibernate.connection.C3P0ConnectionProvider
I tried to set this provider, however hibernate is not picking this up and still the internal Spring/Hibernate connection provider is being used instead of C3p0 provider. So have to drop this.

here is the final datasource configuration:

        
            com.mysql.jdbc.Driver
        
        
            jdbc:mysql://192.168.1.1:3306/testDB?autoReconnect=true
        
        
            
                root</beans:prop>
                <beans:prop key="password">mysqlpassword
            
        
        
            20
        
        
            25
        
    

In session factory you can set a number of attributes and verify whether these are being set or not by just going through the JConsole ( actually this solves my error, since I can check whether the properties are actually being set or not, in my case previously I am setting them in sessionFactory and assuming they will be used, however jConsole tell me that the ComboPooldataSource properties are not the same one as I specified in the xml file, that prompt me to set them in the ComboPooldataSource instead of specifying in the sessionFactory)


Here is the Configuration for hibernate SessionFactory:

        
            
 

            
 org.hibernate.dialect.MySQL5InnoDBDialect
true
                 
                10
                20
                20
                25
                10
                2
                true   
               select 1;
  
 




Test results: so finally when I set the above properties (remember properties defined in sessionFactory does not work for me because I don’t have the extra jar hibernate-c3p0.jar of 6KB and using it does not worked also).
Wait_timeout: 30
idleConnectionTestPeriod: 20
maxIdleTime: 25
If I hit the database now after a period of 30 seconds I never got the error “Communication Failure” because internally C3p0 verifies the validity of every connection in 20 seconds & if a connection lies unused or unchecked ie. Remain idle for 25 seconds, it will die out automatically. Thus I got my problem solved finally.
If you have to use the set of attributes in session factory instead of defining like this in ComboPoolDataSource please see the documentation of C3P0 and the associate hibernate property. Make sure you are associating every c3p0 property with “connection” or “hibernate” keywords as per the documentation, else see the JConsole to check whether you are able to set the property or not.




Here is a list of blogs that proved useful while searching for the solution of the problem and different things worked for different geeks.




Tuesday, July 5, 2011

NetBeans SpringMVC (REST) Project Junit testing: Errors & Resolutions

This blog is a consolidated view of the problems that are being faced while executing JUNIT based test cases for a  Spring MVC based web project in Netbeans.
The project environment is:
1. NetBeans 6.9
2. JDK 6u13
3. Tomcat 6.0.32
4. Windows XP



Problems faced while executing Junit test cases:
1. Memory problems while executing test cases
2. A number of properties are being exposed with the help of catalina.properties like the proxy username and password need not to be hardcoded in the applicationcontext files & a number of different properties files (like cache.properties, dbdetails.properties)



The test package "Test Packages" contains all the Junit test cases. 




An Example of a single test case is
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
{
        "classpath*:/web/WEB-INF/applicationContext.xml",
        "classpath*:/web/WEB-INF/dispatcher-servlet.xml"
}) 
public class DaoTest {  
// JUNIT Specific Code
}
Since our project requires a number of properties file that are being configured through catalina.properties like logback configuration file path, dbdetails properties file path etc. (since we are loading all the properties defined in all of these properties file through Spring PropertyPlaceHolderConfigurer) which is provided automatically at runtime while running the application under TOMCAT, here the challenge is to provide all those properties through an external medium to the spring junit runner, so that the Spring application context is being initialized successfully.


For This Go to NetBeans menu: 
a. Tools -> Options  -> ANT Tab
b. Look for the properties at the bottom of the window.



For each of the properties that you have externalize by making use of catalina.properties we need to enter a line here in the PROPERTIES box.
E.g. Suppose we have a propery named “https.proxyPort” defined in the catalina.properties then we need to define a property here also, however we need to keep in mind that each property needs to be prepended by “test-sys-prop.”



      So the final property is test-sys-prop.https.proxyPort=1971 as shown in above diagram.
Similarly if we have externalize the Log4j property file it will be
test-sys-prop.logback.configurationFile=file\:///c\:/logback.xml
NOTE:
The “\” entered above is automatically added by netbeans we just need to add the following.
test-sys-prop.logback.configurationFile=file:///c:/logback.xml



Now Click on “OK” and netbeans will start building the indices for internal purposes.
Start Running your Junit Test Cases and Spring will initialize properly as in the TOMCAT.  And we can get access to all our beans by using @Autowired annotation in the test Cases.



Memory Problem:
Now if we are doing some memory intensive work, we need to provide netbeans with the –Xms and –Xmx runtime arguments. Otherwise we will keep on getting OutofMemoryError : heap space. To remove this:
Right Click on the project -> Properties -> Run


Place the –Xms & -Xmx parameter as per your requirements.

Hope it helps you to do the UNIT Testing in NetBeans. For this blog, I have taken help of a number of blogs,the main one is :http://forums.netbeans.org/post-294.html

Wednesday, April 6, 2011

Spring Web Service - Part III ( Creating Web Services by java bean both for SOAP 1.1 & SOAP 1.2)

In the Last part of the servies, we will learn how to Develop web services that will support both SOAP 1.1 and SOAP 1.2 protocol, (Spring WS does not provide out of box support for this and we need to tweak the things little bit).
There are many ways through which you can generate the Web services, like
  • Manually creating the WSDL file and place it in WEB-INF directory of your web application.
  • Creating the Request XML XSD and let the framework to create the WSDL
The Second one is preferred approach as compared to the first one, as you does not have to code the WSDL directly either with tool or yourself. 
In order to create the following tutorial, i had taken help from a number of blogs, following are the their links, however I could not find a complete one, so summarizing all this in a single post.
Listed here are the steps:
  1. First we will create a xsd which represents the schema of the input xml, below is a snipped of it,  It only contains three fields that need to be passed to the Server, ( ID, Name, Email) and in response two things are being returned to the client ( CODE, DESCRIPTION)
    
    
        
            
                
                    
                    
                    
                
            
        
    
     
            
                
                    
                    
                    
                
            
        
    
        
            
                
                 
                 
                
            
        
    
        
            
                
                     
                     
                
            
        
    
        
            
                
                
            
        
    
        
      
       
        
        
        
       
      
        
    
        
         
       
        
        
       
      
        
    
    
    
    it Clearly Shows that the contents of Subscription Request and Subscription Response, as described above.
  2. Now we need to create the Java Objects corresponds to both Request and Response.
    SubscriptionRequest.java

    package com.test;
    
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    /**
     *
     * @author PankajB
     */
    @XmlRootElement(namespace="http://krams915.blogspot.com/ws/schema/oss",name="subscriptionRequest")
    public class SubscriptionRequest {
    
     private String id;
     private String name;
     private String email;
    
       @XmlElement(name="email",namespace="http://krams915.blogspot.com/ws/schema/oss")
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
       @XmlElement(name="id",namespace="http://krams915.blogspot.com/ws/schema/oss")
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        @XmlElement(name="name",namespace="http://krams915.blogspot.com/ws/schema/oss")
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    
    }
    
     SubscriptionResponse.java
    package com.test;
    
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    /**
     *
     * @author PankajB
     */
    @XmlRootElement(namespace = "http://krams915.blogspot.com/ws/schema/oss", name = "subscriptionResponse")
    public class SubscriptionResponse {
    
        private String code;
        private String description;
    
        @XmlElement(name = "code", namespace = "http://krams915.blogspot.com/ws/schema/oss")
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        @XmlElement(name = "description", namespace = "http://krams915.blogspot.com/ws/schema/oss")
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    }
    
    

  3. Now we need to write our main POJO which which handle the request and generate a response. It pretty simply class, annotated with some special annotations.
    package com.test;
    
    import javax.xml.ws.soap.SOAPBinding;
    import org.springframework.ws.server.endpoint.annotation.Endpoint;
    import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
    import org.springframework.ws.server.endpoint.annotation.RequestPayload;
    import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
    
    /**
     *
     * @author PankajB
     */
    @Endpoint(value = SOAPBinding.SOAP12HTTP_BINDING)
    public class SubscriptionService {
    
        @PayloadRoot(localPart = "subscriptionRequest", namespace = "http://krams915.blogspot.com/ws/schema/oss")
        @ResponsePayload
        public SubscriptionResponse processSubscription(@RequestPayload SubscriptionRequest subscriptionRequest) {
    
    
            SubscriptionResponse response = new SubscriptionResponse();
            System.out.println("Coming Here.........  " + subscriptionRequest.getName());
            response.setCode("234");
            response.setCode("Successfully Executed the application.");
    
            return response;
    
        }
    }
    
    
    here it simply, receive the Payload ( what is being sent by the client in the XML and converted to our SubscriptionRequest Object and generates an SubscriptionResponse type of object, which will again be automatically going to be converted by the Spring Jaxb marshaller in the XML format.
    This Ends the first part of the story, now let's move to the configuration.
  4. First of all in the configuration files, let's visit web.xml
    
        
            spring-ws
            org.springframework.ws.transport.http.MessageDispatcherServlet
            
                transformWsdlLocationstrue
            1
        
        
            spring-ws
            /service/*
        
        
            
                30
            
        
        
            index.jsp
        
    
    
    
    This Simply tells the container that this servlet is going to receive any of the call that matches with the URI /service/*

  5. Now we have the spring-ws-servlet.xml (spring-ws comes from servlet name above in web.xml) which will define all the components related to Spring Web Service.
    
        
        
        
       
            
         
        
        
        
        
        
            
      
        
            
                
                    com.test.SubscriptionRequest
                    com.test.SubscriptionResponse
    
                
            
            
                
                    
                
            
        
    
        
            
        
    
     
        
    
     
        
            
            
        
    
     
        
                
        
       
    
    

    Most of the Things has been commenting in the XML itself, for better understanding.

  6. Since we need to support both SOAP 1.1 & SOAP 1.2 we need to write out own factory, that is going to be an implementation of SoapMessageFactory.
    /*
     *
     * This All has been done as per the things present at this link.
     * http://forum.springsource.org/showthread.php?t=56560
     *
     */
    
    package com.test.soap;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.ws.WebServiceMessage;
    import org.springframework.ws.soap.SoapMessage;
    import org.springframework.ws.soap.SoapMessageFactory;
    import org.springframework.ws.soap.SoapVersion;
    import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
    import org.springframework.ws.transport.TransportInputStream;
    
    public class MyFactory implements SoapMessageFactory, InitializingBean {
            // This is the Request Context Attribute.
     private static final String REQUEST_CONTEXT_ATTRIBUTE = "MyFactory";
    
     private static final Log logger = LogFactory.getLog(MyFactory.class);
    
            // Two message factories for processing two differnet types of protocols.
     private SaajSoapMessageFactory soap11MessageFactory = new SaajSoapMessageFactory();
     private SaajSoapMessageFactory soap12MessageFactory = new SaajSoapMessageFactory();
    
            // This Object, will be responsible for choosing the Protocol on Runtime, it can be application/xml or text/xml (SOAP 1.2 & SOAP 1.1)
     private SoapProtocolChooser soapProtocolChooser = new MySoapProtocolChooser();
    
     private void setMessageFactoryForRequestContext(SaajSoapMessageFactory mf) {
      RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
      attrs.setAttribute(REQUEST_CONTEXT_ATTRIBUTE, mf, RequestAttributes.SCOPE_REQUEST);
     }
    
     private SaajSoapMessageFactory getMessageFactoryForRequestContext() {
      RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
      SaajSoapMessageFactory mf = (SaajSoapMessageFactory) attrs.getAttribute(REQUEST_CONTEXT_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
      return mf;
     }
    
            // Function called, when we are settign the SOPA Version
     public void setSoapVersion(SoapVersion version) {
                System.out.println("setSoapVersion called with: " + version + " -- ignoring");
     }
    
            // This Function, will set teh SOAP Proptocl chooser
     public void setSoapProtocolChooser(SoapProtocolChooser soapProtocolChooser) {
                System.out.println("Setting out the SOAP Protocol Chooser");
      this.soapProtocolChooser = soapProtocolChooser;
     }
    
            // Function will be invoked, when Spring will create the Bean.
     public void afterPropertiesSet() throws Exception {
      soap11MessageFactory.setSoapVersion(SoapVersion.SOAP_11);
      soap11MessageFactory.afterPropertiesSet();
      soap12MessageFactory.setSoapVersion(SoapVersion.SOAP_12);
      soap12MessageFactory.afterPropertiesSet();
                    System.out.println("Setting both the SOAP Version to 1.1 and 1.2");
     }
    
    
        // Function for creating the Web Service Message.
        public SoapMessage createWebServiceMessage() {
            return getMessageFactoryForRequestContext().createWebServiceMessage();
        }
    
        // Function for creating the Web Service Message from inputStream. 
        public SoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
            setMessageFactoryForRequestContext(soap12MessageFactory);
      if (inputStream instanceof TransportInputStream) {
                TransportInputStream transportInputStream = (TransportInputStream) inputStream;
             if (soapProtocolChooser.useSoap11(transportInputStream)) {
              setMessageFactoryForRequestContext(soap11MessageFactory);
             }
            }
      SaajSoapMessageFactory mf = getMessageFactoryForRequestContext();
      if (mf == soap11MessageFactory) {
       System.out.println("Final soapMessageFactory? " + soap11MessageFactory);
      } else {
       System.out.println("Final soapMessageFactory? " + soap12MessageFactory);
      }
      return mf.createWebServiceMessage(inputStream);
        }
    
        
    }
    
    This class is not alone itself, and works with the help of some associating classes & interfaces described below.
    SoapProtocolChooser.java Interface: This is the Interface that is being defined for Choosing a SOAP Protocol chooser class at run time.
    package com.test.soap;
    
    import java.io.IOException;
    
    import org.springframework.ws.transport.TransportInputStream;
    
    public interface SoapProtocolChooser {
     public boolean useSoap11(TransportInputStream transportInputStream) throws IOException;
    }
    
    MySoapProtocolChooser.java Implementation of Above Defined Interface:
    /**
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package com.test.soap;
    
    /**
     *
     * @author PankajB
     */
    import java.io.IOException;
    import java.util.Iterator;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.ws.transport.TransportInputStream;
    
    public class MySoapProtocolChooser implements SoapProtocolChooser {
    
        private static final Log logger = LogFactory.getLog(MySoapProtocolChooser.class);
        private static final Pattern userAgentPattern = Pattern.compile("html", Pattern.CASE_INSENSITIVE);
    
        public boolean useSoap11(TransportInputStream transportInputStream) throws IOException {
            for (Iterator headerNames = transportInputStream.getHeaderNames(); headerNames.hasNext();) {
                String headerName = (String) headerNames.next();
                logger.debug("found headerName: " + headerName);
                for (Iterator headerValues = transportInputStream.getHeaders(headerName); headerValues.hasNext();) {
                    String headerValue = (String) headerValues.next();
                    logger.debug("     headerValue? " + headerValue);
                    // Something weird with case names
                  /*  if (headerName.toLowerCase().contains("user-agent")) {
                    System.out.println("UserAgent  - " + headerValue);
                    Matcher m = userAgentPattern.matcher(headerValue);
                    if (m.find()) {
                    logger.debug("Found AXIS in header.  Using SOAP 1.1");
                    return true;
                    }
                    }*/
                    // This is the code written in order to support multiple Endpints by selection of SOAP
                    if (headerName.toLowerCase().contains("content-type")) {
                        logger.debug("Content Type  - " + headerValue);
    
                        if (headerValue.trim().toLowerCase().contains("text/xml")) {
                            logger.debug("Found text/xml in header.  Using SOAP 1.1");
                            return true;
                        }
    
                    }
                }
            }
            return false;
        }
    }
    
    
    The Above code is pretty self explanatory.
    This Class is being invoked by MyFactory class in method createWebServiceMessage(InputStream) to determine which SOAP Message Factory is going to be used, either 1.1 or 1.2
That's all we required, now we can simply deploy our application to the web container after creating a WAR file.
Now simply call the HTTP URI: http://localhost:8080/SpringWSGen/service/service/SubService/subscription.wsdl
( Note: service has been writted two times because:
      1. we have service/* servlet mapping, so first one belongs to it.
      2. we have service/SubService in the dynamic WSDL generation tag in sprng-ws-servlet.xml, so second one refers to it. Obviously one can go ahead with any mappings he want )
you will see the following WSDL Generated. now it can be invoked in any tool example SOAP UI to get to know which one is being called. As the WSDL File has the bindings for both the SOAP 1.1 & SOAP 1.2

  So that's all for the time beings. here can you create Spring Web Services through this. I will have some interesting URL's thta just add to the above functionaltiy, that i will add later on.
Thanks Spring, for creating such a light weight framework.
Please let me know, in case you want the complete source code. I will host it somewhere.

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.


Tuesday, March 1, 2011

Spring Web Services 2 - Part I

This is an introductory article, in a three part series which illustrates the use of Spring Web Services in a Java/J2EE Application.
All the Examples has been created by using Spring 3, Spring Web Services 2, JAX-WS, JAXB 2.2, and wsdl4j.jar

This Part will simplify the process of invoking a simple web service located at w3schools.com ( to convert a temperature from Celsius to Fahrenheit ).
Web Service URL is : http://www.w3schools.com/webservices/tempconvert.asmx 
WSDL is : http://www.w3schools.com/webservices/tempconvert.asmx?wsdl

Note: Please use SOAP UI, an excellent tool for testing the web services.

So as per Spring WS Configuration, we will create a WebServiceTemplate which follows the same pattern as of JDBCTemplate, RestTemplate etc
So our application context (ac.xml) file in this case is:



    
    
    
     
     
        
        
       
    



Now we have to construct two Classes:
1. This Class will represent the java representation of the SOAP REQUEST BODY with all the tags defined through JAXB 2.2 framework. CelsiusToFahrenheit.java 

package springws;

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

/**
 *
 * @author PankajB
 * namespace represent the namespace of the elements, plz see wsdl for greater information
 * CelsiusToFahrenheit is the Root Element name
 */
@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;
    }
}




2. This class will represent the response that is coming from the Web service. CelsiusToFahrenheitResponse.java


package springws;

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;


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

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



Now the Final Part will be is to load the xml file and perform the invocation. The Source Code is easy to read, hence does not contain much comments (Sorry for this guys!!!)

Main.java
package springws;

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
        {
   // getting the file present in springws package
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springws/ac.xml");
  // get the Bean
        WebServiceTemplate webServiceTemplate = (WebServiceTemplate)applicationContext.getBean("webServiceTemplate"); 
  // Create the Marshaller, so that we can generate the request SOAP Body XMl
        JAXBContext jc= JAXBContext.newInstance(CelsiusToFahrenheit.class);
        Marshaller m=jc.createMarshaller();
  // Creating the Request Object
        CelsiusToFahrenheit celsiusToFahrenheit=new CelsiusToFahrenheit();
        celsiusToFahrenheit.setCelsius(10);
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);

        StringWriter wr=new StringWriter();
  // Marshalling the object to the writer
        m.marshal(celsiusToFahrenheit, wr);
        System.out.println(wr.toString());
        StringWriter finalResponseWriter = new StringWriter();
  // Creating the Source and Result object, that will contain the corressponding REUQEST & RESPONSE.
        StreamSource webServiceInput = new StreamSource(new StringReader(wr.toString()));
        StreamResult webServiceOutput = new StreamResult(finalResponseWriter);
  // Invoking the Web Service
        webServiceTemplate.sendSourceAndReceiveToResult(webServiceInput,new WebServiceMessageCallback() {

         // This is very much required, since we need to set the ACTION as defined in the WSDL. ( Since a web service can contain multiple options
        public void doWithMessage(WebServiceMessage message) {
   // Please see the WSDL for more details.
            ((SoapMessage)message).setSoapAction("http://tempuri.org/CelsiusToFahrenheit");
        }
    }, webServiceOutput);
 // This line, will print the Response to the Console
            System.out.println(finalResponseWriter.toString());
          
   // This will simply unmarshal the xml response in the Java Object (for easy handling of response)
            JAXBContext jaxc=JAXBContext.newInstance(CelsiusToFahrenheitResponse.class);
            CelsiusToFahrenheitResponse tr=(CelsiusToFahrenheitResponse)jaxc.createUnmarshaller().unmarshal(new StringReader(finalResponseWriter.toString()));
            System.out.println(tr.getResult()  + "  is the result");
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }

}
Once the following will be executed, we will see the response on our console.

In the next two parts we will see the following:
Part 2: Making use of JAXB Marshalling & UnMarshalling to automate the above manual marshalling through coding.
Part 3: How to create a web service through Spring WS and provide a simple end point to support both SOAP 1.1 & SOAP 1.2
So, stay tuned.