RESTful Web Services

Restful Services

Example of RESTful Web Service using Jersey

Advertisements

RSA Encryption Example

Encryption is a one of the ways to achieve data security. Encryption is converting the data in the plain text into an unreadable text called the cipher text. Decryption is converting the cipher text back to plain text.

This encryption/decryption of data is part of cryptography. Encryption and decryption generally require the use of some secret information, referred to as a key, which is used in converting plain text to cipher text and vice versa.

Symmetric key cryptography refers to encryption methods in which both the sender and receiver share the same key.

Asymmetric key cryptography (also known as public key cryptography) refers to a system that requires two separate keys, one of which is secret and one of which is public. Although different, the two parts of the key pair are mathematically linked. One key encrypts the plain text, and the other decrypts the cipher text. Neither key can perform both functions. The public key, or the key used to encrypt information can be freely distributed.

 RSA is one of the algorithm for public-key cryptography that is based on factoring large integers. RSA stands for Ron Rivest, Adi Shamir and Leonard Adleman, who first publicly described it.

Following example shows how to encrypt/decrypt information using RSA algorithm in Java.

The KeyPairGenerator class instance is used to generate the pair of public and private key for RSA algorithm and are saved into the files.

The Cipher class instance is used encrypt/decrypt information using the pair of keys generated above.

package in.javadigest.encryption;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.Cipher;

/**
 * @author JavaDigest
 * 
 */
public class EncryptionUtil {

  /**
   * String to hold name of the encryption algorithm.
   */
  public static final String ALGORITHM = "RSA";

  /**
   * String to hold the name of the private key file.
   */
  public static final String PRIVATE_KEY_FILE = "C:/keys/private.key";

  /**
   * String to hold name of the public key file.
   */
  public static final String PUBLIC_KEY_FILE = "C:/keys/public.key";

  /**
   * Generate key which contains a pair of private and public key using 1024
   * bytes. Store the set of keys in Prvate.key and Public.key files.
   * 
   * @throws NoSuchAlgorithmException
   * @throws IOException
   * @throws FileNotFoundException
   */
  public static void generateKey() {
    try {
      final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
      keyGen.initialize(1024);
      final KeyPair key = keyGen.generateKeyPair();

      File privateKeyFile = new File(PRIVATE_KEY_FILE);
      File publicKeyFile = new File(PUBLIC_KEY_FILE);

      // Create files to store public and private key
      if (privateKeyFile.getParentFile() != null) {
        privateKeyFile.getParentFile().mkdirs();
      }
      privateKeyFile.createNewFile();

      if (publicKeyFile.getParentFile() != null) {
        publicKeyFile.getParentFile().mkdirs();
      }
      publicKeyFile.createNewFile();

      // Saving the Public key in a file
      ObjectOutputStream publicKeyOS = new ObjectOutputStream(
          new FileOutputStream(publicKeyFile));
      publicKeyOS.writeObject(key.getPublic());
      publicKeyOS.close();

      // Saving the Private key in a file
      ObjectOutputStream privateKeyOS = new ObjectOutputStream(
          new FileOutputStream(privateKeyFile));
      privateKeyOS.writeObject(key.getPrivate());
      privateKeyOS.close();
    } catch (Exception e) {
      e.printStackTrace();
    }

  }

  /**
   * The method checks if the pair of public and private key has been generated.
   * 
   * @return flag indicating if the pair of keys were generated.
   */
  public static boolean areKeysPresent() {

    File privateKey = new File(PRIVATE_KEY_FILE);
    File publicKey = new File(PUBLIC_KEY_FILE);

    if (privateKey.exists() && publicKey.exists()) {
      return true;
    }
    return false;
  }

  /**
   * Encrypt the plain text using public key.
   * 
   * @param text
   *          : original plain text
   * @param key
   *          :The public key
   * @return Encrypted text
   * @throws java.lang.Exception
   */
  public static byte[] encrypt(String text, PublicKey key) {
    byte[] cipherText = null;
    try {
      // get an RSA cipher object and print the provider
      final Cipher cipher = Cipher.getInstance(ALGORITHM);
      // encrypt the plain text using the public key
      cipher.init(Cipher.ENCRYPT_MODE, key);
      cipherText = cipher.doFinal(text.getBytes());
    } catch (Exception e) {
      e.printStackTrace();
    }
    return cipherText;
  }

  /**
   * Decrypt text using private key.
   * 
   * @param text
   *          :encrypted text
   * @param key
   *          :The private key
   * @return plain text
   * @throws java.lang.Exception
   */
  public static String decrypt(byte[] text, PrivateKey key) {
    byte[] dectyptedText = null;
    try {
      // get an RSA cipher object and print the provider
      final Cipher cipher = Cipher.getInstance(ALGORITHM);

      // decrypt the text using the private key
      cipher.init(Cipher.DECRYPT_MODE, key);
      dectyptedText = cipher.doFinal(text);

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

    return new String(dectyptedText);
  }

  /**
   * Test the EncryptionUtil
   */
  public static void main(String[] args) {

    try {

      // Check if the pair of keys are present else generate those.
      if (!areKeysPresent()) {
        // Method generates a pair of keys using the RSA algorithm and stores it
        // in their respective files
        generateKey();
      }

      final String originalText = "Text to be encrypted ";
      ObjectInputStream inputStream = null;

      // Encrypt the string using the public key
      inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
      final PublicKey publicKey = (PublicKey) inputStream.readObject();
      final byte[] cipherText = encrypt(originalText, publicKey);

      // Decrypt the cipher text using the private key.
      inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
      final PrivateKey privateKey = (PrivateKey) inputStream.readObject();
      final String plainText = decrypt(cipherText, privateKey);

      // Printing the Original, Encrypted and Decrypted Text
      System.out.println("Original Text: " + originalText);
      System.out.println("Encrypted Text: " +cipherText.toString());
      System.out.println("Decrypted Text: " + plainText);

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

Spring Web Service Example

  • Web service is medium by which, any two application can communicate with one another over internet.
  • The WSDL(Web Services Description Language) is a xml file is used to describe a web service, it specifies the service location and the operations that service exposes.
  • The system communicates using the SOAP (Simple Object Access protocol) messages. The SOAP messages are xml based and are used to send request and response messages.
  • There are two approaches for developing web services: Contract First and Contract last.
  • In the Contract First approach you first create the contract (XML) and write the Java code to implement the contract.
  • In the Contract Last approach you first write the Java code and later create a Contract (WSDL) for the code.
  • Spring Web Service is the module of Spring framework that can used to develop SOAP based Contract First Web Services.
  • While developing Contract First the focus is always on XML files, you need to think in terms of XML.

The Spring WS consists of the Core module, XML module, OXM module and the Security module.
Let’s take an example of a very simple web service to understand how web services can be implemented using Spring WS.
The following web service takes in name as an input parameter and responds with a hello message.
This example uses JiBX for marshaling and maven for running the application.
Steps for creating a web service

1. Creating the contract

The first step in contract first web service would be to define the schema for the request and the response messages

/WEB-INF/xsd/hello.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://in.javadigest/HelloService/"
  elementFormDefault="qualified">
  <xsd:element name="HelloRequest">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="in" type="xsd:string" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="HelloResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="out" type="xsd:string" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Example of SOAP request and response xmls for the above schema

Request.xml

<soapenv:Envelope
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:hel="http://in.javadigest/HelloService/">
  <soapenv:Header />
  <soapenv:Body>
    <hel:HelloRequest>
      <hel:in>User</hel:in>
    </hel:HelloRequest>
  </soapenv:Body>
</soapenv:Envelope>

Response.xml

<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header />
  <SOAP-ENV:Body>
    <hs:HelloResponse xmlns:hs="http://in.javadigest/HelloService/">
      <hs:out>Hello : User!</hs:out>
    </hs:HelloResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Based on the request and response schema, you also need to create a WSDL file; which can be done manually or use Spring to auto generate the WSDL file.

In this example, Spring bean to generate the WSDL file:
Use the following URL to view the WSDL file

http://localhost:8080/helloservice/HelloRequest.wsdl

The WSDL file will look like

<?xmlt;?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://in.javadigest/HelloService/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://in.javadigest/HelloService/" targetNamespace="http://in.javadigest/HelloService/">
  <wsdl:types>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://in.javadigest/HelloService/">
  <xsd:element name="HelloRequest">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="in" type="xsd:string"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="HelloResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="out" type="xsd:string"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
  </wsdl:types>
  <wsdl:message name="HelloRequest">
    <wsdl:part element="tns:HelloRequest" name="HelloRequest">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="HelloResponse">
    <wsdl:part element="tns:HelloResponse" name="HelloResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="Hello">
    <wsdl:operation name="Hello">
      <wsdl:input message="tns:HelloRequest" name="HelloRequest">
    </wsdl:input>
      <wsdl:output message="tns:HelloResponse" name="HelloResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HelloSoap11" type="tns:Hello">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="Hello">
      <soap:operation soapAction=""/>
      <wsdl:input name="HelloRequest">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="HelloResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HelloService">
    <wsdl:port binding="tns:HelloSoap11" name="HelloSoap11">
      <soap:address location="http://localhost:8080/helloservice/services/HelloRequest"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

2. Create and define the service interface

The next step is to define the interface that would be exposed as the web service and implement the same
In this example we would take name as an input parameter and respond with a hello message.

Following is the HelloService interface and its implementation

HelloService.java

package in.javadigest.service;

public interface HelloService {

  String sayhello(String name);
}

HelloServiceImpl.java

package in.javadigest.service;

public class HelloServiceImpl implements HelloService {

  private boolean validate;

  @Override
  public String sayhello(String name) {

    if (validate && (name == null || name.trim().isEmpty())) {
      return "Error: The input name was empty.";
    }

    return "Hello : " + name + "!";
  }

  public boolean isValidate() {
    return validate;
  }

  public void setValidate(boolean validate) {
    this.validate = validate;
  }

}

 3. Creating the Object/XML binding

Rather than handling XML directly, you can convert the XML message into a Request Object and vice versa. This conversion of XML document to and from a Java Object is known as Marshalling, or XML Serialization. A marshaller serializes an object to XML, and an unmarshaller deserializes XML stream to an object.
This example uses JiBX for the purpose of marshalling and unmarshalling.

To create the Object/XML binding, we need to first create the POJO classes for the request and response

HelloRequest.java

package in.javadigest.message;

public class HelloRequest {

  private String name;

  public HelloRequest() {
    super();
  }

  public HelloRequest(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

)

HelloResponse.java

package in.javadigest.message;

public class HelloResponse {

  private String message;

  public HelloResponse() {
    super();
  }

  public HelloResponse(String message) {
    this.message = message;
  }

  public String getMessage() {
    return message;
  }

  public void setMessage(String message) {
    this.message = message;
  }

}

And next step would be to define /XML JiBX binding for the above model classes (can also be generated usin JiBX)

helloservice_jibx_binding.xml

<?xml version="1.0" encoding="UTF-8"?>
<binding>
  <mapping name="HelloRequest" class="in.javadigest.message.HelloRequest">
    <namespace prefix="hs"
      uri="http://in.javadigest/HelloService/" default="all" />
    <value name="in" field="name" />
  </mapping>

  <mapping name="HelloResponse"
    class="in.javadigest.message.HelloResponse">
    <namespace prefix="hs"
      uri="http://in.javadigest/HelloService/" default="all" />
    <value name="out" field="message" />
  </mapping>
</binding>

Spring WS provides support for many Marshellers like JAXB, Castor, XMLBeans, and JiBX

4. Define the Endpoint

Endpoint is the components that are used to handle incoming XML messages. There are two types of endpoints: message endpoints and payload endpoints. Message endpoints give access to the entire XML message, including SOAP headers and the Payload endpoints provides access to the content of the SOAP body.
To define the endpoint you can either implement the MessageEndpoint/PayloadEndpoint interface, extend any of the abstract classes provided by the Spring WS.
In the following example we have used AbstractMarshallingPayloadEndpoint class

HelloServiceEndpoint.java

package in.javadigest.endpoint;

import in.javadigest.message.HelloRequest;
import in.javadigest.message.HelloResponse;
import in.javadigest.service.HelloService;

import org.springframework.ws.server.endpoint.AbstractMarshallingPayloadEndpoint;

public class HelloServiceEndpoint extends AbstractMarshallingPayloadEndpoint {

  private HelloService helloService;

  protected Object invokeInternal(Object requestObject) throws Exception {
    HelloRequest request = (HelloRequest) requestObject;
    String name = request.getName();
    return new HelloResponse(helloService.sayhello(name));
  }

  public HelloService getHelloService() {
    return helloService;
  }

  public void setHelloService(HelloService helloService) {
    this.helloService = helloService;
  }

}

5. Configuring deployment descriptor

The Spring’s MessageDispatcherServlet is used to dispatch incoming XML messages to endpoints. All the web service requests should be mapped to this servlet.

Web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>MemberService</display-name>
  <servlet>
    <servlet-name>helloservice</servlet-name>
    <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:/applicationContext.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>helloservice</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>helloservice</servlet-name>
    <url-pattern>*.wsdl</url-pattern>
  </servlet-mapping>
</web-app>

6. Configuring Spring’s Application Context

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  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.xsd">

  <bean id="endpoint"
    class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
    <property name="endpointMap">
      <map>
        <entry
          key="{http://in.javadigest/HelloService/}HelloRequest"
          value-ref="helloServiceEndpoint" />
      </map>
    </property>
  </bean>

  <bean id="helloService" class="in.javadigest.service.HelloServiceImpl">
    <property name="validate" value="true" />
  </bean>

  <bean id="helloServiceEndpoint"
    class="in.javadigest.endpoint.HelloServiceEndpoint">
    <property name="marshaller" ref="marshaller" />
    <property name="unmarshaller" ref="unmarshaller" />
    <property name="helloService" ref="helloService" />
  </bean>

  <bean id="marshaller"
    class="org.springframework.oxm.jibx.JibxMarshaller">
    <property name="targetClass"
      value="in.javadigest.message.HelloResponse" />
  </bean>

  <bean id="unmarshaller"
    class="org.springframework.oxm.jibx.JibxMarshaller">
    <property name="targetClass"
      value="in.javadigest.message.HelloRequest" />
  </bean>

  <bean id="HelloRequest"
    class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
    <property name="schema" ref="schema" />
    <property name="portTypeName" value="Hello" />
    <property name="locationUri"
      value="http://localhost:8080/helloservice/services/HelloRequest" />
  </bean>

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

</beans>

The above configuration file contains
• Endpoint Mapping: The MessageDispatcherServlet would direct the incoming request to the bean and this would select an appropriate endpoint and forward the request to that endpoint. (You can also configure interceptors here, which will be processed before the request is processed).
• Spring bean for the service implementation.
• Spring bean for the endpoint, which requires marhaller and unmarshaller.

7. Running the example

The following maven code can be used to run this example (it would also download all the dependencies)

Pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>in.javadigest</groupId>
  <artifactId>helloservice</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Hello Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>org.springframework.ws</groupId>
      <artifactId>spring-ws</artifactId>
      <version>${spring-ws.version}</version>
      <classifier>all</classifier>
    </dependency>
    <dependency>
      <groupId>org.springframework.ws</groupId>
      <artifactId>spring-ws-core</artifactId>
      <version>${spring-ws.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jibx</groupId>
      <artifactId>jibx-run</artifactId>
      <version>${jibx.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jibx</groupId>
      <artifactId>jibx-extras</artifactId>
      <version>${jibx.version}</version>
    </dependency>
    <dependency>
      <groupId>xpp3</groupId>
      <artifactId>xpp3</artifactId>
      <version>${xpp3.version}</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>stringreversalservice</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.10</version>
        <configuration>
          <scanIntervalSeconds>60</scanIntervalSeconds>
          <webAppSourceDirectory>${basedir}/WebContent</webAppSourceDirectory>
          <webXml>${basedir}/WebContent/WEB-INF/web.xml</webXml>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.jibx</groupId>
        <artifactId>maven-jibx-plugin</artifactId>
        <version>1.2.1</version>
        <configuration>
          <directory>src/main/resources</directory>
          <includes>
            <includes>*binding.xml</includes>
          </includes>
          <verbose>true</verbose>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>bind</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>
  <properties>
    <spring.version>2.5.6</spring.version>
    <spring-ws.version>1.5.6</spring-ws.version>
    <jibx.version>1.2.1</jibx.version>
    <xpp3.version>1.1.3.3</xpp3.version>
  </properties>

</project>

Use the following command to run the application.

mvn jetty:run

8. Writing the client code

Tools like SOAPUI can be used to test any webservice application, once it up and running

Alternatively you can use the following Java application to test it.

package in.javadigest.client;

import java.io.StringReader;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.ws.client.core.WebServiceTemplate;

public class HelloServiceClient {
  public static void main(String[] args) throws Exception {
    String xmlRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
        + "<hs:HelloRequest xmlns:hs=\"http://in.javadigest/HelloService/\">"
        + "<hs:in>test</hs:in>" + "</hs:HelloRequest>";
    String wsdlUrl = "http://localhost:8080/helloservice/services/HelloRequest";
    StreamSource requestMessage = new StreamSource(new StringReader(xmlRequest));
    StreamResult responseMessage = new StreamResult(System.out);
    WebServiceTemplate template = new WebServiceTemplate();
    template.sendSourceAndReceiveToResult(wsdlUrl, requestMessage,
        responseMessage);
  }
}
}

Download this example.

Spring scheduling using annotations

To achieve the scheduling of asynchronous tasks, Spring provides the @Scheduled and @Async annotations.

  • @Scheduled: Used for task scheduling. The trigger information needs to be provided along with this annotation. You use the properties fixedDelay/fixedRate/cron to provide the triggering information.
    @Scheduled(fixedDelay =30000)
    public void processScheduledJob () {... }
    @Scheduled(fixedRate=30000)
    public void processScheduledJob () {... }
    @Scheduled(cron="0 0 * * * *")
    public void processScheduledJob () {... }

    The time period in milliseconds.

    With fixedDelay the time specified will be measured from the completion of the job, whereas with fixedRate the time specified will be measured from the start time of the job.

    Note that the methods annotated with @Scheduled should be void and cannot have any parameters.

  • @Async: Supports the asynchronous task execution
    @Async
    void execute() {.... }

    The method with @Async annotation can accept parameters

    @Async
    void execute(String s) {.... }

    Or it can have the Future type return values

    @Async
    Future execute(String s) {.... }

To enable the annotation driven scheduling you need to add the “annotation-driven” element from the task namespace.

Example:

Following example shows how to schedule a job in Spring using annotations.

Spring Context Xml

<!--?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:context="http://www.springframework.org/schema/context"
 xmlns:task="http://www.springframework.org/schema/task"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/task
   http://www.springframework.org/schema/task/spring-task-3.0.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:component-scan base-package="javadigest.spring.scheduler" />

<task:annotation-driven executor="executor" scheduler="scheduler" />

<task:executor id="executor" pool-size="5" />

<task:scheduler id="scheduler" pool-size="5" />

</beans>

The Scheduler

package javadigest.spring.scheduler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class MyScheduler {

  @Autowired
  private MyTask task;

  @Scheduled(fixedDelay = 30000)
  public void processScheduledJob() {
    task.execute();
  }

  public MyTask getTask() {
    return task;
  }

  public void setTask(MyTask task) {
    this.task = task;
  }
}

The Asynchronous Task

package javadigest.spring.scheduler;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
public class MyTask {

  @Async
  public void execute() {
    System.out.println("Executing asynchronous task.");
  }
}

The main() method

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringScheduler {

  public static void main(String[] args) {
    new ClassPathXmlApplicationContext("context.xml");
  }
}

Reference: Spring Manual

Spring batch example with Spring’s built in scheduling support

Following is a simple example of Spring batch scheduled using the Spring’s built in scheduler.

The Application Context

In the application context file we need to define the :-

  • transactionManager
  • jobRepository
  • jobLauncher

Above are basic objects we would need while defining a batch job.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  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">

  <bean id="transactionManager"
    class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

  <bean id="jobRepository"
    class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
    <property name="transactionManager" ref="transactionManager" />
  </bean>

  <bean id="jobLauncher"
    class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
  </bean>
</beans>

The Job Configuration File

This file contains the configuration of a batch job and its steps. It also contains the scheduling configuration and batch launcher.

jobConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:batch="http://www.springframework.org/schema/batch"
  xmlns:task="http://www.springframework.org/schema/task"
  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/task
    http://www.springframework.org/schema/task/spring-task-3.0.xsd
    http://www.springframework.org/schema/batch
    http://www.springframework.org/schema/batch/spring-batch-2.0.xsd">

  <import resource="applicationContext.xml" />

  <bean id="mytasklet" class="javadigest.springbatch.SimpleTasklet" />

  <batch:job id="simpleJob">
    <batch:step id="simpleTaskletStep">
      <batch:tasklet ref="mytasklet" />
    </batch:step>
  </batch:job>

  <bean id="myLauncher" class="javadigest.springbatch.MyLauncher">
    <property name="jobLauncher" ref="jobLauncher"></property>
    <property name="job" ref="simpleJob"></property>
  </bean>

  <task:scheduled-tasks>
    <task:scheduled ref="myLauncher" method="launch"
      fixed-delay="60000" />
  </task:scheduled-tasks>

</beans>

The Tasklet Class

This is a simple tasklet prints “Hello World !” on the console.

SimpleTasklet.java

package javadigest.springbatch;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

public class SimpleTasklet implements Tasklet {

  @Override
  public RepeatStatus execute(StepContribution paramStepContribution,
      ChunkContext paramChunkContext) throws Exception {
    System.out.println("Hello World!");
    return RepeatStatus.FINISHED;
  }
}

The Launcher Class

This class is used launch the batch job using the Job, JobParameter, and the Job classes, and is scheduled using the spring task scheduler.

MyLauncher.java

package javadigest.springbatch;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;

class MyLauncher {

  private JobLauncher jobLauncher;

  private Job job;

  public void launch() {
    JobParameters jobParameters = new JobParametersBuilder().addLong("time",
        System.currentTimeMillis()).toJobParameters();
    try {
      JobExecution execution = jobLauncher.run(job, jobParameters);
      System.out.println("Exit Status : " + execution.getStatus());
    } catch (Exception e) {
      System.out.println("Unable to execute job");
      e.printStackTrace();
    }
  }

  public JobLauncher getJobLauncher() {
    return jobLauncher;
  }

  public void setJobLauncher(JobLauncher jobLauncher) {
    this.jobLauncher = jobLauncher;
  }

  public Job getJob() {
    return job;
  }

  public void setJob(Job job) {
    this.job = job;
  }
}

Singleton Design Pattern

Singleton design pattern is a creational design pattern that restricts the initialization of objects. This pattern ensures that at any point of time there is only one instance of the object within the application context. And the singleton design  also pattern requires that there should be a global point to access the object.

Singleton design pattern should provide the flexibility of creating multiple instances if the situation demands at a later stage, without affecting classes that are using the singleton object.

Any fields defined in the singleton class would act as static fields; as only one instance of the class would be created. Singletons can be used in place of the global variables.

The singleton pattern may be used for an application wide resource, like the logger or implement a state object.

Implementing Singleton Design Pattern

To implement the singleton design pattern, you need to:

  1. Declare the constructor of the class as private so that the class cannot be instantiated by any other class.
  2. Declare a public static method to get the instance of the class, so that the method that method can control the number instance that can be created. The method should also be thread safe.

Example of a Singleton class

public class MySingleton {
  private static MySingleton instance;

  // Private Contructor
  private MySingleton() {
  }

  // Lazy initialization
  public static synchronized MySingleton getInstance() {
    if (instance == null) {
      instance = new MySingleton();
    }
    return instance;
  }
}

The above example uses the lazy initiation as the instance of the class would not be created until the getInstance() method is called for the first time.

Cloning can create problems as will allow you create a copy of the singleton object. Thus to avoid cloning the clone() method should be overridden.

public Object clone() throws CloneNotSupportedException {

      throw new CloneNotSupportedException();

}

Downloading Multiple Files As Zip

Example to download multiple files from servlet as a zip file

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Downloading Multiple Files As Zip
 * 
 * @author JavaDigest
 */
public class DownloadMultipleFiles2 extends HttpServlet {

	private static final long serialVersionUID = -7767828383799037391L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// Set the content type based to zip
		response.setContentType("Content-type: text/zip");
		response.setHeader("Content-Disposition",
				"attachment; filename=mytest.zip");

		// List of files to be downloaded
		List files = new ArrayList();
		files.add(new File("C:/first.txt"));
		files.add(new File("C:/second.txt"));
		files.add(new File("C:/third.txt"));

		ServletOutputStream out = response.getOutputStream();
		ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(out));

		for (File file : files) {

			System.out.println("Adding file " + file.getName());
			zos.putNextEntry(new ZipEntry(file.getName()));

			// Get the file
			FileInputStream fis = null;
			try {
				fis = new FileInputStream(file);

			} catch (FileNotFoundException fnfe) {
				// If the file does not exists, write an error entry instead of
				// file
				// contents
				zos.write(("ERROR: Could not find file " + file.getName())
						.getBytes());
				zos.closeEntry();
				System.out.println("Could not find file "
						+ file.getAbsolutePath());
				continue;
			}

			BufferedInputStream fif = new BufferedInputStream(fis);

			// Write the contents of the file
			int data = 0;
			while ((data = fif.read()) != -1) {
				zos.write(data);
			}
			fif.close();

			zos.closeEntry();
			System.out.println("Finished adding file " + file.getName());
		}

		zos.close();
	}
}

Downloading Multiple Files Using Multipart Response

Example to download multiple files using “multipart/x-mixed-replace”.

PS: This code does not work with Internet Explorer.

import java.io.BufferedInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 
import javax.servlet.ServletException; 
import javax.servlet.ServletOutputStream; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse;

/**
 * Downloading Multiple Files using "multipart/x-mixed-replace".
 *
 * @author JavaDigest
 */
public class DownloadMultipleFiles extends HttpServlet {

  private static final long serialVersionUID = 3305561818342965462L;

  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // Set the response type and specify the boundary string
    response.setContentType("multipart/x-mixed-replace;boundary=END");

    // Set the content type based on the file type you need to download
    String contentType = "Content-type: text/rtf";

    // List of files to be downloaded
    List files = new ArrayList();
    files.add(new File("C:/first.txt"));
    files.add(new File("C:/second.txt"));
    files.add(new File("C:/third.txt"));

    ServletOutputStream out = response.getOutputStream();

    // Print the boundary string
    out.println();
    out.println("--END");

    for (File file : files) {

      // Get the file
      FileInputStream fis = null;
      try {
        fis = new FileInputStream(file);

      } catch (FileNotFoundException fnfe) {
        // If the file does not exists, continue with the next file
        System.out.println("Could not find file " + file.getAbsolutePath());
        continue;
      }

      BufferedInputStream fif = new BufferedInputStream(fis);

      // Print the content type
      out.println(contentType);
      out.println("Content-Disposition: attachment; filename=" + file.getName());
      out.println();

      System.out.println("Sending file " + file.getName());

      // Write the contents of the file
      int data = 0;
      while ((data = fif.read()) != -1) {
        out.write(data);
      }
      fif.close();

      // Print the boundary string
      out.println();
      out.println("--END");
      out.flush();
      System.out.println("Finished sending file " + file.getName());
    }

    // Print the ending boundary string
    out.println("--END--");
    out.flush();
    out.close();
  }

}

Yet another way to achieve this will be to zip all the files before downloading, and then download the zip file as a zip attachment.

Downloading Multiple Files As Zip

Using the sequence generator in Hibernate

The generator in hibernate are basically used to generate unique identifiers and generally used for populating the primary key of the objects. As mentioned in the hibernate docs

sequence uses a sequence in DB2, PostgreSQL, Oracle, SAP DB, McKoi or a generator in Interbase. The returned identifier is of type long, short or int

To use this generator in  the application :

  1. Create a sequence in the database
    CREATE SEQUENCE my_seq START WITH 1 INCREMENT BY 1;
  2. Annotate primary key with
    @Id
    @SequenceGenerator(name = "MySequence", sequenceName = "my_seq", allocationSize=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="MySequence")
    private Long id;

The max “allocationSize” is by default set to 50
And, by default, the “increment by” is set to 1.

It’s important to note that, the sequence generator work correctly, only when the “allocationSize” and the “increment by” are same, otherwise there is a possibility of getting the “unique constraint violation” exception. therefore, it is better to explicitly define “allocationSize” and “increment by”.

Having a higher allocationSize would increase the performance of your application to some extend but may lead to gaps in the ids of the primary keys.

Generating Secure Random Numbers

Example to generate secure random numbers

package random;

import java.security.SecureRandom;

/**
 * A Simple Example to generate secure random numbers using
 * java.security.SecureRandom class.
 * 
 */
public class SecureRandomGenerator {
  public static void main(String[] args) {

    // Get the instance of SecureRandom class with specified PRNG algorithm
    SecureRandom secureRandom = new SecureRandom();

    // You can use the getInstance() of the Secure Random class to create an object of SecureRandam
    // where you would need to specify the algorithm name.
    // SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");

    // Display the algorithm name
    System.out.println("Used algorithm: " + secureRandom.getAlgorithm());

    // You also specify the algorithm provider in the getInstance() method
    // SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");

    // Display the Provider
    System.out.println("Provider: " + secureRandom.getProvider());

    // A call to the setSeed() method will seed the SecureRandom object.
    // If a call is not made to setSeed(),
    // The first call to nextBytes method will force the SecureRandom object to seed itself.

    // Get 10 random numbers
    System.out.println("Random Integers generated using SecureRandom");
    for (int i = 0; i < 10; i++) {
      System.out.println(secureRandom.nextInt());
    }
  }
}

Why use Secure Random Numbers