Archive for May 2011

Handling alien Java types in XML messages

Most of times we find ourself in situations where the XML instance doesn't fully comply with the available Java types.

Let's define a near real world problem to understand this.

Problem: Need to process XML message coming from some XYZ source we don't have control on( the message format is shown below). As can be seen dob element has value as date of birth for Nikhil but is surrounded by brackets [ and ]. Now if we want to unmarshal this message to Person object than with this limitation we will have to declare dob as String and then provide some more methods to parse date every time we process this XML message.

So what should we do - declare dob as String?


Nikhil
[1986-08-27]


Answer is NO, we can use adapters, how? be patient ..

Let's first define our domain object
// members are public just to keep it short..
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Person {

 @XmlElement
 public String name;

 @XmlElement
 @XmlJavaTypeAdapter(DateAdapter.class)
 public Date dob;

}
As can be seen above we have declared dob as of type Date only, but how it can be populated with the kind of values we are getting, you got it - yes it is our DateAdapter class who is going to manage this, let's see how:
/**
  * Our custom dob adapter.
  */
 class DateAdapter extends XmlAdapter<String, Date> {
  
  static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

  public DateAdapter() {
  }

  @Override
  public String marshal(Date date) throws Exception {
   // while sending message back to the source we will obey its format
   return "[" + format.format(date) + "]";
  }

  @Override
  public Date unmarshal(String dob) throws Exception {
   // remove unwanted characters and build date
   dob = dob.replace("[", "").replace("]", "");
   return format.parse(dob);
  }

 }

Let's unmarshal the message now:

JAXBContext context = JAXBContext.newInstance(Person.class);
  Unmarshaller unmarshal = context.createUnmarshaller();
// employee file is the source of message in this example
  Person person = (Person) unmarshal.unmarshal(new File("employee"));

  Assert.assertEquals("Nikhil", person.name);
  Assert.assertEquals("Wed Aug 27 00:00:00 SGT 1986", person.dob
    .toString());


and marshalling our new Person object works fine too :)

Person person = new Person();
  person.name="Toshi";
  person.dob= format.parse("2010-10-10");
  
  Marshaller marshaller = context.createMarshaller();
  marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  marshaller.marshal(person, System.out);
// The console output is shown below:

  
      Toshi
      [2010-10-10]
  
This is exactly what we expect, value of dob within brackets. This was just a simple example to demonstrate the power of adapters for handling alien types in Java XML world. Hope you can also use this approach in some of your Projects.

See you later !!!
Saturday, May 14, 2011
Posted by Unknown

Converting JSF <h:dataTable/> to <annaRascla:RajniKant/> table ...



By RajniKant table I mean a readonly table that has all the features (sorting, pagination, searching etc). Most developers who are struck with JSF RI implementation know already how difficult it is to provide all these mentioned features. Suddenly you think of moving to PrimeFaces, RichFaces, BlaBlaFaces etc. but hey stop a while I have something special for you in today's post.

In the next section I will try to convert one simple <h:datatable> to <annaRascla:RajniKant> table as per the description of Rajnikant table.

Let's assume we have an existing JSF data table as shown below and suddenly there is a requirement to provide pagination and sorting capabilities.


   

The table looks exactly same as shown below:

Nothing fancy :(, lets move to make it live.

We will use DataTables plug-in for the jQuery Javascript library to make it happen.

  
  
  
  
 
 
  
   
Points to note
  • The tags htmlhead and htmlbody shown above correspond to usual HEAD and BODY tags of html language (Blogger doesn't allow these tags)
  • The reason for not using table id (form:mytable) in ready(function) is that Datatables plugin doesn't accept id of the table having colon in the name itself :( and we all know that JSF generates Ids like this, so how I provide the id of my table? Simple provide the unique class name of that element :)
  • Use this approach if the table is not very large, for large tables you can use ajax capabilities of the plugin, check Project's home page for more details.
  • All the resources above (css and js) come from the artifacts we downloaded earlier
Having made these changes, let's see how our simple table looks now:


The only word that come to my mind is WOW, as can be seen it has:

> Sorting feature
> Pagination feature
> Search feature
> Simple and clean design

Thanks everyone.
Posted by Unknown

Building RESTful WS with JAX-RS (Jersey) and Tomcat

This post is dedicated to my friend jagdish salgotra who wanted me to write something on RESTful web services and to all starters in this area.

In the REST(REpresentational State Transfer) world, information on the server side is considered a resource, which anyone can access in a uniform way using web URIs (Uniform Resource Identifiers) and HTTP. Because REST uses HTTP as the communication protocol, the REST style is constrained to a stateless client/server architecture. We can map the HTTP methods POST, GET, PUT, and DELETE to create, read, update and delete (CRUD) operations.

There are many ways to write RESTful web services:
> Sun offers a reference implementation for JAX-RS code-named Jersey.
> Spring provides RestTemplate for the same purpose

In this sample example (very basic and naive just to give u all a gentle kick) I will try to explain how we can use DEPARTMENT as representational state in REST using GET method. We will try to map following urls to the particular state we are interested in using Jersey implementation.

/api/departments/Get all departments
/api/departments/{id}Get details of a particular department
/api/departments/employeesGet all departments with employee details
/api/departments/{id}/employeesGet employees of particular department

NOTE: All employees related data will be available under department node (by design)

The output of the Restful web services can be a plain text, html, xml, json or any media type, For our example We will use XML as content type of our service output and will rely on JAXB annotations to provide the required marshaling/unmarshaling services.

Let's start with the root XML element. I chose to call mine GetDepartmentResponse, and use it as a container for a collection of Department objects. This is just to do with the convention I usually follow (no hard fast rules behind this).
package com.mg.rest.hr.resources;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class GetDepartmentResponse {

 private List<Department> departments;

 @XmlElement(name = "department")
@XmlElementWrapper(name = "departments")
 public List<Department> getAllDepartments() {
  if (departments == null) {
   departments = new ArrayList<Department>();
  }
  return departments;
 }

}

Notice the @XmlElementWrapper annotation on the Department collection. This makes JAXB wrap all of the department XML elements inside of an departments XML element. Also notice that I placed the @XmlElement annotations on the getter methods instead of on the private fields. When placed on the private fields, JAXB will give you an error unless you add @XmlAccessorType(XmlAccessType.FIELD) at the class level.

Next we define our Resources - Department and Employee

package com.mg.rest.hr.resources;

import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlType;

/**
 * 
 * @author Munish Gogna
 *
 */
@XmlType(name = "department")
public class Department {

 private String deptId;
 private String deptName;
 private List<Employee> employees;

 public Department() {
 }

 @XmlElement
 public String getDeptId() {
  return deptId;
 }

 @XmlElement(name = "employee")
 @XmlElementWrapper(name = "employees")
 public List<Employee> getEmployees() {
  return employees;
 }

 @XmlElement
 public String getDeptName() {
  return deptName;
 }

 public void setDeptId(String deptId) {
  this.deptId = deptId;
 }

 public void setEmployees(List<Employee> employees) {
  this.employees = employees;
 }

 public void setDeptName(String deptName) {
  this.deptName = deptName;
 }

}

In the example above, we use @XmlType at the class level instead of @XmlRootElement because it is not the root element

package com.mg.rest.hr.resources;

import java.math.BigDecimal;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 * 
 * @author Munish Gogna
 * 
 */
@XmlType(propOrder = { "empId", "empName", "salary" })
public class Employee {

 private String empId;
 private String empName;
 private BigDecimal salary;

 public Employee() {
 }

 public Employee(String empId, String empName, BigDecimal salary) {
  super();
  this.empId = empId;
  this.empName = empName;
  this.salary = salary;
 }

 @XmlElement
 public BigDecimal getSalary() {
  return salary;
 }

 @XmlElement
 public String getEmpId() {
  return empId;
 }

 @XmlElement
 public String getEmpName() {
  return empName;
 }

 public void setEmpId(String empId) {
  this.empId = empId;
 }

 public void setEmpName(String empName) {
  this.empName = empName;
 }

 public void setSalary(BigDecimal salary) {
  this.salary = salary;
 }

}


Now lets create a JAX-RS RESTful web service that can return above defined object graph in the responses we have defined in the beginning of this article.

JAX-RS defines a resource as any Java class (POJO) that uses JAX-RS annotations to implement a web resource. The annotation @Path identifies a Java class as a resource class as shown below.

package com.mg.rest.hr;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

import com.mg.rest.hr.resources.Department;
import com.mg.rest.hr.resources.GetDepartmentResponse;

/**
 * Service to handle Department and related resources.
 * Just a mock implementation, nothing fancy.
 * @author Munish Gogna
 *
 */
@Path("/api")
public class DepartmentResource {

 @GET
 @Produces("text/xml")
 @Path("/departments/employees")
 public GetDepartmentResponse getAllDepartmentsWithEmployees() {
  GetDepartmentResponse response = new GetDepartmentResponse();
  response.getAllDepartments().addAll(
    FromHeaven.getDeptsWithEmps().values());
  return response;
 }

 @GET
 @Produces("text/xml")
 @Path("/departments/{id}")
 public GetDepartmentResponse getDepartment(@PathParam("id") String id) {
  GetDepartmentResponse response = new GetDepartmentResponse();
  Department dept = FromHeaven.getDepts().get(id);
  response.getAllDepartments().add(dept);
  return response;
 }

 @GET
 @Produces("text/xml")
 @Path("/departments/{id}/employees")
 public GetDepartmentResponse getEmployeesForDepartment(
   @PathParam("id") String id) {
  GetDepartmentResponse response = new GetDepartmentResponse();
  Department dept = FromHeaven.getDeptsWithEmps().get(id);
  response.getAllDepartments().add(dept);
  return response;

 }

 @GET
 @Produces("text/xml")
 @Path("/departments")
 public GetDepartmentResponse getAllDepartments() {
  GetDepartmentResponse response = new GetDepartmentResponse();
  response.getAllDepartments().addAll(FromHeaven.getDepts().values());
  return response;

 }
}


Notice the @Produces("text/xml") annotation, and that the method returns a GetDepartmentResponse object. Since the GetDepartmentResponse is annotated with JAXB annotations, JAX-RS will automatically marshal the response to XML.
Also note that FromHeaven is a utility class that provides dummy departmental data(This class has 2 hard coded departments D1 and D2 with 2 employees in D1 and only single employee in D2)

Let's try some URIs now:

1. http://localhost:8080/rest/api/departments

 
  
   D2
   Human Resource
  
  
   D1
   Finance
  
 


2. http://localhost:8080/rest/api/departments/D1

 
  
   D1
   Finance
  
 


3. http://localhost:8080/rest/api/departments/employees

 
  
   D1
   Finance
   
    
     e1
     Munish Gogna
     1000
    
    
     e2
     Jagdish Salgotra
     2000
    
   
  
  
   D2
   Human Resource
   
    
     e3
     Sahil Gogna
     5000
    
   
  
 


4.http://localhost:8080/rest/api/departments/D1/employees

 
  
   D1
   Finance
   
    
     e1
     Munish Gogna
     1000
    
    
     e2
     Jagdish Salgotra
     2000
    
   
  
 


In order for Jersey to work, we need to configure the JAX-RS Servlet in the web.xml as shown below:


 
  com.mg.rest.hr
  JAX-RS REST Servlet
  com.sun.jersey.spi.container.servlet.ServletContainer
  
   com.sun.jersey.config.property.packagescom.mg.rest.hr
  1
 
 
  JAX-RS REST Servlet
  /*
 


Notice that we have to provide the package name (com.mg.rest.hr) of the resource handler classes to the servlet class.

That's all for now, later some day we will try make these RESTful services secure so that only authorized callers can use these resources.

Please don't forget to provide your valuable feedback, especially you Jagi :)
Sunday, May 8, 2011
Posted by Unknown

Saving ENUM values as String in database using JPA

First of all nothing very fancy or technical about this post :)

Let's say you have an enum declaration as shown below and you want to store these values as String (not the evil ordinals) in the database:

public enum UserSex {
 MALE, FEMALE, UNKNOWN
}

To save this enum as String in database, the table where this enum is referenced should declare a column of type varchar as shown below:
`user_sex` varchar(255) DEFAULT NULL

The entity (say User) should use this enumeration as shown below:

@Entity
@Table(name = "user")
public class User {

private Integer id;
private UserSex userSex;

@Id
public Integer getId() {
 return id;
}

@Enumerated(EnumType.STRING)
 @Column(name ="user_sex")
 public UserSex getUserSex() {
  return userSex;
 }

 public void setId(Integer id) {
  this.id = id;
 } 

 public void setUserSex(UserSex userSex) {
  this.userSex = userSex;
 }

That's all. Now if you want to load all MALE users, you can use this column in JPA queries as

public List<User> getAllMaleUsers() {
  return entityManager.createQuery(
    "select user from User as user where user.userSex=:userSex")
    .setParameter("userSex", UserSex.MALE).getResultList();
 }

Please note that this will work only in case you have complete control on the database side, in case the column is declared as integer or varchar having length say 1 then you will have to write your own converter or fall back to evil ordinal().

NOTE: I'm guessing but I'm pretty sure that for using ENUM as String hibernate 3.2+ is required. So if anyone out there is interested in knowing my POM dependencies then here are they (specific to JBOSS AS 5.1.0 deployment)


   
javaee
   javaee-api
   5
   compile
  
  

   javax.persistence
   ejb3-persistence
   1.0
   provided
  
  
   org.hibernate
   hibernate-entitymanager
   3.3.1.ga
   
    
     javax.persistence
     persistence-api
    
    
     jboss
     jboss-common-core
    
    
     jboss
     javassist
    
   
  
Sunday, May 1, 2011
Posted by Unknown
Tag : ,

Popular Post

Labels

enums (1) java (2) JAX-RS (1) JPA (1) mysql (1) request 2 (1) RESTful (1) sphinx (1) tomcat (1) web service (2) ws (2)