Friday, May 29, 2015

Creating Soap based Webservice Client using Spring-WS

Creating a Simple Web Service Client with JAX-WS using Spring WS

SOAP Web Services provide a platform agnostic integration mechanism that allows disparate systems to exchange data regardless of the platform they are running on. For example, SOAP web services are commonly used to integrate .NET applications with applications running on the Java platform. Almost all modern platforms and frameworks (Java, .Net, Ruby, PHP, etc)  

  This section shows how to build and deploy a simple web service client.

Communication between a JAX-WS Web Service and a Client

Diagram showing a client and web service communicating through a SOAP message.
                                                                                                                                                                                           
Spring Web Services aims to facilitate contract-first SOAP service development, allowing for the creation of flexible web services using one of the many ways to manipulate XML payloads. The product is based on Spring itself, which means you can use the Spring concepts such as dependency injection as an integral part of your Web service.

As the best way to define the data contract is xml schema hence we would consider that we have XSD provided with us and if not we can create an XSD from the sample documents conforming the requirements specs. Any good XML editor or Java IDE offers this functionality. Basically, these tools use some sample XML documents, and generate a schema from it that validates them all. The end result certainly needs to be polished up, but it's a great starting point. 

Consider we have the XSD with us, then we would need following:
  • Generate the WSDL from the xsd provided
  • Generate domain objects based on a WSDL (Considering WSDL is available else one needs to have a XSD shared by the WebService Producer)
  • Spring configuration - To inject WebServiceTemplate into the client class.
  • An implementation class - This class will be actually the webservice client
  • Calling the Web Service client 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1. Generating WSDL from the supplied XSD:
    
    a. We can use Spring to help us generate wsdl - we can configure spring-ws-servlet.xml in our Spring based web application we can have below "WSDL - Generator code"

<!-- WSDL Generator -->

    <bean id="anyservices"
        class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
        <property name="createSoap12Binding" value="true" />
        <property name="schema">
            <bean class="org.springframework.xml.xsd.SimpleXsdSchema" p:xsd="classpath:ANY_XXX_XX.xsd"/>
        </property>
        <property name="portTypeName" value="ackEventPort" />
        <property name="locationUri"
            value="https://anyendpoint.domain.com:1234/ANY/AnyContext" />
    </bean>
   
    <sws:dynamic-wsdl id="anyservices"  portTypeName="ackEventPort" locationUri="/">
              <sws:xsd location="classpath:ANY_XXX_XX.xsd"/>
    </sws:dynamic-wsdl> 


b. Deploying the Spring Web App on any web container (I have used Tomcat 6)
following URL will generate the WSDL for you, consider the bean id as context (anyServices) and dynamic wsdl id as wsdl name anyservices.wsdl :
 
http://localhost:8080/ApplicationWAR/anyService/anyservices.wsdl




++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
If you want to validate the request / response against schema (xsd) , you can add the below in the spring ws servlet xml.

<!-- Schema validation -->
<bean id="validatingInterceptor"
   class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
            <property name="schemas">
                  <value>classpath:
ANY_XXX_XX.xsd</value>              
            </property>
            <property name="validateRequest" value="true" />
            <property name="validateResponse" value="true" />
        </bean>

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 If we want to set the properties or as in read values from the properties file for some parameters we can set as below in the same spring ws servlet .xml file

<!-- @Start : Property Mappings for Application -->
    <bean id="account-property-mappings"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="properties" ref="account-configuration" />
    </bean>
    <!-- Composite configuration -->
    <bean id="account-configuration"
        class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
        <property name="configurations">
            <list>               
                <!-- pick from classpath -->
                <bean id="applicationProperties"
                    class="org.apache.commons.configuration.PropertiesConfiguration">
                    <constructor-arg type="java.io.File"
                        value="classpath:webservices.properties" />
                </bean>

                <!-- The db -->

<bean id="ackdatabaseConfiguration"                                                      class="org.apache.commons.configuration.DatabaseConfiguration">
                     <constructor-arg type="javax.sql.DataSource" ref="dataSource"/>
                     <constructor-arg index="1" value="PROPERTY"/>
                     <constructor-arg index="2" value="NAME"/>
                     <constructor-arg index="3" value="VALUE"/>
                 </bean>
            </list>
        </property>
    </bean>


 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2. Generating the Domain Objects from the WSDL generated from above step:

We can use wsimport utility of your JDK installed on your system and we have below command which will also generate the .java files at prescribed location::
 
wsimport -keep -s C:\SoapTestWSServiceSample\SVN_1.2\ApplicationsWAR\src -p org.utkarsh.ws.jaxb.generated C:\WSDLSample\TestWebService\accountservices.wsdl

This command will be generating the required domain objects which will then be used as a client to consume the web-service exposed and defined under the contract via .wsdl / .xsd file.
 


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3. Writing the Implementation Service Client :

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ws.client.core.WebServiceTemplate;
import com.pnc.lon.app.exception.WebServiceException;

@Service("wsClientServiceImpl")
public class WSClientServiceImpl {
   
    private static XLogger log = XLoggerFactory.getXLogger(WSClientServiceImpl.class);   
   
    @Autowired
    private WebServiceTemplate webServiceTemplateV2;
   
    public AnyModel validateAnyRequest(AnyModel anyModel) throws WebServiceException {
        ValidateAnyResponse validateAnyResponse =  null;
         try{
                validateAnyResponse = (ValidateAnyResponse) webServiceTemplateV2.marshalSendAndReceive(convertValidateAccountRequest("11456",anyModel));
               
                if(validateAnyResponse == null){
                    log.error("No Data found. Reponse is null");
                    return null;
                }
                //If response status is error, then throw WebServiceException
                    if(validateAnyResponse != null && (ApplicationConstants.ER.equals(validateAnyResponse.getResult().getStatus().toUpperCase()))){
                        //throw the exception to UI layer
                        WebServiceException wsException = new WebServiceException(validateAnyResponse.getResult().getStatus());
                        throw wsException;
                    }       
                           
            } catch (Exception e) {
                log.error("Exception thrown while calling validateAnyRequest() web service for MessageID : " + messageId + " : " + e.toString());
                WebServiceException wsException = new WebServiceException(e.getMessage() + "for MessageID : " + messageId);
                throw wsException;
            }
       
        return convertValidateAnyResponse(validateAnyResponse);
    }



    private ValidateAnyRequest convertValidateAccountRequest(String messageId,AnyModel anyModel) {
       
        ValidateAnyRequest validateAnyRequest = new ValidateAnyRequest();
       
        validateAnyRequest.setAccountCurrency(anyModel.getCurrency());
        validateAnyRequest.setAccountName(anyModel.getAccountName());
        validateAnyRequest.setAccountNumber(anyModel.getAccountNumber());
       
        return validateAnyRequest;
    }
   
    private AnyModel convertValidateResponse(ValidateAnyResponse response) {
        AnyModel anyModel =  new AnyModel();
       
        anyModel.setName(response.getAccountName());
        anyModel.setNumber(response.getAccountNumber());
       
        return anyModel;
    }

+++++++++++++++++++++++++++++++++++++++++++++++++++++++
The Spring documentation requires the client class to extend org.springframework.ws.client.core.support.WebServiceGatewaySupport, which is rather ugly. Instead, I prefer to have WebServiceTemplate injected into my client class.
 

The WebServiceTemplate bean is configured like this in the Service context or wherever you are performing the dependency injection :-
 
<!-- TEST -->
    <oxm:jaxb2-marshaller id="wsMarshallerV2" contextPath="com.pnc.lon.ws.jaxb.generated"/>
    <bean id="webServiceTemplateV2" class="org.springframework.ws.client.core.WebServiceTemplate">
        <property name="marshaller" ref="wsMarshallerV2"/>
        <property name="unmarshaller" ref="wsMarshallerV2"/>
        <property name="defaultUri" value="https://anyendpoint.domain.com:1234/ANY/AnyContext"/>
        <property name="messageSenders">
            <list>
                <ref bean="httpMsgSender"/>
            </list>
        </property>
         <property name="interceptors">
            <list>
                <ref bean="webSecurityInterceptor" />
            </list>
        </property>
    </bean>    


<!-- Configure Security as in user id password to connect to Web Service -->

<bean id="webSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
        <property name="securementMustUnderstand" value="true"/>
        <property name="securementUsernameTokenElements" value="Nonce Created"/>
        <property name="securementActions" value="UsernameToken"/>
        <property name="securementPasswordType" value="PasswordText"></property>
        <property name="securementUsername" value="serviceid"/>
        <property name="securementPassword" value="@passwdDV"/>
    </bean> 

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4. Invoking the Web Service Client :

a. Set the Request : 
           AnyModel anyModel = new AnyModel ();
             anyModel.setCurrency("USD");
             anyModel.setAccountNumber("3000003977");
             anyModel = wsClientServiceImpl.validateAnyRequest(false, anyModel) ;

             
 b. Printing any information from the response model object
            System.out.println(anyModel.getBalance());

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 



























Tuesday, May 26, 2015

How do I compare two enum in Java?

 How do I compare two enum in Java? Should I use == operator or equals() method? What is difference between comparing enum with == and equals() method are some of the tricky Java questions. Until you have solid knowledge of Enum in Java, It can be difficult to answer these question with confidence. By the way unlike comparing String in Java, you can use both == and equals() method to compare Enum, they will produce same result because equals() method of Java.lang.Enum internally uses == to compare enum in Java. Since every Enum in Java implicitly extends java.lang.Enum ,and since equals() method is declared final, there is no chance of overriding equals method in user defined enum. If you are not just checking whether two enum are equal or not, and rather interested in order of different instance of Enum, than you can use compareTo() method of enum to compare two enums. Java.lang.Enum implements Comparable interface and implements compareTo() method. Natural order of enum is defined by the order they are declared in Java code and same order is returned by ordinal() method.
 

 Comparing Enums with compareTo method
When we say comparing enum, it's not always checking if two enums are equal or not. Sometime you need to compare them for sorting or to arrange them in a particularly order. We know that we can compare objects using Comparable and Comparator in Java and enum is no different, though it provides additional convenience. Java.lang.Enum implements Comparable interface and it's compareTo() method compares only same type of enum. Also natural order of enum is the order in which they are declared in code. As shown on 10 examples of Enum in Java, same order is also maintained by ordinal() method of enum, which is used by EnumSet and EnumMap.

public final int compareTo(E o) {
        Enum other = (Enum)o;
        Enum self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
}


If you look last line, it's using ordinal to compare two enum in Java.

That's all on How to compare two enum in Java and difference between == and equals to compare two enums. Though using equals() to compare object is considered Java best practice, comparing Enum using == is better than using equals. Don't forget ordinal() and compareTo() methods, which is also key to get natural order of Enum during comparison.

Java Code to remove objects in a list iteration

// Handling removal of objects from a list using iterator,
// Removal of objects when amount is greater than balance in account

                        Iterator<Accounts> act_iterator = listAccounts.iterator();    
                        Collection<Accounts> accounts  =  null;
                        for (DueAmount dueAmt : listDueAmounts) {
                                while (act_iterator.hasNext()) {
                                   Accounts acctEnt = act_iterator.next();
                                     if (acctEnt.getAmount() < dueAmt.getAmount()) {
                                                    accounts.remove(acctEnt);
                                                }
                                 }
                        }