Saturday, May 7, 2016

Using Flame JMS Thin client

package org.flame.jms.client.test;

import static org.junit.Assert.*;

import javax.jms.ObjectMessage;

import org.flame.jms.client.helper.Credential;
import org.flame.jms.client.helper.IJmsMessageExecutor;
import org.flame.jms.client.helper.ITransaction;
import org.flame.jms.client.helper.JMSImplementation;
import org.flame.jms.client.remote.AbstractJmsMessageExecutor;
import org.flame.jms.client.remote.CorrelationIDGenerator;
import org.flame.jms.client.remote.IJmsConnectionConfiguration;
import org.flame.jms.client.remote.IJmsQueueConfiguration;
import org.flame.jms.client.remote.IMessageConnection;
import org.flame.jms.client.remote.IMessageSession;
import org.flame.jms.client.remote.JMSMessageProducer;
import org.flame.jms.client.remote.JmsTransportConfiguration;
import org.flame.jms.exceptions.FlameJMSClientException;
import org.flame.jms.exceptions.FlameMessageExecutionException;
import org.flame.jms.exceptions.FlameMessageFlowException;
//import org.apache.activemq.ActiveMQConnection;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class TestJmsClient {
private static Credential credential = null;
private static JmsTransportConfiguration transportConf = null;
private static IJmsConnectionConfiguration connectionConf = null;
private static IJmsQueueConfiguration queueConfig = null;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
String connUserName = "prabir";
String connPassword = "prabir4@mj";
credential = new Credential(connUserName, connPassword);
transportConf = new JmsTransportConfiguration(JMSImplementation.HORNETQ"127.0.0.1", credential);
connectionConf = transportConf.createConnectionConfiguration("jms/RemoteConnectionFactory", credential);
queueConfig = transportConf.createQueueConfiguration("jms/queue/asyncInbound");
}

@AfterClass
public static void tearDownAfterClass() throws Exception {
transportConf.release();
}

@Before
public void setUp() throws Exception {
}

@After
public void tearDown() throws Exception {
}

//@Test
public void testHornetQNonTransactional() {
try {
IJmsMessageExecutor executor = new AbstractJmsMessageExecutor(
connectionConf, queueConfig) {

public Void execute() throws FlameMessageFlowException {
ObjectMessage objectMsg = createObjectMessage(new AppMessage());
getProducer().send(objectMsg);
return null;
}
};
executor.run();
} catch (Exception e) {
e.printStackTrace();
Assert.fail();
}
}
@Test
public void testHornetQTransactional() {
try {
boolean isTransactional = true;
IJmsMessageExecutor executor = new AbstractJmsMessageExecutor(
connectionConf, queueConfig, isTransactional) {

public Void execute() throws FlameMessageFlowException {
ObjectMessage objectMsg = createObjectMessage(new AppMessage());
getProducer().send(objectMsg);
return null;
}
};
executor.run();
} catch (FlameMessageExecutionException e) {
e.printStackTrace();
Assert.fail();
}
}
//@Test
public void testHornetQTransactionalWithBeginTrxn() {
try {
boolean isTransactional = true;
IJmsMessageExecutor executor = new AbstractJmsMessageExecutor(
connectionConf, queueConfig, isTransactional) {

public Void execute() throws FlameMessageFlowException {
ObjectMessage objectMsg = createObjectMessage(new AppMessage());
ITransaction txn = beginTransaction();
getProducer().send(objectMsg);
txn.commit();
return null;
}
};
executor.run();
} catch (FlameMessageExecutionException e) {
e.printStackTrace();
Assert.fail();
}
}
//@Test
public void testHornetQTransactionalUnCommitted() {
try {
boolean isTransactional = true;
IJmsMessageExecutor executor = new AbstractJmsMessageExecutor(
connectionConf, queueConfig, isTransactional) {

public Void execute() throws FlameMessageFlowException {
ObjectMessage objectMsg = createObjectMessage(new AppMessage());
ITransaction txn = beginTransaction();
getProducer().send(objectMsg);
//txn.commit();
return null;
}
};
executor.run();
} catch (FlameMessageExecutionException e) {
e.printStackTrace();
Assert.fail();
}
}
@Test
public void testHornetQUnStructured() {
ITransaction txn = null;
try {
IMessageConnection conn = connectionConf.getConnection();
IMessageSession session = conn.createTransactionalSession();
JMSMessageProducer producer = session.createProducer(queueConfig);
txn = session.beginTransaction();
ObjectMessage objectMsg = session.createObjectMessage(new AppMessage());
producer.send(objectMsg);
txn.commit();

producer.close();
session.close();
} catch (Exception e) {
if(txn!=null)
{
txn.rollback();
}
e.printStackTrace();
Assert.fail();
}
}
@Test
public void testHornetQWithUserDefineCorrelationIDGenerator() {
ITransaction txn = null;
try {
IMessageConnection conn = connectionConf.getConnection();
IMessageSession session = conn.createTransactionalSession();
JMSMessageProducer producer = session.createProducer(queueConfig);
txn = session.beginTransaction();
ObjectMessage objectMsg = session.createObjectMessage(new AppMessage(), new CorrelationIDGenerator() {
@Override
public String generate() {
return "Correlation : " + 1;
}
});
producer.send(objectMsg);
txn.commit();

producer.close();
session.close();
} catch (Exception e) {
if(txn!=null)
{
txn.rollback();
}
e.printStackTrace();
Assert.fail();
}
}
@Test
public void testActiveMQ() {
try {
String connUserName = "admin";
String connPassword = "admin";
Credential credential = new Credential(connUserName, connPassword);
JmsTransportConfiguration transportConf2 = new JmsTransportConfiguration(JMSImplementation.ACTIVEMQ"localhost", credential);
IJmsConnectionConfiguration connectionConf2 = transportConf2.createConnectionConfiguration("ConnectionFactory", credential);
IJmsQueueConfiguration queueConfig2 = transportConf2.createQueueConfiguration("APPANALYZER_QUEUE");
IJmsMessageExecutor executor2 = new AbstractJmsMessageExecutor(
connectionConf2, queueConfig2) {
public Void execute() throws FlameMessageFlowException {
AppMessage msg = new AppMessage();
msg.setName("Prabir");
ObjectMessage objectMsg = createObjectMessage(msg);
getProducer().send(objectMsg);
return null;
}
};
executor2.run();
} catch (FlameMessageExecutionException e) {
e.printStackTrace();
Assert.fail();
} catch(FlameJMSClientException e) {
e.printStackTrace();
Assert.fail();
}
}

}

Tuesday, December 8, 2015

Choosing Hadoop Data Organisation for your Application

If you or your organisation decided to move to Hadoop solutions then you may need to think few points describe below on overall application design before moving to Hadoop. 

Data Storage : Data storage is one the important parts of overall application design in Hadoop. To do this correctly, you must understand which applications are going to access the data, and what is the access pattern. If data is mostly used by MapReduce implementation and sequential access of files then HDFS is the best option. Also data locality is also important in overall application performance. So, all those things are supported by HDFS.

File Format : File format is also an important factor while designing a Hadoop based application. If your application is most doing MapReduce processing then SequenceFiles will be the best option because its processing semantic is well aligned with MapReduce processing. SequenceFiles provides flexibility on providing compression on different level (Record, Block), it is more compact than regular text files, It provides Header records which contains meta data of the file, type of the file and also contains version information of the files. You can choose other file format specially when integrating with other applications. but you need to keep in mind about custom format as this will lead to additional complexities in reading, splitting and writing data.

Types of Calculation :  You need to think on the type of calculation you will be doing on the data. If you are considering all the data for the calculation then there is no additional considerations. But if your calculation considered on subset of the data, then you need to think on the data partitioning to avoid unnecessary data reads. The partitioning depends of the data usages pattern of the application. 

Data Conversion : As you know Hadoop/HBase is internally storing byte stream of the given data. So, you need to think on the data conversion of your data to byte stream. Here different potential options exists on marshalling/unmarshalling application specific data to byte stream. There are couple of standard Java marshalling approach. But here Apache Avro provides a generic approach for simplifying data marshalling. Avro provides both performance and compact data size. It also storing data definition along with the data and also provide data versioning.

Security : This is one of the important factor to secure data in HDFS or HBase. HDFS and HBase have quite a few security risks. The implementation of the overall security required application/enterprise-specifi solutions to ensure data security.



Monday, December 7, 2015

Distributed File Systems for Big Data

As you all aware that today Data plays a vital role for any kind of systems. Systems does not mean should belongs to IT (Information Technology). Now to justify above said, we can consider any food product company, company need to regularly survey their product's demand in market and future growth of the product and advertising of new product. One more thing we need to consider that the company mentioned above is multinational company. So, to start survey they need to hire someone, who can do the survey on behalf of the company and based of that survey management can decide their next course of action. As you know one person can not do the survey and eventually it will not be effective interns of cost and man power.

So, company decided to start advertisement of their product and the survey in social media web sites. Which is cost effective and less man power and high ROI (Return of Investment). Now, you have understanding that how Data is important and existence of that Data is also important. It is also important that how Data is organised. So that as and when required it can be available. As you can imaging how large data will be, basically there is no limit. Data will be growing and growing. Now, question is how social media will handle that amount data. All software giants are starts thinking and discover the way to manage and process large data. There are lots of algorithms has been developed and implemented to handle large data interns of size and processing. So, Big Data evolved.

It is also important that how Big Data is distributed so that data can be survive from the failure and easily available for processing to make the decision. So, Distributed File Systems comes into the picture to handle Big Data. DFS was also there before Big Data, but after Big Data evolution it is getting notable importance and existing DFS is also getting re-design.

A distributed file system is a file system that allows access to files via network. The advantage of a distributed file system is that you can share data among multiple hosts or nodes. There are couple of Distributed File Systems such as NFS, CIFS, HDFS and OwFS.

HDFS is widely known and is an open source file system that was influenced by Google's GFS.

For NFS or CIFS, Network Attached Storage (NAS), which is an expensive storage system, is typically used. Whenever you increase its capacity, therefore, there is a high infrastructure cost. 

On the other hand, as OwFS and HDFS allow you to use relatively economical hardware (commodity server), you can establish high-capacity storage at much lower cost.
However, OwFS or HDFS are not better than NFS or CIFS, which use NAS in all cases. For some purposes, you should use NAS. The same is true of OwFS and HDFS. As they are built for different purposes, you need to select one of these file systems according to the purpose of the internet server you are implementing.


Hadoop Distributed File System (HDFS)
Google developed Google File System (GFS), its unique distribution system, which stores information about webpages crawled by Google. Google published a paper on the GFS in 2003. HDFS (Hadoop) is an open source system developed using GFS as a model.
For this reason, HDFS has the same characteristics as GFS. HDFS separates a large file into chunks, and stores three of them into each datanode. In other words, one file is stored in multiple distributed data nodes. This also means that one file has three replicas. The typical size of a chunk is 64 MB.
The metadata about which data node stores the chunk is stored in the namenode. This allows you to read data from distributed files and perform operations by using MapReduce.


The namenode of HDFS manages the name space and metadata of all files and the information on file chunks. Chunks are stored in data nodes and these data nodes process file operation requests from the clients.
As explained above, in HDFS, large files can be distributed and stored effectively. Moreover, you can also perform distributed processing of operations by using the MapReduce framework based on the chunk location information.
Compared to OwFS, the weakness of HDFS is that it is not suitable for processing a large number of files. This is because a bottleneck can occur at the namenode. If the number of files increases, OOM (Out of Memory) occurs at the service daemon of the namenode, and consequently the daemon process is terminated.
The features of HDFS are as follows:
  • A large file is divided into chunks and distributed and stored into multiple data nodes.
  • The size of a chunk is usually 64 MB, each chunk has three replicas, and chunks are stored in different data nodes.
  • The information on these chunks is stored in the namenode.
  • It is advantageous for storing large files, though if the number of files is large, the burden of the namenode increases.
  • The namenode is a SPOF, and if a failure occurs at the namenode, HDFS will stop and must be restored manually.
As HDFS is written in Java, its interface (API) is also a Java API. However, you can also use C API by using JNI. 

There are some other distributed file systems these are GFS2, Swift, Ceph and pNFS.

GFS2
Google's GFS is to distributed file systems what the Beatles were to the music industry, in that many distributed file systems, including HDFS, were inspired by GFS.
However, GFS also has a huge structural weakness. It is vulnerable to namenode failure. Unlike HDFS, GFS has a slave namenode. This is why GFS is less susceptible to failures than HDFS. Despite its slave namenode, however, when a failure occurs at the master namenode, the transfer time is not short.
If the number of files increases, the amount of metadata also increases, and consequently the processing speed is deteriorated, and the total number of files available is also limited due to the limit of the memory size of the master server.
Usually the size of a chunk is 64 MB, and GFS is too inefficient to store data smaller than this size. Of course, you can reduce the size of a chunk, but if you reduce the size, the amount of metadata will increase. For this reason, even when there are many files smaller than 64 MB, it is still difficult to reduce the size of a chunk.
However, GFS2 overcomes this weakness of GFS. GFS2 uses a much more advanced metadata management method than GFS. The namenode of GFS2 has a distributed structure rather than a single master. In addition, it stores metadata in a correctable database, such as BigTable. Through this, GFS2 addresses the limit of the number of files and the vulnerability to a namenode failure.
As you can easily increase the amount of metadata to be processed, you can reduce the size of a chunk to 1 MB. The structure of GFS2 is expected to have a huge influence on approaches to improving the structure of most other distributed file systems.


Swift
Swift is an object storage system used in OpenStack, which is used by Rackspace Cloud and others. Swift uses a structure in which there is no separate master server, as Amazon S3 does. It uses a 3-level object structure (Account, Container and Object) to manage files. The Account object is a kind of account used to manage containers. The Container object is an object used to manage the Object object like a directory. It is like a bucket in Amazon S3. The Object is an object corresponding to a file. To access this Object, you should access the Account object and Container object, in that order. Swift provides REST API, and has a proxy server to provide the REST API. It uses a static table with the predefined location to which an object has been allocated, and this is called Ring. All servers in Swift share the Ring information and find the location of a desired object.
As the use of OpenStack has been growing rapidly with the participation of more and more large companies, Swift has recently been getting more attention. In Korea, KT is participating in OpenStack, and provides its KT uCloud server by using Swift.


Ceph
Ceph is a distributed file system with a unique metadata management method. Like other distributed file systems, it also manages the namespace and metadata of the entire file system by using the metadata server. But it features the operation of metadata servers in clusters and the dynamic adjustment of the namespace area by metadata according to the degree of load. This allows you to easily respond when load is concentrated on some parts, and easily expand metadata servers. Moreover, unlike other distributed file systems, it is compatible with POSIX. This means that you can access a file stored in the distributed file system as in the local file system.
It also supports REST API, and is compatible with the REST API of Swift or Amazon S3.
The most noticeable thing about Ceph is that it is included in Linux Kernel source. The released version is that high, but as Linux develops, Ceph may eventually become the main file system of Linux. It is also attractive as it is compatible with POSIX and supports kernel mount.


Parallel Network File System (pNFS)
As mentioned above, NFS has multiple versions. To resolve the scalability issue of the versions up to NFSv4, NFSv4.1 has introduced pNFS. This version enables you to process the content of a file and its metadata separately, and to store a single file in multiple distributed places. If the client brings the metadata of a certain file and learns the location of the file, it will be connected to servers that contain the content of the file when it accesses the same file later. At this time, the client can read or write the content of the file in multiple servers in parallel. You can also easily expand the metadata server, which manages metadata, to prevent the occurrence of a bottleneck phenomenon.
pNFS is an advanced version of NFS, and reflects the recent trends of distributed file systems. Therefore, pNFS has the advantages of NFS, as well as the advantages of the latest distributed file systems. Currently, there are some, if not many, products that support pNFS being released.

One of the reasons we should pay attention to pNFS is that currently NFS is not managed by Oracle (Sun) but by the Internet Engineering Task Force (IETF). NFS is used as a standard in many Linux/Unix environments, and thus pNFS may be popularized if many vendors release products that support pNFS.

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.