Spring – Hibernate – JAX-RS Putting Hibernate to REST

This pattern exposes your domain model as a http REST interface. It violates MVC and many other good practices but it’s way cool and easy to not blog about it. There are certain scenarios too where you might want to expose your model this way, for example if you’re not building an app but a framework to build apps and you want to give raw access to some of the core model beans or data.

In most examples I found on the web, all REST services go through services before they hit the model and I wanted an automatic way to access the model by simply adding a few annotations to the beans.

This pattern allows you to

  1. List objects by class in a paginated fashion
  2. !!! List objects properties in a paginated fashion
  3. Update objects
  4. Get individual object properties
  5. !!! Update individual object properties
  6. automatically serialize / desiarilize in xml, json, etc…

I have not added search but the implementation is trivial based on Hibernate Search by simply annotating the entities and properties.
The code also does not go into the details in handling aggregated collections @OneToMany, @ManyToMany, @Any or agregated objects @ManyToOne

The code uses some non standard way of doing things such as injection of a Service in one of the entities base class properties.

This code in this article and some other examples are available for download with svn:
svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only
Comments in the code itself should be self-explanatory if you already have some java + spring experience.

See embedded video for a demo of the code at work

Demo video

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
    <description>hibernate-rest</description>
    <display-name>hibernate-rest</display-name>
 
    <!-- Spring config  -->
    <context-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>
               /WEB-INF/conf/applicationContext.xml
           </param-value>
       </context-param>
 
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/conf/log4j.properties</param-value>
    </context-param>
 
 
    <!-- Spring Listeners -->
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
 
    <filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>
            org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
        </filter-class>
    </filter>
 
    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 
    <!-- Remote web services -->
       <servlet>
           <servlet-name>CXFServlet</servlet-name>
           <servlet-class>
               org.apache.cxf.transport.servlet.CXFServlet
           </servlet-class>
       </servlet>
 
       <servlet>
           <servlet-name>remoteApiBasicHttpHandlerImpl</servlet-name>
           <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
       </servlet>
 
 
       <!-- Remote web services mapping -->
       <servlet-mapping>
           <servlet-name>CXFServlet</servlet-name>
           <url-pattern>/api/*</url-pattern>
       </servlet-mapping>
 
 
</web-app>

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory name="com.raulraja.tutorials">
        <!-- Persistent entities -->
        <mapping class="com.raulraja.model.domain.Person"/>  
    </session-factory>
</hibernate-configuration>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:cxf="http://cxf.apache.org/core"
        xmlns:jaxws="http://cxf.apache.org/jaxws"
        xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
       http://cxf.apache.org/core
       http://cxf.apache.org/schemas/core.xsd
       http://cxf.apache.org/jaxws
       http://cxf.apache.org/schemas/jaxws.xsd
       http://cxf.apache.org/jaxrs
       http://cxf.apache.org/schemas/jaxrs.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
        default-autowire="byName">
 
    <!-- Load CXF modules from cxf.jar -->
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/>
 
 
    <cxf:bus>
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus>
 
    <!-- A template instance to expose as the service -->
    <bean id="person" class="com.raulraja.model.domain.Person"/>
 
    <!-- The rest server configuration -->
    <jaxrs:server id="restServer" address="/rest/">
        <jaxrs:serviceBeans>
            <ref bean="person"/>
        </jaxrs:serviceBeans>
        <jaxrs:extensionMappings>
            <entry key="feed" value="application/atom+xml"/>
            <entry key="json" value="application/json"/>
            <entry key="xml" value="application/xml"/>
            <entry key="html" value="text/html"/>
        </jaxrs:extensionMappings>
    </jaxrs:server>
 
    <!-- The datasource -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="org.postgresql.Driver"/>
        <property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/tutorials?autoReconnect=true"/>
        <property name="user" value="tutorials"/>
        <property name="password" value="tutorials"/>
    </bean>
 
    <!-- The hibernate session factory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocations">
            <list>
                <value>WEB-INF/conf/hibernate.cfg.xml</value>
            </list>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
    </bean>
 
    <!-- A persistence adapter implementation that acts as a data access service -->
    <bean id="persistenceAdapter" class="com.raulraja.model.persistence.impl.HibernatePersistenceAdapterImpl" autowire="autodetect">
        <property name="defaultResultSize" value="10"/>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>
 
    <!-- The transaction manager -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
    </bean>
 
    <!-- enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
 
    <!-- The hibernate template -->
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
    </bean>
 
    <!-- statically injects the persistence service in the entities base class -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="com.raulraja.model.domain.PersistentEntity.setPersistenceAdapter"/>
        <property name="arguments">
            <ref bean="persistenceAdapter"/>
        </property>
    </bean>
 
 
</beans>

PaginatedList.java

package com.raulraja.model.domain;
 
import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
 
/**
 * An object that encapsualtes pagination over list of records
 */
@XmlRootElement(namespace = PersistentEntity.NAMESPACE)
@XmlType(name = "paginatedList", namespace = PersistentEntity.NAMESPACE)
public class PaginatedList<Entity> {
 
	/**
	 * the total amount of items available in the data store
	 */
	private long count;
 
	/**
	 * the starting record displayed on the list
	 */
	private long start;
 
	/**
	 * the size of this list
	 */
	private long size;
 
	/**
	 * the records contained on the list
	 */
	private List<Entity> items = new ArrayList<Entity>();
 
	/**
	 * default constructor
	 */
	public PaginatedList() {
		super();
	}
 
	/**
	 * Constructor that takes the data
	 * @param count the total amount of items available in the data store
	 * @param start the starting record displayed on the list
	 * @param items the records contained on the list
	 */
	public PaginatedList(long count, long start, List<Entity> items) {
		this();
		setCount(count);
		setStart(start);
		setItems(items);
		setSize(items.size());
	}
 
	/**
	 * @return the total amount of items available in the data store
	 */
	public long getCount() {
		return count;
	}
 
	public void setCount(long count) {
		this.count = count;
	}
 
	/**
	 * @return the starting record displayed on the list
	 */
	public long getStart() {
		return start;
	}
 
	public void setStart(long start) {
		this.start = start;
	}
 
	/**
	 * @return the size of this list
	 */
	public long getSize() {
		return size;
	}
 
	public void setSize(long size) {
		this.size = size;
	}
 
	/**
	 * @return the records contained on the list
	 */
	@XmlElementWrapper(name = "items")
	@XmlElements({
            @XmlElement(name="person", type=Person.class, namespace = PersistentEntity.NAMESPACE),
			@XmlElement(name="property", type=Object.class, namespace = PersistentEntity.NAMESPACE)
    })
	public List<Entity> getItems() {
		return items;
	}
 
	public void setItems(List<Entity> items) {
		this.items = items;
	}
}

PersistentEntity.java

package com.raulraja.model.domain;
 
import com.raulraja.model.persistence.PersistenceAdapter;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.transaction.annotation.Transactional;
 
import javax.ws.rs.*;
import java.lang.reflect.InvocationTargetException;
 
/**
 * Base class for entities with static access to the persistent context
 */
public abstract class PersistentEntity<Entity extends PersistentEntity> {
 
	public static final String NAMESPACE = "https://apps.raulraja.org/api";
 
	private static PersistenceAdapter<PersistentEntity> persistenceAdapter;
 
	public static void setPersistenceAdapter(PersistenceAdapter<PersistentEntity> persistenceAdapter) {
		PersistentEntity.persistenceAdapter = persistenceAdapter;
	}
 
	public abstract Long getId();
 
	public abstract Class<Entity> getMappedClass();
 
	@Override
	@SuppressWarnings("unchecked")
	public boolean equals(Object o) {
		if (this == o) {
			return true;
		}
		if (o == null || getClass() != o.getClass()) {
			return false;
		}
 
		PersistentEntity<?> entity = (PersistentEntity<?>) o;
 
		if (getId() != null ? !getId().equals(entity.getId()) : entity.getId() != null) {
			return false;
		}
 
		return true;
	}
 
	@Override
	public int hashCode() {
		return getId() != null ? getId().hashCode() : 0;
	}
 
 
	/**
	 * Returns a paginated list of all entities for this class
	 * @param start the start record
	 * @param size the limit
	 * @return the list of matches
	 */
	@GET @Path("list")
	@SuppressWarnings("unchecked")
    public PaginatedList<Entity> list(@QueryParam("start") int start, @QueryParam("size") int size) {
		Class mappedClass = getMappedClass();
		PaginatedList<Entity> list = (PaginatedList<Entity>) persistenceAdapter.list(mappedClass, start, size);
		return list;
	}
 
	/**
	 * Returns a paginated list of all entities for this class
	 * @param start the start record
	 * @param size the limit
	 * @return the list of matches
	 */
	@GET @Path("{property}/list")
	@SuppressWarnings("unchecked")
    public PaginatedList<Object> list(@PathParam("property") String property, @QueryParam("start") int start, @QueryParam("size") int size) {
		Class mappedClass = getMappedClass();
		PaginatedList<Object> list = (PaginatedList<Object>) persistenceAdapter.list(mappedClass, property, start, size);
		return list;
	}
 
 
	@GET @Path("{id}")
    public PersistentEntity get(@PathParam("id") Long id) {
		Class mappedClass = getMappedClass();
		PersistentEntity entity = persistenceAdapter.get(mappedClass, id);
		return entity;
	}
 
	@GET @Path("{id}/{property}")
    public Object getProperty(@PathParam("id") Long id, @PathParam("property") String property) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		Class mappedClass = getMappedClass();
		PersistentEntity entity = persistenceAdapter.get(mappedClass, id);
		return PropertyUtils.getProperty(entity, property);
	}
 
	@POST @Path("{id}/{property}")
	@Transactional
    public Object updateProperty(@PathParam("id") Long id, @PathParam("property") String property, String value) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		Class mappedClass = getMappedClass();
		PersistentEntity entity = persistenceAdapter.get(mappedClass, id);
		BeanUtils.setProperty(entity, property, value);
		return persistenceAdapter.save(entity);	
	}
 
	@POST @Path("create")
	@Transactional
    public PersistentEntity create(Entity entity) {
		PersistentEntity persistentEntity = get(entity.getId());
		if (persistentEntity != null) {
			throw new IllegalStateException("There is already a " + getMappedClass() + " with id = " + entity.getId());
		}
		persistenceAdapter.save(entity);
		return entity;
	}
 
	@POST @Path("update")
	@Transactional
    public PersistentEntity update(Entity entity) {
		PersistentEntity<Entity> persistentEntity = get(entity.getId());
		if (persistentEntity == null) {
			throw new IllegalStateException("There is no" + getMappedClass() + " with id = " + entity.getId());
		}
		persistentEntity.updateFromRequest(entity);
		persistenceAdapter.save(persistentEntity);
		return persistentEntity;
	}
 
	public abstract Entity updateFromRequest(Entity entity);
 
	@POST @Path("delete")
    public Entity delete(Entity entity) {
		persistenceAdapter.delete(entity);
		return entity;
	}
 
}

Person.java

package com.raulraja.model.domain;
 
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.ws.rs.Path;
import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
 
@Entity
@Path("/person/")
@XmlRootElement
@XmlType(name = "person", namespace = PersistentEntity.NAMESPACE)
public class Person extends PersistentEntity<Person> {
 
	@Id
	private Long id;
 
	private String name;
 
	private String email;
 
	@ManyToOne
	private Person parent;
 
	@OneToMany(mappedBy = "parent")
	private List<Person> children = new ArrayList<Person>();
 
	@XmlElement(type = Long.class)
	public Long getId() {
		return id;
	}
 
	public void setId(Long id) {
		this.id = id;
	}
 
	@XmlElement(type = String.class)
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	@XmlElement(type = String.class)
	public String getEmail() {
		return email;
	}
 
	public void setEmail(String email) {
		this.email = email;
	}
 
	@XmlElement(type = Person.class)
	public Person getParent() {
		return parent;
	}
 
	public void setParent(Person parent) {
		this.parent = parent;
	}
 
	@XmlElement(type = Person.class, name = "person", namespace = PersistentEntity.NAMESPACE)
	@XmlElementWrapper(name = "children")
	public List<Person> getChildren() {
		return children;
	}
 
	public void setChildren(List<Person> children) {
		this.children = children;
	}
 
	public Class<Person> getMappedClass() {
		return Person.class;
	}
 
	public Person updateFromRequest(Person person) {
		setName(person.getName());
		setEmail(person.getEmail());
		return this;
	}
 
 
}

PersistenceAdapter.java

package com.raulraja.model.persistence;
 
import com.raulraja.model.domain.PaginatedList;
 
import java.io.Serializable;
 
 
public interface PersistenceAdapter<Entity> {
 
	/**
	 * Returns a paginated list of all entities for this class
	 * @param entityClass the entity class
	 * @param start the start record
	 * @param limit the limit
	 * @return the list of matches
	 */
	PaginatedList<Entity> list(Class<Entity> entityClass, int start, int limit);
 
	/**
	 * Returns a paginated list of the selected property for this class
	 * @param entityClass the entity class
	 * @param start the start record
	 * @param limit the limit
	 * @return the list of matches
	 */
	PaginatedList<?> list(Class<Entity> entityClass, String property, int start, int limit);
 
    /**
     * Find a persistent object based on its unique id
     * @param entityClass the entity's class
     * @param id unique identifier
     * @return returns a persistent object
     */
    public Entity get(Class<Entity> entityClass, Serializable id);
 
    /**
     * Persists an object
     * @param entity to be persisted
	 * @return the saved entity
     */
    public Entity save(Entity entity);
 
    /**
     * Removes an entity from the data store
     * @param entity to be removed
	 * @return the deleted entity
     */
    public Entity delete(Entity entity);
 
 
}

HibernatePersistenceAdapterImpl.java

package com.raulraja.model.persistence.impl;
 
import com.raulraja.model.domain.PaginatedList;
import com.raulraja.model.persistence.PersistenceAdapter;
import org.apache.log4j.Logger;
import org.hibernate.*;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.orm.hibernate3.HibernateAccessor;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
 
import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
 
/**
 * Hibernate spring based impl of the persistence adapter
 */
public class HibernatePersistenceAdapterImpl<Entity> extends HibernateDaoSupport implements PersistenceAdapter<Entity> {
 
	private final static Logger log = Logger.getLogger(HibernatePersistenceAdapterImpl.class);
 
	private Integer defaultResultSize = 10;
 
	public void setDefaultResultSize(Integer defaultResultSize) {
		this.defaultResultSize = defaultResultSize;
	}
 
	/**
	 * Returns a paginated list of all entities for this class
	 *
	 * @param entityClass the entity class
	 * @param start	   the start record
	 * @param limit	   the limit
	 * @return the list of matches
	 */
	@SuppressWarnings("unchecked")
	public PaginatedList<Entity> list(Class<Entity> entityClass, int start, int limit) {
		limit = limit > 0 ? limit : defaultResultSize;
		if (entityClass == null)
            return null;
 
        List<Entity> entities;
		PaginatedList<Entity> page = new PaginatedList<Entity>();
 
		int total;
		try {
			DetachedCriteria criteria = DetachedCriteria.forClass(entityClass);
			entities = (List<Entity>) getPreparedHibernateTemplate().findByCriteria(criteria, start, limit);
			total = count(entityClass);
			page = new PaginatedList<Entity>(total, start, entities);
        }
        catch (Throwable e) {
            log.error(e, e);
        }
        return page;
	}
 
	/**
	 * Returns a paginated list of the selected property for this class
	 *
	 * @param entityClass the entity class
	 * @param start	   the start record
	 * @param limit	   the limit
	 * @return the list of matches
	 */
	public PaginatedList<?> list(Class<Entity> entityClass, String property, int start, int limit) {
		limit = limit > 0 ? limit : defaultResultSize;
		if (entityClass == null)
            return null;
 
        List<Object> properties;
		PaginatedList<Object> page = new PaginatedList<Object>();
 
		int total;
		try {
			DetachedCriteria criteria = DetachedCriteria.forClass(entityClass);
			criteria.setProjection(Projections.property(property));
			properties = (List<Object>) getPreparedHibernateTemplate().findByCriteria(criteria, start, limit);
			total = count(entityClass);
			page = new PaginatedList<Object>(total, start, properties);
        }
        catch (Throwable e) {
            log.error(e, e);
        }
        return page;
	}
 
	private Integer count(final Class<Entity> entityClass) {
		return (Integer) getPreparedHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(entityClass);
				criteria.setProjection(Projections.rowCount());
				return criteria.list().get(0);
			}
		});
	}
 
	/**
	 * Find a persistent object based on its unique id
	 *
	 * @param entityClass the entity's class
	 * @param id		  unique identifier
	 * @return returns a persistent object
	 */
	@SuppressWarnings("unchecked")
	public Entity get(Class<Entity> entityClass, Serializable id) {
		Entity entity = (Entity) getHibernateTemplate().get(entityClass, id);
		return initializeProxy(entity);
	}
 
	/**
	 * Persists an object
	 *
	 * @param entity to be persisted
	 */
	@SuppressWarnings("unchecked")
	public Entity save(Entity entity) {
		getHibernateTemplate().saveOrUpdate(entity);
		return initializeProxy(entity);
	}
 
	/**
	 * Removes an entity from the data store
	 *
	 * @param entity to be removed
	 */
	@SuppressWarnings("unchecked")
	public Entity delete(Entity entity) {
		getHibernateTemplate().delete(entity);
		return initializeProxy(entity);
	}
 
 
	private HibernateTemplate getPreparedHibernateTemplate() {
        HibernateTemplate template = getHibernateTemplate();
        template.setCacheQueries(true);
        template.setFlushMode(HibernateAccessor.FLUSH_AUTO);
        return template;
    }
 
	private Entity initializeProxy(Entity entity) {
		getPreparedHibernateTemplate().initialize(entity);
		return entity;
	}
 
	/**
	 * Finds a class associated with this path name
	 *
	 * @param name the name
	 * @return the found class if any
	 */
	@SuppressWarnings("unchecked")
	public Class<Entity> getClassForName(String name) {
		final String normalizedName = name.length() > 0 ? name.substring(name.lastIndexOf("."),1).toUpperCase() + name.substring(0) : name;
		return (Class<Entity>) getPreparedHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				SessionFactory factory = session.getSessionFactory();
				ClassMetadata classMetadata = factory.getClassMetadata(normalizedName);
				return classMetadata != null ? classMetadata.getMappedClass(EntityMode.POJO) : null;
			}
		});
	}
}
Discuss
16 Comments
  1. I’ve set up this example and got it running fine. Except if i try and hit the create() method – i get errors thrown on the server when i try and send an xml payload to the create() method. Is this how it’s supposed to work – the create() method accepts an Entity instance so i’m sending an xml ‘person’ node with name and email but errors are always thrown as it tries to decode.

    Guessing i’m doing something dumb here but any help would be most appreciated as this seems perfect for the project i’m working on.

    T

  2. Raul Raja says:

    Hi Trevor, the create should work fine but I have not tested it thoroughly. Can you send me the error stack trace and the xml payload? Also do you get the same when using json instead of xml?

  3. Raul,

    Thanks for getting back to me :)

    the xml payload being sent is

    trevor
    5
    trevor.burton@whatever.org

    and the stack trace looks like:

    26-May-2010 09:15:32 org.apache.cxf.phase.PhaseInterceptorChain doIntercept
    INFO: Interceptor has thrown exception, unwinding now
    java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariabl
    eImpl cannot be cast to java.lang.Class
    at org.apache.cxf.jaxrs.utils.InjectionUtils.getActualType(InjectionUtil
    s.java:194)
    at org.apache.cxf.jaxrs.utils.InjectionUtils.getActualType(InjectionUtil
    s.java:185)
    at org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.objectFactoryForTy
    pe(AbstractJAXBProvider.java:191)
    at org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.isSupported(Abstra
    ctJAXBProvider.java:168)
    at org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.isReadable(Abstrac
    tJAXBProvider.java:80)
    at org.apache.cxf.jaxrs.provider.ProviderFactory.matchesReaderCriterias(
    ProviderFactory.java:406)
    at org.apache.cxf.jaxrs.provider.ProviderFactory.chooseMessageReader(Pro
    viderFactory.java:381)
    at org.apache.cxf.jaxrs.provider.ProviderFactory.createMessageBodyReader
    (ProviderFactory.java:237)
    at org.apache.cxf.jaxrs.provider.ProviderFactory.createMessageBodyReader
    (ProviderFactory.java:247)
    at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.
    java:818)
    at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.jav
    a:470)
    at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.ja
    va:435)
    at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JA
    XRSInInterceptor.java:194)
    at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAX
    RSInInterceptor.java:65)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseIntercept
    orChain.java:236)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainIniti
    ationObserver.java:89)
    at org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDes
    tination.java:99)
    at org.apache.cxf.transport.servlet.ServletController.invokeDestination(
    ServletController.java:368)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletCont
    roller.java:146)
    at org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCX
    FServlet.java:163)
    at org.apache.cxf.transport.servlet.AbstractCXFServlet.doPost(AbstractCX
    FServlet.java:141)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
    icationFilterChain.java:269)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
    ilterChain.java:188)
    at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.do
    FilterInternal(OpenSessionInViewFilter.java:198)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerR
    equestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
    icationFilterChain.java:215)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
    ilterChain.java:188)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperV
    alve.java:213)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextV
    alve.java:172)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.j
    ava:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.j
    ava:117)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineVal
    ve.java:108)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.jav
    a:174)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java
    :873)
    at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.p
    rocessConnection(Http11BaseProtocol.java:665)
    at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpo
    int.java:528)
    at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFol
    lowerWorkerThread.java:81)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadP
    ool.java:689)
    at java.lang.Thread.run(Thread.java:619)

    sending json i get

    26-May-2010 09:22:01 org.apache.cxf.jaxrs.utils.InjectionUtils handleParameter
    SEVERE: Class java.lang.Long can not be instantiated using a constructor with a
    single String argument
    26-May-2010 09:22:01 org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toR
    esponse
    WARNING: WebApplicationException has been caught : cause is java.lang.reflect.In
    vocationTargetException
    26-May-2010 09:22:01 org.apache.cxf.interceptor.LoggingOutInterceptor$LoggingCal
    lback onClose
    INFO: Outbound Message

    but this may be being caused by the way i’m sending it (from flash) – i’d rather have the xml being sent at the moment so that’s what i’m most interested in getting working but if you need anything else to debug…

    I’m assuming the payload is incorrectly formatted, but any light you can help shed on this would be most appreciated, i’m not familiar with this sort of setup so i’m a little lost at the moment and google isn’t helping :(

    thanks again

    T

  4. payload looks like:

    trevor
    5
    <a href="mailto:trevor.burton@whatever.org">trevor.burton@whatever.org</a>

  5. Raul Raja says:

    Sorry it looks like wp does not like xml, try passing it through http://www.elliotswan.com/postable/

  6. ok, trying again:

    <person>
    <children/>
    <email>{email}</email>
    <id>5</id>
    <name>{username}</name>
    </person>

  7. Raul Raja says:

    I see no namespaces. My guess is that you are missing the namespaces and it does not know what entity your xml belongs to. If you look at the video above they’re usually prefixed as ns2:person. Try hitting your service with a browser and look in the source code view the xml that it outputs, you should be able to use the same as input for an entity given an id. Also I recommend you use restclient for testing http://code.google.com/p/rest-client/ until you get your service working instead of flash as it may include headers or stuff in the request that may confuse cxf

  8. thanks raul – i tried adding the namespace but got the same result – i’ll take another look this afternoon and get back to you if i find anything new.

  9. Anil says:

    please can you attach tutorials schema/database sql file so that we can use MySQL/HSQLDB to connfigure and run the app.

  10. Raul Raja says:

    Anil, the sessionFactory and datasource beans declared on the spring configuration that I posted contain all the properties that you can change to use any db you wish. Also the sessionFactory contains prop key=”hibernate.hbm2ddl.auto” set to “update” which will create the schema automatically for you. You just need to create a db with whatever name you want and the tables and columns will be created automatically

  11. Anil says:

    Cool, got the app running with MySQL. How can I submit reuest to, any sample url or xml payload request. How to test in RestClient.

  12. Raul Raja says:

    It’s on the youtube video on the post. A little blurry… but if you go fullscreen you’ll see multiple sample urls and ways to get to your data

  13. Bruno says:

    Hi Raul!

    I have this error on my pom.xml

    Project build error: Non-resolvable parent POM: Failure to find com.raulraja:tutorials:pom:0.1 in http://repo1.maven.org/maven2 was
    cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced
    and ‘parent.relativePath’ points at wrong local POM

    Don´t know how to solve this one. Any help?

  14. Raul Raja says:

    Hi Bruno, All the tutorials share a common parent that includes the most common dependencies.
    If you get the full source tree with svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only you will be able to build the individual tutorials since the parent pom will be included. If you prefer not to do that you can just remove the parent dependency from your pom and manually add the dependencies to your project or tutorial folder.

  15. priya says:

    my getHibernateTemplate() is somin null.What could be the probable reason?

  16. Raul Raja says:

    @priya, the hibernate template should not be null as it is an explicitly wired dependency in the example which is configured via xml in the applicationContext. This example is quite old though and if implemented today I would use the new MVC JSON and XML converters instead of JaxRS and a more abstract layer not dependent in Hibernate / JPA

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">