Monday, December 31, 2012

Json deserialization with Jackson and Super type tokens

Datatables is a jquery plugin to present tabular information - it can enhance a simple table or can use a AJAX based data and present the information in a tabular form.

Datatables requires the data from the server to follow a specific JSON format for it to be displayed on screen. Consider the case where a list of Member entities is to be displayed, the expected json structure for Members then has to be along these lines:


{
   "aaData":[
      {
         "id":1,
         "first":"one",
         "last":"one",
         "addresses":[

         ],
         "version":0
      },
      {
         "id":2,
         "first":"two",
         "last":"two",
         "addresses":[

         ],
         "version":0
      }
   ],
   "iTotalRecords":100,
   "iTotalDisplayRecords":10,
   "success":true
}

A generic java type can be defined which Jackson can use to generate json of the type shown above, consider the following Java generic type:

package mvcsample.types;
import java.util.List;

public class ListWrapper<T> {
    private List<T> aaData;
    private int iTotalRecords;
    private int iTotalDisplayRecords;
    private  Boolean success;

    public List<T> getAaData() {
  return aaData;
 }
 public void setAaData(List<T> aaData) {
  this.aaData = aaData;
 }
 public int getiTotalRecords() {
  return iTotalRecords;
 }
 public void setiTotalRecords(int iTotalRecords) {
  this.iTotalRecords = iTotalRecords;
 }
 public int getiTotalDisplayRecords() {
  return iTotalDisplayRecords;
 }
 public void setiTotalDisplayRecords(int iTotalDisplayRecords) {
  this.iTotalDisplayRecords = iTotalDisplayRecords;
 }
 public Boolean getSuccess() {
  return success;
 }
 public void setSuccess(Boolean success) {
  this.success = success;
 }   
}

So, with this generic type, to generate a list of Members I would have a parameterized type defined as in this test:

List<Member> members = new ArrayList<>();
members.add(new Member("one", "one"));
members.add(new Member("two", "two"));
ListWrapper<Member> membersWrapper = new ListWrapper<>();
membersWrapper.setAaData(members);
membersWrapper.setiTotalDisplayRecords(10);
membersWrapper.setiTotalRecords(100);
ObjectMapper objectMapper = new ObjectMapper();

StringWriter w = new StringWriter();
objectMapper.writeValue(w, membersWrapper);
String json = w.toString();
System.out.println(json);

And similarly a json for any other type can be generated.

However, what about the other way around, generating the Java type given the json.

Again, consider a case where the json given in the beginning is to be converted to ListWrapper<Member> , I can try a deserialization this way:

ObjectMapper objectMapper = new ObjectMapper();  
ListWrapper<Member> membersUpdated = objectMapper.readValue(json, ListWrapper.class);

Note that above I cannot refer to the class type as ListWrapper<Member>.class, I can only refer to it as ListWrapper.class.

This however will not work and the resulting type will not be a wrapper around Member class, as at runtime Jackson has no idea that it has to generate a ListWrapper<Member>.

The fix is to somehow pass the information about the ListWrapper's type to Jackson and this is where Super type tokens fits in. The article explains how this works in great detail, the essence is that
while type erasure does remove the type information from parameterized instances of generic type, however the type is retained in subclasses of generic classes.

For eg. Consider the following StringList class which derives from ArrayList<String> , it is possible to find that the type parameter of the base class is a String as shown in the test below:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;

public class StringList extends ArrayList<String>{

 public static void main(String[] args) {
  StringList list = new StringList();
  Type superClassType = list.getClass().getGenericSuperclass();
  ParameterizedType parameterizedType = (ParameterizedType)superClassType;
  System.out.println(parameterizedType.getActualTypeArguments()[0]);
 }
}

This is applicable for a case where a subclass is defined as an anonymous class also this way:

ArrayList<String> list = new ArrayList<String>(){};
Type superClassType = list.getClass().getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType)superClassType;
System.out.println(parameterizedType.getActualTypeArguments()[0]);

This is what is used internally with the Super Type tokens pattern to find the type of the parameterized type. Jackson's com.fasterxml.jackson.core.type.TypeReference abstract class implements this and using this the Jackson deserialization would work this way:

import com.fasterxml.jackson.core.type.TypeReference;

....
ListWrapper<Member> membersWrapper = objectMapper.readValue(json, new TypeReference<ListWrapper<Member>>() {});

ListWrapper<Address> addressWrapper = objectMapper.readValue(json, new TypeReference<ListWrapper<Address>>() {});

This way two different parameterized types can be deserialized given a generic type and a json representation.


References:

Reflecting Generics: http://www.artima.com/weblogs/viewpost.jsp?thread=208860

Neal Gafter's Super type tokens: http://gafter.blogspot.com/2006/12/super-type-tokens.html

Thursday, December 27, 2012

Spring Data JPA and pagination

Let us start with the classic JPA way to support pagination.

Consider a simple domain class - A "Member" with attributes first name, last name. To support pagination on a list of members, the JPA way is to support a finder which takes in the offset of the first result(firstResult) and the size of the result(maxResults) to retrieve, this way:

import java.util.List;

import javax.persistence.TypedQuery;

import org.springframework.stereotype.Repository;

import mvcsample.domain.Member;

@Repository
public class JpaMemberDao extends JpaDao<Long, Member> implements MemberDao{

 public JpaMemberDao(){
  super(Member.class);
 }
 @Override
 public List<Member> findAll(int firstResult, int maxResults) {
  TypedQuery<Member> query = this.entityManager.createQuery("select m from Member m", Member.class);
  return query.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
 }

 @Override
 public Long countMembers() {
  TypedQuery<Long> query = this.entityManager.createQuery("select count(m) from Member m", Long.class);
  return query.getSingleResult();
 }
}

An additional API which returns the count of the records is needed to determine the number of pages for the list of entity, as shown above.

Given this API, two parameters are typically required from the UI:


  • the current page being displayed (say "page.page")
  • the size of list per page (say "page.size")
The controller will be responsible for transforming these inputs to the one required by the JPA - firstResult and maxResults this way:

@RequestMapping(produces="text/html")
public String list(@RequestParam(defaultValue="1", value="page.page", required=false) Integer page, 
   @RequestParam(defaultValue="10", value="page.size", required=false) Integer size, Model model){
 int firstResult = (page==null)?0:(page-1) * size;
 model.addAttribute("members",this.memberDao.findAll(firstResult, size));
 float nrOfPages = (float)this.memberDao.countMembers()/size;
 int maxPages = (int)( ((nrOfPages>(int)nrOfPages) || nrOfPages==0.0)?nrOfPages+1:nrOfPages);
 model.addAttribute("maxPages", maxPages);
 return "members/list";
}

Given a list as a model attribute and the count of all pages(maxPages above), the list can be transformed to a simple table in a jsp, there is a nice tag library that is packaged with Spring Roo which can be used to present the pagination element in a jsp page, I have included it with the reference.



So this is the approach to pagination using JPA and Spring MVC.

Spring-Data-JPA makes this even simpler, first is the repository interface to support retrieving a paginated list - in its simplest form the repository simply requires extending Spring-Data-JPA interfaces and at runtime generates the proxies which implements the real JPA calls:

import mvcsample.domain.Member;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

public interface MemberRepository extends JpaRepository<Member, Long>{
 //
}

Given this, the controller method which accesses the repository interface is also very simple:

@RequestMapping(produces="text/html")
public String list(Pageable pageable, Model model){
 Page<Member> members = this.memberRepository.findAll(pageable);
    model.addAttribute("members", members.getContent());
    float nrOfPages = members.getTotalPages();
    model.addAttribute("maxPages", nrOfPages);
 return "members/list";
}

The controller method accepts a parameter called Pageable, this parameter is populated using a Spring MVC HandlerMethodArgumentResolver that looks for request parameters by name "page.page" and "page.size" and converts them into the Pageable argument. This custom HandlerMethodArgumentResolver is registered with Spring MVC this way:

<mvc:annotation-driven>
 <mvc:argument-resolvers>
  <bean class="org.springframework.data.web.PageableArgumentResolver"></bean>
 </mvc:argument-resolvers>
</mvc:annotation-driven> 

the JpaRepository API takes in the pageable argument and returns a page, internally automatically populating the count of pages also which can retrieved from the Page methods.

If the queries need to be explicitly specified then this can be done in a number of ways, one of which is the following:

@Query(value="select m from Member m", countQuery="select count(m) from Member m")
Page<Member> findMembers(Pageable pageable);


One catch which I could see is that that pageable's page number is 0 indexed, whereas the one passed from the UI is 1 indexed, however the PageableArgumentResolver internally handles and converts the 1 indexed UI page parameter to the required 0 indexed value.

Spring Data JPA thus makes it really simple to implement a paginated list page.

I am including a sample project which ties all this together, along with the pagination tag library which makes it simple to show the paginated list.

Reference:
A sample projects which implements a paginated list is available here : https://github.com/bijukunjummen/spring-mvc-test-sample.git

Spring-Data-JPA reference: http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/




Sunday, December 23, 2012

context:component-scan, context:annotation-config and list of beans registered

A <context:component-scan/> custom tag registers the same set of bean definitions as is done by <context:annotation-config/>, apart from its primary responsibility of scanning the java packages and registering bean definitions from the classpath.

The following bean types are registered by either of these custom tags:


Bean Purpose
ConfigurationClassPostProcessor
A bean factory post processor used for bootstrapping classes annotated with @Configuration
AutowiredAnnotationBeanPostProcessor
A bean post processor which processes fields, setter methods, arbitrary methods annotated with @AutoWired, @Value and supports JSR-330 @Inject annotation
RequiredAnnotationBeanPostProcessor
A bean post processor which enforces that the required bean properties have been set - by looking for fields annotated with @Required annotation
CommonAnnotationBeanPostProcessor
A bean post processor which supports JSR-250 annotations - eg. @Resource
PersistenceAnnotationBeanPostProcessor
A bean post processor that processes @PersistenceUnit and @PersistenceContext annotations for injecting in a EntityManagerFactory and EntityManager respectively.

This is the reason why if component-scan is present, annotation-config can be kept out.

If for some reason this registration of default bean definitions are to be avoided, the way to do that is to specify an additional "annotation-config" attribute in component-scan, this way:



<context:component-scan basePackages=".." annotation-config="false"/>

Reference:
Spring Reference site

Sunday, December 9, 2012

Composing Java annotations

The allowed attribute types of a Java annotations are deliberately very restrictive, however some clean composite annotation types are possible with the allowed types.

Consider a sample annotation from the tutorial site:

package annotation;
@interface ClassPreamble {
   String author();
   String[] reviewers();
}

Here the author and reviewers are of String and array types which is in keeping with the allowed types of annotation attributes. The following is a comprehensive list of allowed types(as of Java 7):


  • String
  • Class
  • any parameterized invocation of Class
  • an enum type
  • an annotation type, do note that cycles are not allowed, the annotated type cannot refer to itself
  • an array type whose element type is one of the preceding types.

Now, to make a richer ClassPreable consider two more annotation types defined this way:

package annotation;

public @interface Author {
 String first() default "";
 String last() default "";
}


package annotation;

public @interface Reviewer {
 String first() default "";
 String last() default "";
}


With these, the ClassPreamble can be composed from the richer Author and Reviewer annotation types, this way:

package annotation;
@interface ClassPreamble {
   Author author();
   Reviewer[] reviewers();
}

Now an annotation applied on a class looks like this:

package annotation;

@ClassPreamble(author = @Author(first = "John", last = "Doe")
    , reviewers = {@Reviewer(first = "first1", last = "last1"), @Reviewer(last = "last2") }
)
public class MyClass {
....
}

This is a contrived example just to demonstrate composition of annotations, however this approach is used extensively for real world annotations, for eg, to define a many to many relationship between two JPA entities:

    @ManyToMany
    @JoinTable(name="Employee_Project",
          joinColumns=@JoinColumn(name="Employee_ID"),
          inverseJoinColumns=@JoinColumn(name="Project_ID"))
    private Collection<Project> projects;