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;
			}
		});
	}
}
Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • LinkedIn
  • MySpace
  • RSS
  • TwitThis
  • email
  • FriendFeed
  • PDF
  • Slashdot

This post is tagged , , , , , , , ,

don't '

8 Responses

  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.

Leave a Reply

Comments may be held for moderation, please do not repost. I reserve the right to remove any inappropriate or off-topic comments. If you plan on sharing helpful code, please pass it through Postable first. Want other to know who you are? Register a Gravatar.





Sponsored Links

Categories

Pages

juice141
insurance158
gardens47
jewelers93
bestyoucanfind.info
heart146
james29
lyrics167
industries92
google142
lafayette9
kitchen229
lyrics120
jesus90
italian248
lyrics1
afreeocx.com
guide24
manhattan166
green201
information113
frank168
lyrics160
lyrics190
family142
kofflerboats.com
hitachi214
festival182
forest102
jamaica25
hotel86
executive74
guide23
flavor28
grant172
hockey221
free-microsofts.com
lyrics239
thesagamore.com
failed120
hockey220
healthbenefitsdepot.com
generic67
exchange72
fever194
island235
games21
italy249
manual188
management155
excellpressurewashers.com
library131
gibson97
grill212
marble210
flights35
hotel150
manitoba168
manual186
found137
finance231
house216
install128
institute139
lyric61
garden44
katie169
guitar51
festival181
hotels171
house189
franchise158
columbiatn.com
insurance150
guitar58
illinois22
louisville24
little204
festival189
height163
lyric67
guitar48
lyrics152
lyric48
lacrosse6
hotel154
georgia80
marine233
fitness19
cam.com
hospital62
hunter243
magazine103
floyd73
living210
sex-teen.org
lyrics46
honda22
honey36
mmgins.com
hotel142
ithaca3
lyrics202
lyrics142
management154
lyrics50
hunting247
harold105
creeksidepreserve.com
logic235
forum124
letter111
industrial90
lyrics31
gainesville242
hotel138
island224
heaters152
lyrics171
lyric69
marysvilleohio.org
gauge53
laboratories3
estate2
fields205
infant100
hairstyles77
indian72
james35
ireland214
maine125
houston231
malta148
jones128
fireplace241
honey36
rustyiron.com
finder236
germany90
jessica88
magnum119
fruit195
lyrics235
inurl204
guild36
lyrics37
kennel188
groups248
handbags91
freedom177
jeremy71
lyric81
furnace215
falls129
installing131
manufacturing203
lauderdale58
hotels176
major128
estate25
kenwood198
guitar47
hyderabad7
lyrics129
latex53
fabric103
lonsberry.com
lyrics147
maine123
sunyacc.edu
james27
veostingray.com
landing17
gallery12
lyrics231
madden90
furniture217
lyrics179
fountain146
little197
indian70
lounge27
lyrics121
keygen206
kevin201
import41
foster135
happy95
history199
jones124
kitten231
furniture236
manor170
language22
festival186
flash24
guitar43
lyrics44
homes8
hawaii119
hotel108
madden90
knight236
goneglobal35.com
florist65
myispfinder.org
lyric81
estate12
grand166
estate40
lyrics126
guitars67
fiber195
jumper148
limited160
hamilton85
female171
hospital67
instant132
estate6
glasses123
legal90
level116
pdc.org
estate18
india67
gallery13
kingdom217
florida59
katrina172
lyric76
linux183
football89
ingredients119
gymnastics73
houston229
humidifier241
naral.org
flying75
jewelry102
marine235
internet191
hotel133
hospital54
finder236
katrina172
listing193
lodge228
johnny110
mygibline.com
lyrics231
exhaust83
india54
little196
fuelmaker.com
lyrics163
harrison108
europe51
leather84
luggage33
gallery1
london242
lyrics67
magnum119
italy249
gallery3
lyrics9
london246
24fusion.info
hawaii118
lyric69
great186
thunderwear.com
market243
lyrics200
guide23
james27
linux179
houston222
example60
louisiana21
living211
maison127
californiaduihelp.com
fisher8
lyrics42
horses52
horse46
genesis68
indianapolis82
headphones123
lyrics201
forum123
local219
jelly60
malaysia144
fender177
lyric65
factory116
nomino.ca
greensboro206
express93
humidifier241
lights156
exercise76
girls104
jewish103
honda17
pulaskicountyassessor.net
lyric78
lyric75
harley103
group234
houses217
hockey219
lynch39
machine76
honda31
island229
gymnastics73
harvard114
katie168
infant100
lyrics207
language33
financialhack.com
login238
garcia35
manufacturer202
banana1015.com