Thursday, 6 December 2012

Hibernate Second Level EHCache Example

Hibernate Second Level EHCache Example


In an application when the database traffic is very heavy, hibernate is well used because of its high performance. To overcome from this problem hibernate caching is the best technique. This technique is optimizing the database applications by caching the already loaded data from the database.
so the traffic between our application and the database will be reduced when the application want to access that data again.

Cache Types in Hibernate:

    First-level cache
    Second-level cache.

Hibernate Cache Implementations:

    OSCache  (Open Symphony Cache)
    EHCache  (Easy Hibernate Cache)
    JBoss TreeCache
    SwarmCache

Hibernate Caching Strategies:

    Read-only.
    Read-Write.
    Nonstriict read-write.
    Transactional.

First-level cache:-

First-level cache always associates with the Session object. Hibernate uses this cache by default. First level cache is enabled by default. Here, it processes one transaction after another one, it means it wont process one transaction many times. Mainly it is reducing the number of SQL queries it needs to generate within a given transaction i.e. instead of updating after every modification done in the transaction, it updates the transaction only at the end of the transaction. 

Second-level cache:-

Second level cache was introduced in hibernate 3.0.Second-level cache always associates with the Session Factory object. Second level cache works while running the transactions, in between it loads the objects at the Session Factory level, so that those objects will available to the entire application, don’t bounds to single user. Since the objects are already loaded in the cache, whenever an object is returned by the query, at that time no need to go for a database transaction. We can use query level cache also. 


Hibernate Cache Implementations:-

a) OSCache (Open Symphony Cache) (org.hibernate.cache.OSCacheProvider)

  1. It is a powerful .
  2. It supports read-only and read/write caching.
  3. It supports memory- based and disk-based caching.
  4. It provides basic support for clustering via either JavaGroups or JMS.

 b) EHCache (Easy Hibernate Cache) (org.hibernate.cache.EhCacheProvider)

  1. It is lightweight and that's why it is fast.
  2. It is Easy-to-use.
  3. It supports read-only and read/write caching.
  4. It supports memory-based and disk-based caching.
  5. It does not support clustering.

c) JBoss TreeCache (org.hibernate.cache.TreeCacheProvider)

  1. It is a powerful replicated and transactional cache.
  2. It is useful when we need a true transaction-capable caching architecture .

d)SwarmCache (org.hibernate.cache.SwarmCacheProvider)

  1. It is a cluster-based caching.
  2. It supports read-only or nonstrict read/write caching .
  3. It is very much appropriate for applications those have more read operations than write operations.

 

Hibernate Caching/Concurrency Strategies

A concurrency strategy is a way which is responsible for storing items of data in the cache and retrieving them from the cache.  

a) Read-only

  1. It is useful for those data which is frequently read but never updated.
  2. It is Simple.
  3. This is the best performer among the all caching strategy.
Advantage if this one is, It is safe for using in a cluster. Here is an example for using the read-only cache strategy. 





Refer the below example:- 
<class name="com.gaurav.bean.Customer" mutable="true">
<cache usage="read-only"/>
..........................
</class>

b) Read-Write

  1. It is used, when our data needs to be updated frequently.
  2. It is having more overhead than read-only caches.
  3. It is never used if serializable transaction isolation level is required.
  4. In a JTA environment, for obtaining the JTA TransactionManager we must specify the property hibernate.transaction.manager_lookup_class.
  5. To use it in a cluster the cache implementation must support locking.
Here is an example for using the read-write cache strategy.








<class name="com.gaurav.bean.Customer" .... >
<cache usage="read-write"/>
..............................
<set name="test" ... >
<cache usage="read-write"/>
................................
</set>
</class>

C) Nonstrict read-write

  1. It is needed if the application needs to update data rarely.
  2. we must specify hibernate.transaction.manager_lookup_class to use this in a JTA environment .
Here is an example for using the nonstrict read-write cache strategy.




<class name="com.gaurav.bean.Customer" .... >
<cache usage=" nonstrict-read-write"/>
...............................................
</class>

d) Transactional

  1. It supports only transactional cache providers such as JBoss TreeCache.
  2. It is only used in JTA environment.

 

Configuring Cache in Hibernate

We can use hibernate.cfg.xml file for the cache configuration. A typical configuration file is shown below. 

<hibernate-configuration>
    <session-factory>
        .............................
        <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        .............................
    </session-factory>
</hibernate-configuration>



The name in <property> tag must be hibernate.cache.provider_class or cache.provider_class for activating second-level cache. We can use hibernate.cache.use_second_level_cache property, which allows you to activate and deactivate the second-level cache. By default, the second-level cache is activated and uses the EHCache. 

Hibernate cache tag element

The <cache> element has the following attributes:




<cache
    usage=" caching strategy"
    region="RegionName"
    include="all | non-lazy"/>
  1. usage (mandatory) specifies the caching strategy: transactional, read-write, nonstrict-read-write or read-only.
  2. region (optional) specifies the name of the second level cache region .
  3. include (optional) non-lazy specifies that properties of the entity mapped with lazy=”true” may not be cached when attribute-level lazy fetching is enabled.


Hibernate queries Caching

Hibernate is providing a property through which we can cache the queries. Many times it is happening that some queries are running frequently with same parameters, we can cache those queries. Just We have to set hibernate.cache.use_query_cache to true by calling Query.setCacheable(true) for enabling the query cache.
  1.     For storing the most recent updates.
  2.     For storing the results.
Query cache always used second-level cache only. Queries wont cached by default. Below is an example implementation of query cache.

        Session session = SessionFactory.openSession();
        Query query = session.createQuery("FROM CUSTOMER");
        query.setCacheable(true);
        query.setCacheRegion("customer");
        List users = query.list();
        SessionFactory.closeSession();

Note: - This(query.setCacheRegion("customer")) code uses the method to tell Hibernate to store and look for the query in the customer area of the cache.
   

hibernate.cache.use_query_cache property We need to set in the hibernate.cfg.xml file to true like below :

<property name="hibernate.cache.use_query_cache">true</property>

Then, we can use the setCacheable() method on any query we wish to cache.

Hibernate second level cache example

Required files are as below:-
  1. Customer.java  [ Pojo class]
  2. Customer.hbm.xml
  3. ehcache.xml
  4. hibernate.cfg.xml 
  5. log4j.properties
  6. HibernateSendLevelCacheTest.java
Customer.java

package com.gaurav.bean;

public class Customer {

    private int customerId;
    private String customerName;
    private double expenditure;

    /**
     * @return the customerId
     */
    public int getCustomerId() {
        return customerId;
    }

    /**
     * @param customerId
     *            the customerId to set
     */
    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    /**
     * @return the customerName
     */
    public String getCustomerName() {
        return customerName;
    }

    /**
     * @param customerName
     *            the customerName to set
     */
    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    /**
     * @return the expenditure
     */
    public double getExpenditure() {
        return expenditure;
    }

    /**
     * @param expenditure
     *            the expenditure to set
     */
    public void setExpenditure(double expenditure) {
        this.expenditure = expenditure;
    }
}

Customer.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.gaurav.bean.Customer" table="customer">
        <cache usage="read-only" />
        <id name="customerId" column="CUSTOMER_ID" />
        <property name="customerName" column="CUSTOMER_NAME" length="50" />
        <property name="expenditure" column="TOTAL_EXPENDITURE" />
    </class>
</hibernate-mapping>

ehcache.xml

<?xml version="1.0"?>

<ehcache>
    <defaultCache maxElementsInMemory="100" eternal="false"
        timeToIdleSeconds="120" timeToLiveSeconds="200" />
    <cache name="com.gaurav.bean.Customer" maxElementsInMemory="100" eternal="false"
        timeToIdleSeconds="5" timeToLiveSeconds="200" />
</ehcache>

hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
        <property name="hibernate.connection.username">root</property>
        <property name="connection.password">root</property>
        <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <mapping resource="Customer.hbm.xml"></mapping>
    </session-factory>
</hibernate-configuration>

log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=warn, stdout
log4j.logger.org.hibernate=debug
log4j.logger.org.hibernate.type=trace

### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug






HibernateSendLevelCacheTest.java

package com.gaurav.impl.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.gaurav.bean.Customer;

public class HibernateSendLevelCacheTest {

    public static void main(String[] args) {

        Configuration cfg = new Configuration();
        cfg.configure("hibernate.cfg.xml");

        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session firstSession = sessionFactory.openSession();
        Object object1 = firstSession.load(Customer.class, new Integer(1));

        Customer customer1 = (Customer) object1;

        System.out.println("Object Loaded first and here customer name is-->"
                + customer1.getCustomerName());
        System.out.println("Object Loaded first and here customer id is-->"
                + customer1.getCustomerId());
        System.out
                .println("Object Loaded first and here customer expenditure is-->"
                        + customer1.getExpenditure());
        System.out.println("***** Object is loaded here *****");

        firstSession.clear();
        firstSession.close();

        System.out.println("Thread.sleep called Status-Waiting......");

        try {
            Thread.sleep(10000);
        } catch (Exception e) {
        }

        System.out
                .println("----------------------------Waiting---------------------------------------------------------");

        System.out.println("10 seconds compelted during wait");

        Session secondSession = sessionFactory.openSession();
        Object object2 = secondSession.load(Customer.class, new Integer(1));

        System.out
                .println("-------------------------------------------------------------------------------------");

        Customer customer2 = (Customer) object2;

        System.out
                .println("Second time object loaded and here customer name is -->"
                        + customer2.getCustomerName());
        System.out
                .println("Second time object loaded and here customer id is-->"
                        + customer1.getCustomerId());
        System.out
                .println("Second time object loaded and here customer expenditure is-->"
                        + customer1.getExpenditure());
        System.out.println("***** Object loaded from the database *****");

        secondSession.close();

        Session thirdSession = sessionFactory.openSession();

        Object object3 = thirdSession.load(Customer.class, new Integer(1));

        System.out
                .println("-------------------------------------------------------------------------------------");

        Customer customer3 = (Customer) object3;

        System.out
                .println("Third time object loaded and here customer name is-->"
                        + customer3.getCustomerName());
        System.out
                .println("Third time object loaded and here customer id is-->"
                        + customer1.getCustomerId());
        System.out
                .println("Third time object loaded and here customer expenditure is-->"
                        + customer1.getExpenditure());
        System.out
                .println("***** Object loaded from global cache successfully *****");

        thirdSession.close();

        sessionFactory.close();
    }

}

Below is the project directory structure:-


About ehcache.xml

    In ehcache.xml, if eternal=”true” then we should not write timeToIdealSeconds, timeToLiveSeconds, 
    hibernate will take care about these values, If you want to give values manually then we can
    use eternal=''false'' and we can assign values into timeToIdealSeconds, timeToLiveSeconds manually,
   
   a) timeToIdealSeconds = ''seconds'' means, if the object in the global cache is not using by any other class or object then it will be waited for some time we specified and deleted from the global cache if time is exceeds more than timeToIdealSeconds value.

   b) timeToLiveSeconds = ''seconds'' means if once the time specified is completed then it will be removed from the global cache by hibernate.

  c) <defaultCache … /> will reflects to all the pojo classes in our application,  and we can also assign the ehcache values to specified pojo class by
    <cache name=”– package name.pojo class name —” …….. />


Hibernate Caching Tips

  1. All the objects those are passed to methods save(), update() or saveOrUpdate() or those you get from load(), get(), list(), iterate() or scroll() will be saved into cache.
  2. evict() is used to delete the object from cache.
  3. flush() is used to synchronize the object with database.
  4. Session.clear() used to delete all objects from the cache . 
  5. contains() used to find whether the object belongs to the cache or not.
  6. If the query wants to force a refresh of its query cache region, we should call Query.setCacheMode(CacheMode.REFRESH).

Tuesday, 4 December 2012

How to send Email in Specific time interval continously Using Timer threads

How to send Email in Specific time interval continously Using Timer

FreeMarker is a "template engine"; a generic tool to generate text output (anything from HTML to autogenerated source code) based on templates. It's a Java package, a class library for Java programmers. It's not an application for end-users in itself, but something that programmers can embed into their products. 
reference(http://freemarker.sourceforge.net/)

I am using freemarker template for creating the email body. I have used my gmail a/c username and password for the email send test purpose. So if you want to execute your program then in the Constant.java file use your gmail username and password for FROM_MAIL_ID and FROM_MAIL_ID_PASS property.

Before going through the below program few jars are required, the references are given below:-
1) http://www.java2s.com/Code/Jar/a/Downloadactivationjar.htm - activation.jar
2) mirrors.ibiblio.org/pub/mirrors/maven2/freemarker/freemarker/2.3.4/freemarker-2.3.4.jar - freemarker.jar
3) http://www.java2s.com/Code/Jar/m/Downloadmailjar.htm - mail.jar

STEP - 1

1) Create java file and name it as Constants.java file as below:-

package com.gaurav.examples.mail;

public class Constants
{
    public static final String TEMPLATE_FILENAME = "html-mail-template.ftl";
    public static final String ATTACHMENT_FILENAME = "
welcome.txt";
    public static final String MAIL_SEND_SUCCESS_STATUS = "mail Sent successfully";
    public static final String MAIL_SEND_SUCCESS_FAIL = "mail send failed";
    public static final String FROM_MAIL_ID = "test@gmail.com";//This is From mail-id.
    public static final String FROM_MAIL_ID_PASS ="Please keep ur password here";//From Mail-id password.
    public static final String TO_MAIL_ID = "tomailIdUsername@gmail.com";//Please use to mail id here.
    public static final String MAIL_SUBJECT = "Sending a Test mail through Java Mail API";
    public static final String TO_MAIL = "to";
    public static final String TO_MAIL_NAME = "Gollu";
    public static final String MAIL_BODY = "body";
    public static final String EMAIL_BODY_CONTENT = "See the text file and reply the answer?";
    public static final String FROM_MAIL = "from";
    public static final String FROM_MAIL_NAME = "Kumar.";
    public static final String PROPERTY_FILENAME ="settings.properties";
    public static final String BODY_CONTENT_TYPE="text/html";
}

STEP - 2

1) Create a java file and name it as SendMail.java, use the below contents
 
package com.gaurav.examples.mail;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import freemarker.template.Configuration;
import freemarker.template.Template;

public class SendMail {

    private String strMailSendStatus = null;

    public String mailSend() throws Exception {

        Properties props = new Properties();
        try {
            props.load(new FileInputStream(
                    new File(Constants.PROPERTY_FILENAME)));
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        Session session = Session.getDefaultInstance(props,
                new Authenticator() {

                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(
                                Constants.FROM_MAIL_ID,
                                Constants.FROM_MAIL_ID_PASS);
                    }
                });

        try {
            Message message = new MimeMessage(session);

            message.setFrom(new InternetAddress());
            message.setRecipients(Message.RecipientType.TO,
                    InternetAddress.parse(Constants.TO_MAIL_ID));
            message.setSubject(Constants.MAIL_SUBJECT);

            BodyPart body = new MimeBodyPart();

            // freemarker api use for using it's template.
            Configuration cfg = new Configuration();
            Template template = cfg.getTemplate(Constants.TEMPLATE_FILENAME);
            Map<String, String> rootMap = new HashMap<String, String>();
            rootMap.put(Constants.TO_MAIL, Constants.TO_MAIL_NAME);
            rootMap.put(Constants.MAIL_BODY, Constants.EMAIL_BODY_CONTENT);
            rootMap.put(Constants.FROM_MAIL, Constants.FROM_MAIL_NAME);
            Writer out = new StringWriter();
            template.process(rootMap, out);
            // freemarker api use for using it's template ends here.

            /* we can keep html tags in our text for the decoration purpose. */
            body.setContent(out.toString(), "text/html");

            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(body);

            body = new MimeBodyPart();

            String filename = Constants.ATTACHMENT_FILENAME;
            DataSource source = new FileDataSource(filename);
            body.setDataHandler(new DataHandler(source));
            body.setFileName(filename);
            multipart.addBodyPart(body);

            message.setContent(multipart, "text/html");

            Transport.send(message);

            strMailSendStatus = Constants.MAIL_SEND_SUCCESS_STATUS;

        } catch (MessagingException e) {
            e.printStackTrace();
            strMailSendStatus = Constants.MAIL_SEND_SUCCESS_FAIL;
        }

        return strMailSendStatus;
    }
}
 
STEP - 3

1) Create a java file and name it as SendMailCaller.java as below

package com.gaurav.examples.mail;

import java.util.TimerTask;


public class SendMailCaller extends TimerTask
{

    public void run()
    {

        SendMail sender = new SendMail();
                String mailSendStatus = null;
                try{
                    mailSendStatus = sender.mailSend();
                }catch(Exception e){
                    e.printStackTrace();
                }
               System.out.println("Email Sent status ->"+mailSendStatus);

            }
}

STEP - 4 

1) Create a java file and name it as EmailJobScheduler.java like below:-

package com.gaurav.examples.mail;

import java.util.Timer;

public class EmailJobScheduler {

    public void callScheduler() throws Exception {

        System.out.println("Scheduler Starterd...");
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new SendMailCaller(), getTimeDelayAndPeriod("2s"),
                getTimeDelayAndPeriod("10s"));

    }

    public long getTimeDelayAndPeriod(String value) throws Exception {
        long l = 0;
        String val = "";
        try {
            if (value.endsWith("d") || value.endsWith("D")) {
                val = value.substring(0, value.length() - 1);
                l = Long.parseLong(val) * 24 * 60 * 60 * 1000;
            }

            else if (value.endsWith("h") || value.endsWith("H")) {

                val = value.substring(0, value.length() - 1);
                l = Long.parseLong(val) * 60 * 60 * 1000;

            } else if (value.endsWith("m") || value.endsWith("M")) {
                val = value.substring(0, value.length() - 1);
                l = Long.parseLong(val) * 60 * 1000;
            } else if (value.endsWith("s") || value.endsWith("S")) {

                val = value.substring(0, value.length() - 1);
                l = Long.parseLong(val) * 1000;
            } else {

                l = Long.parseLong(value);
            }

        } catch (Exception e) {

            throw new Exception(e);
        }

        return l;
    }

    public static void main(String a[]) throws Exception {
        EmailJobScheduler emailJobScheduler = new EmailJobScheduler();
        emailJobScheduler.callScheduler();
    }

}

STEP - 5

1) Create a file and name it as html-mail-template.ftl, use the below contents:-

<html>
<body>
Hi ${to},

<p style='color:midnightblue;'>${body}</p>

Regards,<br/>
${from}.
</body>
</html>


STEP - 6

1) Create a text file and name it as welcome.txt, use the below content:-

Who is elected as the president of India in 2012?

STEP - 7

1) Create a file and name it as settings.properties, and use the below content:

mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
mail.smtp.auth=true
mail.smtp.port=465
mail.smtp.host=smtp.gmail.com
mail.smtp.socketFactory.port=465

STEP - 8

In order to run  this application three external jars are required which is as below:-

Required Jars    -       (download link)

References are given above.

The project directory structure is given below:-




Thursday, 1 November 2012

Contract-first Spring web services example using JAXB-XJC tool


Developing a contract-first Spring web services JAXB-XJC tool

In the earlier link developing-contract-first-spring-web.html, I have provided the details to create a sample application using contract-first spring web services.  Now we will proceed further to create another application using contract-first spring web services.

Approximately all the steps are mentioned in the above are similar.

1) Create a web project in Eclipse and name it as ContractFirstStudentService.


2) Writing the Student.xsd file for Student as below:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://localhost:7070/gaurav/springws/ContractFirstStudentService"
    xmlns:tns="http://localhost:7070/gaurav/springws/ContractFirstStudentService" elementFormDefault="qualified">

    <element name="studentRequest">
        <complexType>
            <sequence>
                <element name="id" type="string"></element>
            </sequence>
        </complexType>
    </element>
    <element name="studentResponse">
        <complexType>
            <sequence>
            <element name="studentdetails" type="tns:studentdetails"></element>
            </sequence>
        </complexType>
    </element>
    <complexType name="studentdetails">
        <sequence>
            <element name="name" type="string"></element>
            <element name="total" type="string"></element>
            <element name="address" type="tns:address"></element>
           
        </sequence>
    </complexType>
    <complexType name="address">
        <sequence>
           
            <element name="flatNo" type="string"></element>
            <element name="street" type="string"></element>
            <element name="city" type="string"></element>
            <element name="state" type="string"></element>
            <element name="pin" type="string"></element>
        </sequence>
    </complexType>
</schema>


3) Get the plugin of JAXB 2.0 for Eclipse Helios or the eclipse version which you are using. Keep the required jar in the Eclipse plugin folder.

4) Right Click on the Student.xsd file, go to JAXB 2.0 option and click on Run XJC option, in the prompt window give package name as gaurav.springws.studentservice.service and in the output directory point it to src folder of ContractFirstStudentService eclipse project.

5) It will generate the classes corresponding as mentioned in the xsd file, which is shown below:



6) Create a service interface class named as StudentService.java in gaurav.springws.student
service.service package. Use the below code:-

StudentService.java
 
package gaurav.springws.studentservice.service;

public interface StudentService {

    Studentdetails getStudentDetails(Long empId);

}

7) Create a service interface implementation class and name it as StudentServiceImpl.java in the package gaurav.springws.studentservice.service. Use the below code:-

StudentServiceImpl.java

package gaurav.springws.studentservice.service;

import org.apache.log4j.Logger;

public class StudentServiceImpl implements StudentService {

    private static final Logger logger = Logger
            .getLogger(StudentServiceImpl.class);

    public StudentServiceImpl() {
    }

    public Studentdetails getStudentDetails(Long empId) {
        logger.info("Id has been provided. EmpID : " + empId);
        String name = null;

        Studentdetails sd = new Studentdetails();

        if (empId == 1) {
            name = "Gaurav";

        } else {
            name = "Shivam";

        }
        sd.setName(name);
        sd.setTotal("895");
        Address address = new Address();
        address.setFlatNo("630");
        address.setStreet("Kondapur");
        address.setCity("Hyderabad");
        address.setState("Andhra Pradesh");
        address.setPin("500048");
        sd.setAddress(address);
        
        Address address1 = sd.getAddress();
        return sd;
    }

}

8) Create a package and name it as gaurav.springws.studentservice.service.endpoint.
  •   Create a class name as StudentServicePayloadRootAnnotationEndPoint.java
  •   Use the below code in the jave file :-
StudentServicePayloadRootAnnotationEndPoint.java
package gaurav.springws.studentservice.service.endpoint;

import gaurav.springws.studentservice.service.ObjectFactory;
import gaurav.springws.studentservice.service.StudentRequest;
import gaurav.springws.studentservice.service.StudentResponse;
import gaurav.springws.studentservice.service.StudentService;

import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;

import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;

@Endpoint
public class StudentServicePayloadRootAnnotationEndPoint {

    private final StudentService studService;
    private final ObjectFactory JAXB_OBJECT_FACTORY = new ObjectFactory();

    public StudentServicePayloadRootAnnotationEndPoint(
            StudentService studentService) {
        this.studService = studentService;
    }

    @PayloadRoot(localPart = "studentRequest", namespace = "http://localhost:7070/gaurav/springws/ContractFirstStudentService")
    public JAXBElement<StudentResponse> getStudentDetails(
            StudentRequest studRequest) {
        StudentResponse response = JAXB_OBJECT_FACTORY.createStudentResponse();
        System.out.println("studRequest.getId()-->" + studRequest.getId());

        response.setStudentdetails(studService.getStudentDetails(Long
                .parseLong(studRequest.getId())));

        return new JAXBElement<StudentResponse>(
                new QName(
                        "http://localhost:7070/gaurav/springws/ContractFirstStudentService",
                        "studentResponse"), StudentResponse.class, response);
    }

}


9) modify the web.xml file as below:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>ContractFirstStudentService</display-name>
    <servlet>
        <servlet-name>spring-ws</servlet-name>
        <servlet-class>
            org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-ws</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

10) Create the spring-ws-servlet.xml file, as spring-ws is the name of the servlet mentioned in the web.xml. So it's rule to create the bean file as the name of the servlet which should be prefixed with -servlet. Like spring-ws-servlet.xml. Use the below code in the spring-ws-servlet.xml file.

 <?xml  version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans             http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context                      
http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <!-- PayloadRootAnnotationMethodEndpointMapping is the Mapping that detects
        and handles the @PayloadRoot Annotation -->
    <bean
        class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
        <property name="interceptors">
            <list>
                <bean
                    class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" />
            </list>
        </property>
    </bean>

    <bean id="studServiceEndpoint"
        class="gaurav.springws.studentservice.service.endpoint.StudentServicePayloadRootAnnotationEndPoint">
        <constructor-arg>
            <bean class="gaurav.springws.studentservice.service.StudentServiceImpl" />
        </constructor-arg>
    </bean>

    <bean id="StudService"
        class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
        <property name="schema" ref="studServiceSchema" />
        <property name="portTypeName" value="StudService" />
        <property name="locationUri"
            value="http://localhost:7070/ContractFirstStudentService/services" />
        <property name="targetNamespace"
            value="http://localhost:7070/gaurav/springws/ContractFirstStudentService" />
    </bean>

    <bean id="studServiceSchema" class="org.springframework.xml.xsd.SimpleXsdSchema">
        <property name="xsd" value="/WEB-INF/Student.xsd" />
    </bean>

    <bean
        class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
        <constructor-arg ref="marshaller" />
    </bean>

    <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="contextPath" value="gaurav.springws.studentservice.service" />
    </bean>

</beans>  

11) The required jars for this project is shown below:-



12) The final architecture of the project is as below:-




13) Select the application, Right Click on it, go to Run As option and select Run On Server. Configure the Tomcat server 6.0 or 7.0, on the port 7070, as I am running my tomcat 6.0 on the port 7070.


14) After running the server, hit the below URL:
http://localhost:7070/ContractFirstStudentService/services/StudService.wsdl

Note :--> http://localhost:7070/ContractFirstStudentService/services - This is the Location URI mentioned in spring-contractfirst-webservice-servlet.xml file. and StudService is the portTypeName.

15) After hitting the above URL the WSDL which we will get is shown below:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
- <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://localhost:7070/gaurav/springws/ContractFirstStudentService" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://localhost:7070/gaurav/springws/ContractFirstStudentService" targetNamespace="http://localhost:7070/gaurav/springws/ContractFirstStudentService">
- <wsdl:types>
- <schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://localhost:7070/gaurav/springws/ContractFirstStudentService">
- <element name="studentRequest">
- <complexType>
- <sequence>
  <element name="id" type="string" />
  </sequence>
  </complexType>
  </element>
- <element name="studentResponse">
- <complexType>
- <sequence>
  <element name="studentdetails" type="tns:studentdetails" />
  </sequence>
  </complexType>
  </element>
- <complexType name="studentdetails">
- <sequence>
  <element name="name" type="string" />
  <element name="total" type="string" />
  <element name="address" type="tns:address" />
  </sequence>
  </complexType>
- <complexType name="address">
- <sequence>
  <element name="flatNo" type="string" />
  <element name="street" type="string" />
  <element name="city" type="string" />
  <element name="state" type="string" />
  <element name="pin" type="string" />
  </sequence>
  </complexType>
  </schema>
  </wsdl:types>
- <wsdl:message name="studentRequest">
  <wsdl:part element="tns:studentRequest" name="studentRequest" />
  </wsdl:message>
- <wsdl:message name="studentResponse">
  <wsdl:part element="tns:studentResponse" name="studentResponse" />
  </wsdl:message>
- <wsdl:portType name="StudService">
- <wsdl:operation name="student">
  <wsdl:input message="tns:studentRequest" name="studentRequest" />
  <wsdl:output message="tns:studentResponse" name="studentResponse" />
  </wsdl:operation>
  </wsdl:portType>
- <wsdl:binding name="StudServiceSoap11" type="tns:StudService">
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
- <wsdl:operation name="student">
  <soap:operation soapAction="" />
- <wsdl:input name="studentRequest">
  <soap:body use="literal" />
  </wsdl:input>
- <wsdl:output name="studentResponse">
  <soap:body use="literal" />
  </wsdl:output>
  </wsdl:operation>
  </wsdl:binding>
- <wsdl:service name="StudServiceService">
- <wsdl:port binding="tns:StudServiceSoap11" name="StudServiceSoap11">
  <soap:address location="http://localhost:7070/ContractFirstStudentService/services" />
  </wsdl:port>
  </wsdl:service>
  </wsdl:definitions> 

16) After getting the WSDL, Use this http://localhost:7070/ContractFirstStudentService/services/StudService.wsdl  URL in SoapUI for Test purpose - I am using SoapUI 3.0.1. 
  • Go to File, select New SoapUI Project, put the above URL in Initial WSDL/WADL option.
  • After placing this URL, it will automatically create a request like below:
 Request:-

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:con="http://localhost:7070/gaurav/springws/ContractFirstStudentService">
   <soapenv:Header/>
   <soapenv:Body>
      <con:studentRequest>
         <con:id>?</con:id>
      </con:studentRequest>
   </soapenv:Body>
</soapenv:Envelope>

Note:- Pass the student id in place of question mark.( I passed 1 in place of Question Mark).

Response:-   

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ns2:studentResponse xmlns:ns2="http://localhost:7070/gaurav/springws/ContractFirstStudentService">
         <ns2:studentdetails>
            <ns2:name>Gaurav</ns2:name>
            <ns2:total>895</ns2:total>
            <ns2:address>
               <ns2:flatNo>630</ns2:flatNo>
               <ns2:street>Kondapur</ns2:street>
               <ns2:city>Hyderabad</ns2:city>
               <ns2:state>Andhra Pradesh</ns2:state>
               <ns2:pin>500048</ns2:pin>
            </ns2:address>
         </ns2:studentdetails>
      </ns2:studentResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope> 

Note:- Pass the other student id like 2,3 or any number.

Response:- 

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ns2:studentResponse xmlns:ns2="http://localhost:7070/gaurav/springws/ContractFirstStudentService">
         <ns2:studentdetails>
            <ns2:name>
Shivam</ns2:name>
            <ns2:total>895</ns2:total>
            <ns2:address>
               <ns2:flatNo>630</ns2:flatNo>
               <ns2:street>Kondapur</ns2:street>
               <ns2:city>Hyderabad</ns2:city>
               <ns2:state>Andhra Pradesh</ns2:state>
               <ns2:pin>500048</ns2:pin>
            </ns2:address>
         </ns2:studentdetails>
      </ns2:studentResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
 

Note :- This Sample application is developed with the help of JAXB 2.0 Run XJC tool by using Spring web services.
 

Developing a contract-first Spring Web Services


  ***Contract-first Spring Web Services***

There are two approaches: Contract Last and Contract First for develping web services.
We can easily develop contract first web service using Spring Web Services. It focus more on XML and lesser on Java implementation.

When we use contract-first approach, we start with the web services contract (XML files like wsdl, xsd)
and after that we are proceeding with the Java impletement the web service contract.
When we use the contract-last approach, we first write the Java code and after web service contract(WSDL) to be genereated for that. Spring Web Services only supports the contract-first development style.

Here we will design a sample application for getting the factorial of the given number using Spring Web Service. Given below are the pre-requisite softwares to develop and run the application

•JDK 1.6 or higher
•Spring Web Service jars
•Web Server(Like Tomcat 6.0 or Tomcat 7.0)


The following steps are required to develop the sample application:

1.Contract Design or writing the XSD file


2.Defining the service interface for getting the factorial


3.Implementing the service interface


4.Defining Spring Web-Service endpoints


5.Configuring deployment descriptor.


6.Configuring Spring’s Application Context file.


STEPS

1) Create a web project in Eclipse and name it as find-factorial-using-contractfirst.




2) Writing the XSD file for the Factorial of a given number

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified" attributeFormDefault="qualified"
    targetNamespace="http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service"
    xmlns:tns="http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service">

    <element name="findFactorialRequest" type="string" />
    <element name="findFactorialResponse" type="string" />

</schema>


3) Writing the service interface for factorial service
  •  Create a package name as gaurav.springws.findfactorial.
  • Create a java class name as FindFactorialService.java
  • Write the code as below in this class :
FindFactorialService.java

package gaurav.springws.findfactorial;
public interface FindFactorialService {
     String getFactorial(String anyString);
}


4) Writing the service interface implementation
  •  Create a class FindFactorialServiceImpl.java in gaurav.springws.findfactorial package.
  • Write the below code in the impl java file:
FindFactorialServiceImpl.java

package gaurav.springws.findfactorial;

public class FindFactorialServiceImpl implements FindFactorialService {

    public boolean isParsableToInteger(String strValue) {
        try {
            Integer.parseInt(strValue);
            return true;
        } catch (NumberFormatException nfe) {
            return false;
        }
    }

    public String getFactorial(String inputString) {

        String factorialResult = "Not a Valid Number";

        if (inputString == null || inputString.trim().length() == 0) {
            return "";
        }

        if (isParsableToInteger(inputString)) {

            int number = Integer.parseInt(inputString);

            int factorial = number;

            for (int i = (number - 1); i > 1; i--) {
                factorial = factorial * i;
            }
            factorialResult = String.valueOf(factorial);

        }

        return factorialResult;
    }
}


5) Writing Spring Web-Service endpoints
  •  Create a package and name it as gaurav.springws.findfactorial.endpoint.
  •  Create a class and name it as FindFactorialServiceEndPoint.java
  •  Write the below code in the EndPoint file.


FindFactorialServiceEndPoint.java

package gaurav.springws.findfactorial.endpoint;

import gaurav.springws.findfactorial.FindFactorialService;

import org.springframework.ws.server.endpoint.AbstractDomPayloadEndpoint;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

public class FindFactorialServiceEndPoint extends AbstractDomPayloadEndpoint {

    public static final String NAMESPACE = "http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service";

    private FindFactorialService findFactorialService;

    public void setFindFactorialService(
            FindFactorialService findFactorialService) {
        this.findFactorialService = findFactorialService;
    }

    protected Element invokeInternal(Element requestElement, Document document)
            throws Exception {

        String requestString = findRequestString(requestElement);
        String findFactorialString = invokeServiceAndReturnResponse(requestString);
        Element responseXml = prepareResponseXml(document, findFactorialString);
        return responseXml;
    }

    private static String findRequestString(Element requestElement) {

        NodeList childNodes = requestElement.getChildNodes();
        String requestString = null;
        for (int i = 0; i < childNodes.getLength(); i++) {
            if (childNodes.item(i).getNodeType() == Node.TEXT_NODE) {
                Text tempText = (Text) childNodes.item(i);
                requestString = tempText.getNodeValue();
                break;
            }
        }
        return requestString;
    }

    private String invokeServiceAndReturnResponse(String requestString) {

        String findFactorialString = findFactorialService
                .getFactorial(requestString);
        return findFactorialString;
    }

    private static Element prepareResponseXml(Document document,
            String responseString) {

        Element responseElement = document.createElementNS(NAMESPACE,
                "findFactorialResponse");
        Text responseText = document.createTextNode(responseString);
        responseElement.appendChild(responseText);
        return responseElement;
    }
}

 

6) Writing the web.xml file, code is given below :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>find-factorial-using-contractfirst</display-name>
  <servlet>
        <servlet-name>spring-contractfirst-webservice</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
            <param-name>transformWsdlLocations</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-contractfirst-webservice</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>


7) Writing the spring-contractfirst-webservice-servlet.xml file. In this file, we will define the location, name, schema Type, Endpoint for the factorial service.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans    
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <bean id="findFactorialService" class="gaurav.springws.findfactorial.FindFactorialServiceImpl">
    </bean>

    <bean id="findFactorialServiceEndpoint"
        class="gaurav.springws.findfactorial.endpoint.FindFactorialServiceEndPoint">
        <property name="findFactorialService" ref="findFactorialService" />
    </bean>

    <bean id="payloadMapping"
        class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
        <property name="defaultEndpoint" ref="findFactorialServiceEndpoint" />
    </bean>

    <bean id="findFactorialSchema" class="org.springframework.xml.xsd.SimpleXsdSchema">
        <property name="xsd" value="/WEB-INF/findFactorialService.xsd" />
    </bean>

    <bean id="findFactorial"
        class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
        <property name="schema" ref="findFactorialSchema" />
        <property name="portTypeName" value="findFactorial" />
        <property name="locationUri"
            value="http://localhost:7070/find-factorial-using-contractfirst/services" />
    </bean>


</beans>


8) The required jars for this project is shown below:-



9) The final architecture of the project is as below:-


10) Select the application, Right Click on it, go to Run As option and select Run On Server. Configure the Tomcat server 6.0 or 7.0, on the port 7070, as I am running my tomcat 6.0 on the port 7070.

11) After running the server, hit the below URL:
http://localhost:7070/find-factorial-using-contractfirst/services/findFactorial.wsdl 

Note :--> http://localhost:7070/find-factorial-using-contractfirst/services - This is the Location URI mentioned in spring-contractfirst-webservice-servlet.xml file. and findFactorial is the portTypeName.

12) After hitting the above URL the WSDL which we will get is shown below:

 <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
- <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service" targetNamespace="http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service">
- <wsdl:types>
- <schema xmlns="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service">
  <element name="findFactorialRequest" type="string" />
  <element name="findFactorialResponse" type="string" />
  </schema>
  </wsdl:types>
- <wsdl:message name="findFactorialRequest">
  <wsdl:part element="tns:findFactorialRequest" name="findFactorialRequest" />
  </wsdl:message>
- <wsdl:message name="findFactorialResponse">
  <wsdl:part element="tns:findFactorialResponse" name="findFactorialResponse" />
  </wsdl:message>
- <wsdl:portType name="findFactorial">
- <wsdl:operation name="findFactorial">
  <wsdl:input message="tns:findFactorialRequest" name="findFactorialRequest" />
  <wsdl:output message="tns:findFactorialResponse" name="findFactorialResponse" />
  </wsdl:operation>
  </wsdl:portType>
- <wsdl:binding name="findFactorialSoap11" type="tns:findFactorial">
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
- <wsdl:operation name="findFactorial">
  <soap:operation soapAction="" />
- <wsdl:input name="findFactorialRequest">
  <soap:body use="literal" />
  </wsdl:input>
- <wsdl:output name="findFactorialResponse">
  <soap:body use="literal" />
  </wsdl:output>
  </wsdl:operation>
  </wsdl:binding>
- <wsdl:service name="findFactorialService">
- <wsdl:port binding="tns:findFactorialSoap11" name="findFactorialSoap11">
  <soap:address location="http://localhost:7070/find-factorial-using-contractfirst/services" />
  </wsdl:port>
  </wsdl:service>
  </wsdl:definitions>

13) After getting the WSDL, Use this http://localhost:7070/find-factorial-using-contractfirst/services/findFactorial.wsdl  URL in SoapUI for Test purpose - I am using SoapUI 3.0.1.
  • Go to File, select New SoapUI Project, put the above URL in Initial WSDL/WADL option.
  • After placing this URL, it will automatically create a request like below:

Request:-

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:fin="http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service">
   <soapenv:Header/>
   <soapenv:Body>
      <fin:findFactorialRequest>?</fin:findFactorialRequest>
   </soapenv:Body>
</soapenv:Envelope>


Note:- Pass the number in place of question mark.( I passed 5 in place of Question Mark).

Response:- 

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <findFactorialResponse xmlns="http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service">120</findFactorialResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


*****Note:- Pass some invalid number like 6.5. The response will come like below:-

For INVALID Condition:-

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <findFactorialResponse xmlns="http://localhost:7070/gaurav/springws/findfactorial/findfactorial-service">Not a Valid Number</findFactorialResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>