Friday, October 24, 2014

Caching Web Page content using ETag in Spring MVC

Most of the time we are talking about caching web pages to reduce the network traffic and network bandwidth in order to improve the user experience. But the concern is how many times we succeed on this technique after investing lots of effort on this to make it work.

There are couple of techniques available now a days to cache the web pages. In this post we will be discussing the easiest way to caching the page in an efficient way using Spring MVC framework.

Technical Background
An ETag(entity tag) is an HTTP response header returned by an HTTP/1.1 compliant web server used to determine change in content at a given URL. 

It can be considered to be the more sophisticated successor to the Last-Modified header. When a server returns a representation with an ETag header, the client can use this header in subsequent GETs, in an If-None-Match header. If the content has not changed, the server returns 304: Not Modified.

Implementation
Support for ETags is provided by the Spring servlet filter ShallowEtagHeaderFilter. It is declared under package org.springframework.web.filter. It is a plain Servlet Filter, and thus can be used in combination with any web framework. 
The ShallowEtagHeaderFilter filter creates so-called shallow ETags (as opposed to deep ETags, more about that later).The filter caches the content of the rendered JSP (or other content), generates an MD5 hash over that, and returns that as an ETag header in the response. 
The next time a client sends a request for the same resource, it uses that hash as the If-None-Match value. The filter detects this, renders the view again, and compares the two hashes. If they are equal, a 304 is returned. This filter will not save processing power, as the view is still rendered. The only thing it saves is bandwidth, as the rendered response is not sent back over the wire.

Example:










After that start the server and access the resource and observe the request/response readers. In the request you can see the If-None-Match header and in response ETag header. The value of both the headers are same.

















Sunday, September 14, 2014

Working with WebSocket

Before jumping into the WebSocket, I would like to briefly describe about the traditional request/response pattern. In traditional request/response pattern - client will request a resource from the server and server will respond back to the client with the resource. So, at a time one operation is being performed, it may be request or response. This mechanism is sometime called "Half Duplex" communication. 

WebSocket is also followed the same pattern but it is based on "Full Duplex" communication.

What is WebSocket

WebSocket is a communication protocol. It is full duplex communication protocol. It is working on top of TCP connection. WebSocket was designed to be work with Web Browsers and Web Servers.

In the traditional request-response model, the client requests resources, and the server provides responses. The exchange is always initiated by the client; the server cannot send any data without the client requesting it. This model worked well when clients made occasional requests for documents that changed infrequently, but the limitations of this approach are increasingly relevant as content changes quickly and users expect a more interactive experience on the Web. 

The WebSocket protocol addresses these limitations by providing a full-duplex communication channel between the client and the server. Currently WebSocket can be implemented using JavaScript, HTML5, Java etc.


Technical Details

WebSocket is working in client/server model. In WebSocket, WebSocket server publishes a endpoint and WebSocket client uses endpoint Url to invoke the server endpoint. After connection is established then the client and the server can send messages to each other at any time while the connection is open, and they can close the connection at any time. Clients usually connect only to one server, and servers accept connections from multiple clients.


The WebSocket protocol has two parts: handshake and data transfer. The client initiates the handshake by sending a request to a WebSocket endpoint using its URI. 

The handshake is compatible with existing HTTP-based infrastructure: web servers interpret it as an HTTP connection upgrade request. 

An example handshake from a client looks like this:

GET /path/to/websocket/endpoint HTTP/1.1Host: localhostUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==Origin: http://localhostSec-WebSocket-Version: 13

An example handshake from the server in response to the client looks like this:
HTTP/1.1 101 Switching Protocols

Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=

Handshaking Process

After getting the handshaking request from the client. Server applies a known operation to the HTTP header named Sec-WebSocket-Key. The server sends back new value to 
Sec-WebSocket-Accept HTTP header. Once the client got the response back from the server, client applies the same operation to Sec-WebSocket-Key HTTP header. After that client will check the new value with the value of HTTP header named 
Sec-WebSocket-Accept. If both the values are matching then connection from the client to server is established.

WebSocket supports text messages (encoded as UTF-8) and binary messages. 

The control frames in WebSocket are closeping, and pong (a response to a ping frame). Ping and pong frames may also contain application data.

WebSocket connection URI is given below. There are two flavour of WebSocket connection.

1. ws://localhost:8798/websockets/message - ws scheme is the unencrypted WebSocket connection to the server. It is similar to http scheme, if no port number is specified then will consider port 80.
2. wss://localhost:8798/websockets/message - wss scheme is the encrypted WebSocket connection to the server. It is similar to https scheme. If no port number is specified then will consider port 443.

Data transfer

Using WebSocket we can send data of type Text, Binary and Ping/Pong

WebSocket Life Cycle

In order to work with WebSocket, we have to deal with couple of WebSocket's life cycle methods. Life cycle callback methods are given below:

1. onOpen - Called during connection open.
2. onMessage - Called during message received.
3. onClose - Called during connection close.
4. onError - Called when error occurred in connection.


WebSocket Endpoint Designing approach

There are two approaches of designing WebSocket Endpoint. 

1. Programmatic Endpoint - To work with programmatic endpoint, endpoint have to extends from Endpoint class from package javax.websocket. The Endpoint class has only one abstract method i.e onOpen. So, you have to implement that. Also we have to implement onMessage method of message handler. To add message handler, we can use session object's addMessageHandler method.

2. Annotated Endpoint - To work with annotated endpoint, endpoint have to use some pre-defined annotations defined in package javax.websocket and javax.websocket.server. Following are the annotations need to use during defining Annotation based Endpoint. One important thing is that - if you choose annotation based implementation then you do not have to implement any message handler in order to use onMessage life cycle callback method.

1. @javax.websocket.server.ServerEndpoint - It is a class level annotation.
2. @javax.websocket.onOpen
3. @javax.websocket.onMessage
4. @javax.websocket.onClose
5. @javax.websocket.onError

WebSocket Supports

1. WebSocket API supports to maintain client state using session object. We will get session object in all life cycle callback methods.
2. WebSocket API also supports Encoders and Decoders message. Encoding helping to convert java object to WebSocket message. Decoding helping the reverse operation.
3. WebSocket allow us to use Path Parameters while declaring WebSocket Server Endpoint. After that we can use that parameter in any of the life cycle callback methods using @javax.websocket.server.PathParam annotation.
4. Better error handling using one of the life cycle callback method during connection problem, runtime error, error during conversion(encoding, decoding).
5. Supports granular level endpoint configuration.



For practical example please check this blog.

Thursday, June 5, 2014

Using Java Bean Validation (JSR-303)

Java Bean Validation is one of the new validation model in Java 6. This is under Java Specification Requests - 303. According to this specification Java provides an API for JavaBeans Validation. The Bean validation is just like a constraints in the form of annotations placed on fields, methods and class.

To maintain the data integrity is the responsibility of the application logic. So, to maintain the data integrity we have to process the user input before going into the business logic for further processing on the data entered. Before JSR-303, we have to write code to validate one-by-one each of the user input. So, we have to write lots of if..else statements in the code. Sometime it is bigger than the business logic and sometime is very hard to maintain.

So, Java 6 came up with a standardise validation rule API and validation rule engine. Nowadays in the market you can found couple of implementations of Java Bean Validation API (JSR-303). One of the most popular is Apache BVal, there are other also like Hibernate Validator , Spring 3 Validation 

Java standard bean validation API have some standard annotation, those I will be discussing in this post. But this is not the end. We have to look into the implementor's provided extra annotations. Sometime, we can get lots of help from those during the development work.

Standard API provides the following annotations for bean validation placed on fields, methods and class.

Constraint
Description
Example
@AssertFalse
The value of the field or property must be false.
@AssertFalse
boolean isUnsupported;
@AssertTrue
The value of the field or property must be true.
@AssertTrue
boolean isActive;
@DecimalMax
The value of the field or property must be a decimal value lower than or equal to the number in the value element.
@DecimalMax("30.00")
BigDecimal discount;
@DecimalMin
The value of the field or property must be a decimal value greater than or equal to the number in the value element.
@DecimalMin("5.00")
BigDecimal discount;
@Digits
The value of the field or property must be a number within a specified range. The integer element specifies the maximum integral digits for the number, and the fraction element specifies the maximum fractional digits for the number.
@Digits(integer=6, fraction=2)
BigDecimal price;
@Future
The value of the field or property must be a date in the future.
@Future
Date eventDate;
@Max
The value of the field or property must be an integer value lower than or equal to the number in the value element.
@Max(10)
int quantity;
@Min
The value of the field or property must be an integer value greater than or equal to the number in the value element.
@Min(5)
int quantity;
@NotNull
The value of the field or property must not be null.
@NotNull
String username;
@Null
The value of the field or property must be null.
@Null
String unusedString;
@Past
The value of the field or property must be a date in the past.
@Past
Date birthday;
@Pattern
The value of the field or property must match the regular expression defined in the regexp element.
@Pattern(regexp="\\(\\d{3}\\)\\d{3}-\\d{4}")
String phoneNumber;
@Size
The size of the field or property is evaluated and must match the specified boundaries. If the field or property is a String, the size of the string is evaluated. If the field or property is a Collection, the size of the Collection is evaluated. If the field or property is a Map, the size of the Map is evaluated. If the field or property is an array, the size of the array is evaluated. Use one of the optional max or minelements to specify the boundaries.
@Size(min=2, max=240)
String briefMessage;

Example:I am using MVN to build a project and manage project dependencies.

Step:1
In the command prompt type the command below:

mvn archetype:generate -DgroupId=org.wiki -DartifactId=MyBeanValidator -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Above statement will create a project in the current directory and put the POM file inside that directory.

I am using eclipse, so I have to tell maven to treat above project as a eclipse project. From the command prompt, go inside the directory and type the following.

mvn eclipse:eclipse

Now, you can import this project into the eclipse work space.

Step:2
Now you have to modify POM file to declare the dependency to the java bean validation API. One more thing is - I am using the Apache BVal as an implementation of the JSR-303


<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>org.wiki</groupId>
  <artifactId>MyBeanValidator</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>MyBeanValidator</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
    </dependency>
    <dependency>
    <groupId>org.apache.bval</groupId>
    <artifactId>org.apache.bval.bundle</artifactId>
    <version>0.5</version>
    </dependency>
  </dependencies>

</project>

Step:3

In the command prompt type the following:

mvn compile

above command download dependency and put into the maven local repository.

Step:4
package org.wiki;


import java.math.BigInteger;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.apache.bval.constraints.Email;
import org.apache.bval.constraints.NotEmpty;

public class Employee {
private BigInteger ID;
private String firstName;
private String lastName;
private String email;
private String phone;
@NotNull(message="ID can not be null.")
public BigInteger getID() {
return ID;
}
public void setID(BigInteger iD) {
ID = iD;
}
@NotNull(message = "First name is compulsory")
@Pattern(regexp = "[a-z-A-Z]*", message = "First name has invalid characters")
@NotEmpty(message="can not be blank.")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Email(message="Please enter valid email address.")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Pattern(regexp="[d(3)-d(7)]", message="Please enter a valid phone number")
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}

}

Step:5

package org.wiki;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

public class TestBeanValidation 
{
    public static void main( String[] args )
    {
        Employee emp = new Employee();
        emp.setEmail("prabir");
        emp.setFirstName("prabir123");
        
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        
        Set> violation = validator.validate(emp);
        
        for(ConstraintViolation a : violation)
        {
        System.out.println(a.getMessage());
        }
    }
}


Output:


Please enter valid email address.
First name has invalid characters
ID can not be null.

Enjoy! Java Bean Validation.

Please check my next blog post on Using Apache BVal's extra annotations for bean validation.

Monday, April 7, 2014

PrimeFaces with JSF2.0

The title of this post is self describing. This post is trying to describe advantages of PrimeFaces respect to other framework to create rich user interfaces with java  I know most of the developers are not aware of Primefaces, as because this is little bit newer than RichFaces, MyFaces and ICEFaces.

The developers who are using RichFaces, they can easily understand why using PrimeFaces instead of RichFaces and I know they are slowly migrating to PrimeFaces. Both of them are used for developing Rich Internet Applications(RIA). Now the question would be "what is Primefaces?".

PrimeFaces is an open source JSF component suite, It fully implements JSF. It is not only for web based application, it also provides modules for mobile web application. It has TouchFaces module for mobile web application.

PrimeFaces is the one, which provides complete implementation of JSF2.0, but others are not. The support for PrimeFaces is better than RichFaces. PrimeFaces component development is growing rapidly.

PrimeFaces provides 100+ components for JSF. Main goal of PrimeFaces is to create an ultimate component suit for JSF.

PrimeFaces components are lightweight, so the performance of the components are better than RichFaces, ICEFaces and MyFaces components. PrimeFaces provides only one jar file with no dependencies and nothing to configure, only setup needed is for JSF. 

There are several companies, who are recommending to use PrimeFaces, one of them is Spring. If you are using Spring and looking for a JSF front-end framework, then spring suggests to use PrimeFaces.

Rating of favourite framework to create rich user interfaces with java.



Interest trends of PrimeFace over time: