Monday, October 21, 2013

REST with JAX-RS: Part 3 - Embedded Jetty

See previous posts:
There is one feature which I'd like to add. It's embedded Jetty server. I.e. we should be able to run our application from main() method.

Update pom.xml, add jetty server as dependency
...
 <org.eclipse.jetty.version>9.0.6.v20130930</org.eclipse.jetty.version>
...
 
    org.eclipse.jetty
    jetty-webapp
    ${org.eclipse.jetty.version}
 
...
Create special Launcher class which runs embedded Jetty Server. Jetty configuration registers port, host, base REST URL ("/api/*") and the most important - proper Spring config.
package com.halyph;

import com.halyph.config.AppConfig;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;


public class Launcher {

    public static final int PORT = 8080;

    public static void main(final String[] args) throws Exception {
        Server server = new Server(PORT);

        // Register and map the dispatcher servlet
        final ServletHolder servletHolder = new ServletHolder(new CXFServlet());
        final ServletContextHandler context = new ServletContextHandler();
        context.setContextPath("/");
        context.addServlet(servletHolder, AppConfig.API_BASE);
        context.addEventListener(new ContextLoaderListener());

        context.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
        context.setInitParameter("contextConfigLocation", AppConfig.class.getName());

        server.setHandler(context);
        server.start();
        server.join();
    }
}



   You can find sources on GitHub

References
  1. Going REST: embedding Jetty with Spring and JAX-RS (Apache CXF)
  2. Embedding Jetty or Tomcat in your Java Application

Sunday, October 20, 2013

REST with JAX-RS: Part 2 - Spring Java Config and CXF Improvement

See previous post:
Sample application from part 1 has several issues:
  1. It doesn't have application wide REST exception handler. This handler should catch and wrap all internal exceptions and present in some "standard" JSON format
  2. There are no autowiring for REST Resources and JAX-RS providers. I.e. we shouldn't declare REST service beans/providers manually in AppConfig (see part1)
  3. CXF object mapper (Jackson) should be configured and registered in CXF somehow
Let's try to fix all these issues.

JAX-RS has special approach for exception handling - ExceptionMapper.
Let's define two mappers:
  • GeneralExceptionMapper - will catch and handle all Exceptions
  • NotFoundExceptionMapper - will catch and handle only NotFoundException
 
package com.halyph.rest.provider;

import javax.ws.rs.NotFoundException;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class NotFoundExceptionMapper implements ExceptionMapper<NotFoundException> {
    /**
     * Map an exception to a {@link javax.ws.rs.core.Response}.
     *
     * @param exception the exception to map to a response.
     * @return a response mapped from the supplied exception.
     */
    @Override
    public Response toResponse(final NotFoundException exception) {
        Map<String, Object> info = new HashMap<>();
        info.put("msg", exception.getMessage());
        info.put("date", new Date());
        info.put("details", "The requested resource hasn't been found");

        return Response
                .status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(info)
                .type(MediaType.APPLICATION_JSON)
                .build();
    }
}
 
package com.halyph.rest.provider;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class GeneralExceptionMapper implements ExceptionMapper<exception> {
    /**
     * Map an exception to a {@link javax.ws.rs.core.Response}.
     *
     * @param exception the exception to map to a response.
     * @return a response mapped from the supplied exception.
     */
    @Override
    public Response toResponse(final Exception exception) {
        Map<String, Object> info = new HashMap<>();
        info.put("msg", exception.getMessage());
        info.put("date", new Date());

        return Response
                .status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(info)
                .type(MediaType.APPLICATION_JSON)
                .build();
    }
}

And, modify UserResource which throws NotFoundException when some user can't be found by specified id
 
@RestService
@Path("/users")
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public class UserResource {

 ...
    @GET
    @Path("/{id}")
    public User getUser(@PathParam("id") Integer id) {
        User user = service.getUser(id);
        if (user == null) {
            throw new NotFoundException();
        } else {
            return user;
        }
    }

    ...
}

Now, we have to implement REST resource/provider autowiring. 1st we create custom @RestService annotation.
 
package com.halyph.util.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface RestService {
}

Now we have to implement Spring bean scanners which scan specified package and register "selected" beans in Spring context.

 
package com.halyph.util;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import javax.ws.rs.ext.Provider;
import java.util.ArrayList;
import java.util.List;

public final class RestProviderBeanScanner {

    private RestProviderBeanScanner() { }
    public static List<Object> scan(ApplicationContext applicationContext, String... basePackages) {
        GenericApplicationContext genericAppContext = new GenericApplicationContext();
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(genericAppContext, false);

        scanner.addIncludeFilter(new AnnotationTypeFilter(Provider.class));
        scanner.scan(basePackages);
        genericAppContext.setParent(applicationContext);
        genericAppContext.refresh();

        return new ArrayList<>(genericAppContext.getBeansWithAnnotation(Provider.class).values());
    }
}
 
package com.halyph.util;

import com.halyph.util.annotation.RestService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.type.filter.AnnotationTypeFilter;

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

public final class RestServiceBeanScanner {

    private RestServiceBeanScanner() { }

    public static List<Object> scan(ApplicationContext applicationContext, String... basePackages) {
        GenericApplicationContext genericAppContext = new GenericApplicationContext();
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(genericAppContext, false);

        scanner.addIncludeFilter(new AnnotationTypeFilter(RestService.class));
        scanner.scan(basePackages);
        genericAppContext.setParent(applicationContext);
        genericAppContext.refresh();

        List<Object> restResources = new ArrayList<>(genericAppContext.getBeansWithAnnotation(RestService.class).values());

        return restResources;
    }
}
These two classes (scanner) RestServiceBeanScanner and RestProviderBeanScanner are almost identical and should be refactored to support generic scanner type. Let's left this for home work.

There is additional issue with missed Object Mapper configuration:
 
package com.halyph.rest.provider;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

@Provider
public class ObjectMapperProvider implements ContextResolver<Objectmapper> {

    final ObjectMapper objectMapper;

    public ObjectMapperProvider() {
        this.objectMapper = new ObjectMapper();
        this.objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

        //set up ISO 8601 date/time stamp format:
        final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:sss'Z'");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        this.objectMapper.setDateFormat(df);
    }

    @Override
    public ObjectMapper getContext(Class type) {
        return this.objectMapper;
    }
}

We have to update AppConfig:
  •  Add @ComponentScan to register services
  • Call RestProviderBeanScanner to register providers: json provider, ExceptionMapper and  ObjectMapperProvider
  • Call RestServiceBeanScanner to register REST services marked with @RestService annotation
 
package com.halyph.config;

import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.halyph.util.RestProviderBeanScanner;
import com.halyph.util.RestServiceBeanScanner;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.RuntimeDelegate;
import java.util.List;

@Configuration
@ComponentScan(AppConfig.SERVICE_PACKAGE)
public class AppConfig {

    public static final String BASE_PACKAGE = "com.halyph";
    public static final String SERVICE_PACKAGE = BASE_PACKAGE + ".service";
    private static final String RESOURCES_PACKAGE = BASE_PACKAGE + ".rest";
    private static final String PROVIDER_PACKAGE = BASE_PACKAGE + ".rest.provider";

    @ApplicationPath("/")
    public class JaxRsApiApplication extends Application { }

    @Bean(destroyMethod = "shutdown")
    public SpringBus cxf() {
        return new SpringBus();
    }

    @Bean
    @DependsOn("cxf")
    public Server jaxRsServer(ApplicationContext appContext) {
        JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint(jaxRsApiApplication(), JAXRSServerFactoryBean.class);
        factory.setServiceBeans(restServiceList(appContext));
        factory.setAddress("/" + factory.getAddress());
        factory.setProviders(restProviderList(appContext, jsonProvider()));
        return factory.create();
    }

    @Bean
    public JaxRsApiApplication jaxRsApiApplication() {
        return new JaxRsApiApplication();
    }

    @Bean
    public JacksonJsonProvider jsonProvider() {
        return new JacksonJsonProvider();
    }

    private List<Object> restServiceList(ApplicationContext appContext) {
        return RestServiceBeanScanner.scan(appContext, AppConfig.RESOURCES_PACKAGE);
    }

    private List<Object> restProviderList(final ApplicationContext appContext,
                                          final JacksonJsonProvider jsonProvider) {
        final List<Object> providers = RestProviderBeanScanner.scan(appContext, PROVIDER_PACKAGE);
        providers.add(jsonProvider);
        return providers;
    }

}

Now, we should test this. 1st run application:
mvn clean tomcat7:run

Verify REST API calls:
# pretty printed JSON, see ObjectMapperProvider 
$  curl http://localhost:8080/api/users
[ {
  "id" : 1,
  "name" : "foo"
}, {
  "id" : 2,
  "name" : "bar"
}, {
  "id" : 3,
  "name" : "baz"
} ]

# try to get non-existent user, expected to get NotFoundException JSON
$ curl http://localhost:8080/api/users/100
{
  "details" : "The requested resource hasn't been found",
  "date" : "2013-10-19T13:39:034Z",
  "msg" : null
}

# try to get GeneralException JSON
$  curl http://localhost:8080/api/exception
{
  "date" : "2013-10-19T13:40:049Z",
  "msg" : "generateException from ExceptionResource"
}

   You can find sources on GitHub

References
  1. Apache CXF exception handler for jaxrs (REST)
  2. Official documentation: Apache CXF Exception handling

Saturday, October 19, 2013

REST with JAX-RS: Part 1 - Spring Java Config

There are many Java REST frameworks. We can devide these frameworks on three groups:
  1. Spring MVC. It can be used to implement RESTful services. This framework has been widly used, mature, etc. But, Spring, in general, does not support JAX-RS standard.
  2. JAX-RS implementation. I know at least four frameworks:
  3. Non-Standard. I.e. frameworks which do not support JAX-RS, or addition many other features. Please note, it assume that Spring MVC can be called "standard" ;-)
    • Dropwizard very cool frameworks. It supports not only JAX-RS. 
    • RESTX, lightweight framework.
It's logically to ask yourself why don't use Spring MVC for REST services development. There is a  very good article on InfoQ: A Comparison of Spring MVC and JAX-RS. I consider to use JAX-RS frameworks for REST API and Spring MVC for everything else . The most popular are Apache CXF  and Jersey. Also, Apache CXF has SOAP services support. Actually, you can easily switch between JAX-RS frameworks till you use standard approaches.

Let's create simple Spring JAX-RS application with Spring Java Configs (see sample application based on Spring context xml [3])

Create pom.xml file

    4.0.0
    jaxrs-tutorials
    jaxrs-tutorials
    war
    1.0-SNAPSHOT
    jaxrs-tutorials Maven Webapp
    http://maven.apache.org

    
        UTF-8
        1.7

        2.7.6
        3.2.3.RELEASE
        1.7.5
        1.0.13
        3.0.1
        2.0.2

        3.0
        2.0
        2.2
        2.6
    

    

        
            org.apache.cxf
            cxf-rt-frontend-jaxrs
            ${cxf.version}
        

        
        
            org.springframework
            spring-context
            ${org.springframework-version}
            
                
                
                    commons-logging
                    commons-logging
                
            
        
        
            org.springframework
            spring-webmvc
            ${org.springframework-version}
        

        
        
            org.slf4j
            slf4j-api
            ${org.slf4j-version}
        
        
            org.slf4j
            jcl-over-slf4j
            ${org.slf4j-version}
            runtime
        
        
            ch.qos.logback
            logback-classic
            ${ch.qos.logback-version}
        

        
        
            javax.servlet
            javax.servlet-api
            ${servlet-version}
            provided
        

        
        
            com.fasterxml.jackson.jaxrs
            jackson-jaxrs-json-provider
            ${jackson-version}
        

    

    

        jaxrs-tutorials

        
            
                org.apache.tomcat.maven
                tomcat7-maven-plugin
                2.0
                
                    /
                    8080
                
            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                ${maven-compiler-plugin-version}
                
                    ${java-version}
                    ${java-version}
                
            
        
    

Create some sample entity
package com.halyph.entity;

public class User {

    private Integer id;
    private String name;

    public User() {
    }

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

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

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

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return String.format("{id=%s,name=%s}", id, name);
    }
}
We should implement Service(s) which manages this entity:
package com.halyph.service;

import com.halyph.entity.User;

import javax.ws.rs.core.Response;
import java.util.Collection;

public interface UserService {

    Collection<User> getUsers();

    User getUser(Integer id);

    Response add(User user);

}
package com.halyph.service;

import com.halyph.entity.User;
import org.springframework.stereotype.Service;

import javax.ws.rs.core.Response;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Service("userService")
public class UserServiceImpl implements UserService {

     private static Map<Integer, User> users = new HashMap<Integer, User>();

    static {
        users.put(1, new User(1, "foo"));
        users.put(2, new User(2, "bar"));
        users.put(3, new User(3, "baz"));
    }

    public UserServiceImpl() {
    }

    @Override
    public Collection<User> getUsers() {
        return users.values();
    }

    @Override
    public User getUser(Integer id) {
        return users.get(id);
    }

    @Override
    public Response add(User user) {
        user.setId(users.size()+1);
        users.put(user.getId(), user);

        //do more stuff to add user to the system..
        return Response.status(Response.Status.OK).build();
    }

}
It's time to introduce REST services. with the next endpoints /api/users and /api/exception. So, we  have bunch of REST URIs:
  • GET /api/users - get all users
  • GET /api/users/{id} - get user with id
  • POST /api/users - accept "user" json and create the specified user on back-end
  • GET /api/exception - throw exception
 
package com.halyph.rest;

import com.halyph.entity.User;
import com.halyph.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Collection;

@Path("/users")
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public class UserResource {

    private static Logger log = LoggerFactory.getLogger(UserResource.class);

    @Autowired
    UserService service;

    public UserResource() {
    }

    @GET
    public Collection<User> getUsers() {
        return service.getUsers();
    }

    @GET
    @Path("/{id}")
    public User getUser(@PathParam("id") Integer id) {
        return service.getUser(id);
    }

    @POST
    public Response add(User user) {
        log.info("Adding user {}", user.getName());
        service.add(user);
        return Response.status(Response.Status.OK).build();
    }
}
Also we added /api/exception REST url to demonstrate how CXF deals with exceptions:
package com.halyph.rest;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/exception")
public class ExceptionResource {

    public ExceptionResource() { }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String generateException() throws Exception {
        throw new Exception("generateException from ExceptionResource");
    }
}

So, what's left? In general we are creating some web.xml where we configure Apache CXF, etc. But, we will use Spring feature and implement all our configuration in Spring Java Configs.
Our web.xml willl be empty, some App Servers still require it:

Next, we should create some class which does the same work which had been done by web.xml:
package com.halyph.config;

import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import java.util.Set;

public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.addListener(new ContextLoaderListener(createWebAppContext()));
        addApacheCxfServlet(servletContext);
    }

    private void addApacheCxfServlet(ServletContext servletContext) {
        CXFServlet cxfServlet = new CXFServlet();

        ServletRegistration.Dynamic appServlet = servletContext.addServlet("CXFServlet", cxfServlet);
        appServlet.setLoadOnStartup(1);

        Set<String> mappingConflicts = appServlet.addMapping("/api/*");
    }

    private WebApplicationContext createWebAppContext() {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(AppConfig.class);
        return appContext;
    }

}
So, "web.xml" is configured, now we should configure Spring context:
package com.halyph.config;

import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.halyph.rest.UserResource;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import com.halyph.rest.ExceptionResource;
import com.halyph.service.UserService;
import com.halyph.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.RuntimeDelegate;
import java.util.Arrays;

@Configuration
public class AppConfig {

    @ApplicationPath("/")
    public class JaxRsApiApplication extends Application { }

    @Bean(destroyMethod = "shutdown")
    public SpringBus cxf() {
        return new SpringBus();
    }

    @Bean
    @DependsOn("cxf")
    public Server jaxRsServer(ApplicationContext appContext) {
        JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint(jaxRsApiApplication(), JAXRSServerFactoryBean.class);
        factory.setServiceBeans(Arrays.<Object>asList(userResource(), exceptionResource()));
        factory.setAddress("/" + factory.getAddress());
        factory.setProvider(jsonProvider());
        return factory.create();
    }

    @Bean
    public JaxRsApiApplication jaxRsApiApplication() {
        return new JaxRsApiApplication();
    }

    @Bean
    public JacksonJsonProvider jsonProvider() {
        return new JacksonJsonProvider();
    }

    @Bean
    public UserService userService() {
        return new UserServiceImpl();
    }

    @Bean
    public UserResource userResource() {
        return new UserResource();
    }

    @Bean
    public ExceptionResource exceptionResource() {
        return new ExceptionResource();
    }
}
Please note, how service and rest beans have been registered, also we added jackson provider which serialize bean in JSON format.

We almost done, now we should verify out work. Run application:
mvn clean tomcat7:run

Test REST API:
curl http://localhost:8080/api/users
curl http://localhost:8080/api/users/1
curl -v http://localhost:8080/api/exception
curl http://localhost:8080/api/users -X POST -H "Content-Type: application/json" -d '{"name":"John"}'
curl http://localhost:8080/api/users

After the last call you should get four users from back-end.
$ curl http://localhost:8080/api/users
[{"id":1,"name":"foo"},{"id":2,"name":"bar"},{"id":3,"name":"baz"}]

$ curl http://localhost:8080/api/users -X POST -H "Content-Type: application/json" -d '{"name":"John"}'

$  curl http://localhost:8080/api/users
[{"id":1,"name":"foo"},{"id":2,"name":"bar"},{"id":3,"name":"baz"},{"id":4,"name":"John"}]

   You can find sources on GitHub.

References
  1. InfoQ: A Comparison of Spring MVC and JAX-RS
  2. REST client, CXF server : JAX-RS or SPRING-MVC ?
  3. REST web services with JAX-RS, Apache CXF and Spring Security
  4. Official Apache CXF Doc: Configuring JAX-RS services in container with Spring configuration file.
  5. Converting Jersey REST Examples to Apache CXF

Thursday, October 03, 2013

Java Object to Object Mapper

I've been using Dozer some time on the project. But, recently I have got very interesting error which motivates me to look around and try to use other Object to Object mapper.

Here is the list of tools I've found:
  • Dozer: Dozer is a Java Bean to Java Bean mapper that recursively copies data from one object to another. Typically, these Java Beans will be of different complex types.
  • Orika: Orika is a Java Bean mapping framework that recursively copies (among other capabilities) data from one object to another. It can be very useful when developing multi-layered applications.
  • Transmorph: Transmorph is a free java library used to convert a Java object of one type into an object of another type (with another signature, possibly parameterized).
  • EZMorph: EZMorph is simple java library for transforming an Object to another Object. It supports transformations for primitives and Objects, for multidimensional arrays and transformations with DynaBeans
  • Commons-BeanUtils: ConvertUtils -> Utility methods for converting String scalar values to objects of the specified Class, String arrays to arrays of the specified Class.
  • Commons-Lang: ArrayUtils -> Operations on arrays, primitive arrays (like int[]) and primitive wrapper arrays (like Integer[]).
  • Commons-Convert: Commons-Convert aims to provide a single library dedicated to the task of converting an object of one type to another. The first stage will focus on Object to String and String to Object conversions.
  • Morph: Morph is a Java framework that eases the internal interoperability of an application. As information flows through an application, it undergoes multiple transformations. Morph provides a standard way to implement these transformations.
  • Lorentz: Lorentz is a generic object-to-object conversion framework. It provides a simple API to convert a Java objects of one type into an object of another type. (seems dead)
  • Spring framework: Spring has an excellent support for PropertyEditors, that can also be used to transform Objects to/from Strings.
  • ModelMapper: ModelMapper is an intelligent object mapping framework that automatically maps objects to each other. It uses a convention based approach to map objects while providing a simple refactoring safe API for handling specific use cases.
  • OTOM: With OTOM, you can copy any data from any object to any other object. The possibilities are endless. Welcome to "Autumn".
  • Smooks: The Smooks JavaBean Cartridge allows you to create and populate Java objects from your message data (i.e. bind data to).
  • Nomin: Nomin is a mapping engine for the Java platform transforming object trees according to declarative mapping rules. This Java mapping framework aims to reduce efforts when it's needed to map different structures to each other.
  • Modelbridge: Modelbridge is an Eclipse plugin that lets you copy data between Java objects.
  • omapper: This project aims at providing a simple library to ease the process of mapping objects or beans from one design layer to another design layer, using annotations. One can specify mappings both in source class (Sink Annotation) and target class(Source Annotation). Supports mapping composed user class objects and array fields. 
  • Moo: Moo maps an object or graph of objects to another object or set of objects while trying to stay as unintrusive as possible and easy-to-use. Moo makes it possible to create quick copies and data transfer objects.   
  • OpenL Tablets: treats tables in Excel and Word files as a source of application logic. This approach may be unusual, but it has it's own unique advantages, in particular it allows to close the gap between business world and IT world.
  • JMapper: JMapper Framework is a java bean to java bean mapper, allows you to perform the passage of data dynamically with annotations and / or XML.
References