Este patron permite publicar las clases modelo a traves de http REST. Es contradictoria al patron MVC pero util en algunos casos por ejemplo usando http para comunicar otras aplicaciones con tu modelo.
Este patron te permite
- Listar objectos con paginacion
- !!! Listar propiedades de objetos con paginacion
- Actualizar objectos
- Extraer propiedades individuales de objetos
- !!! Actualizar propiedades individuales de objetoss
- Automaticamente serializar / deserializar en xml, json, etc…
No he anadido busqueda pero la implementacion es trivial simplemente usando hibernate search
El codigo tampoco muestra en detalle como usar asociaciones del tipo @OneToMany, @ManyToMany, @Any, @ManyToOne
El codigo tambien usa algunas tecnicas ortodoxas como la inyeccion de servicios en campos estaticos dentro de la clase base de modelo.
El código de este articulo y el de muchos otros esta disponible para descargar con svn en :
svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only
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; } }); } }

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
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?
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
payload looks like:
trevor
5
<a href="mailto:trevor.burton@whatever.org">trevor.burton@whatever.org</a>
Sorry it looks like wp does not like xml, try passing it through http://www.elliotswan.com/postable/
ok, trying again:
<person>
<children/>
<email>{email}</email>
<id>5</id>
<name>{username}</name>
</person>
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
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.