Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3
Note
titlebeta - used in production

org.tynamo:tapestry-resteasy:0.0.1

Works with RestEASY 1.1.GA but not with newer versions
Works ONLY with singleton resources
Requires Tapestry 5.1.x

User guide for Tapestry-resteasy module

Tapestry-resteasy provides integration with JBoss' RESTEasy, an implementation JAX-RS (Java API for RESTful Web Services). JAX-RS is a very nice little spec and if you know what it is about, the following should be very easy to understand. Otherwise, read up on it at Jersey's overview (the reference implementation) or the actual specification. JBoss' RESTEasy provides a few more features over the reference implementation.

To use tapestry-resteasy (an independent module of Tynamo), you need to add the following dependency to your pom.xml:

Code Block
        <dependency>
            <groupId>org.tynamo</groupId>
            <artifactId>tapestry-resteasy</artifactId>
            <version>0.0.1</version>
        </dependency>

Modify your web.xml to include the following:

Code Block
   	<context-param>
		<param-name>resteasy.servlet.mapping.prefix</param-name>
		<param-value>/rest</param-value>
	</context-param>

	<filter>
		<filter-name>app</filter-name>
		<filter-class>org.tynamo.resteasy.ResteasyTapestryFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>app</filter-name>
		<url-pattern>/rest/*</url-pattern>
	</filter-mapping>

	<listener>
		<listener-class>
			org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
		</listener-class>
	</listener>

	<servlet>
		<servlet-name>Resteasy</servlet-name>
		<servlet-class>
			org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
		</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>Resteasy</servlet-name>
		<url-pattern>/rest/*</url-pattern>
	</servlet-mapping>

Create a package named "rest" for your rest services.
Code your singleton resource.
Good practices:

  • Name the resource class using the entity name followed by the word "Resource".
  • The @Path should be the entity name in lowercase.

For example:

Code Block
package org.tynamo.examples.simple.rest;

import org.tynamo.examples.simple.MyDomainObject;
import org.tynamo.services.PersistenceService;

import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import java.util.List;

@Path("/mydomainobject")
public class MyDomainObjectResource
{

	private PersistenceService persistenceService;

	public MyDomainObjectResource(PersistenceService persistenceService) {
		this.persistenceService = persistenceService;
	}

	@GET
	@Produces("application/json")
	public List<MyDomainObject> getAllDomains()
	{
		return (persistenceService.getInstances(MyDomainObject.class));
	}

	@POST
	@Consumes("application/json")
	public Response post(MyDomainObject domainObject)
	{
		persistenceService.save(domainObject);
		return Response.ok().build();
	}

	@GET
	@Path("{id}")
	@Produces("application/json")
	public MyDomainObject getDomainObject(@PathParam("id") Long id)
	{
		MyDomainObject domainObject = persistenceService.getInstance(MyDomainObject.class, id);
		if (domainObject == null)
		{
			throw new WebApplicationException(Response.Status.NOT_FOUND);
		}
		return domainObject;
	}

}

Don't forget to annotate your entities with JAXB annotations. You need at least @XmlRootElement. http://www.caucho.com/resin/doc/jaxb-annotations.xtp

For example:

Code Block
package org.tynamo.examples.simple.entities;

import org.hibernate.validator.NotNull;
import org.tynamo.descriptor.annotation.PropertyDescriptor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.xml.bind.annotation.XmlRootElement;

@Entity
@XmlRootElement(name = "mydomainobject")
public class MyDomainObject
{
	private Long id;

	private String name;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@PropertyDescriptor(index = 0)
	public Long getId()
	{
		return id;
	}

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

	@NotNull(message = "name can't be null")
	public String getName()
	{
		return name;
	}

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

	public boolean equals(Object o)
	{
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		MyDomainObject that = (MyDomainObject) o;

		return getId() != null ? getId().equals(that.getId()) : that.getId() == null;
	}

	public int hashCode()
	{
		return (getId() != null ? getId().hashCode() : 0);
	}

	public String toString()
	{
		return getName();
	}
}

Finally contribute your singleton resource to your AppModule:

Code Block
	/**
	 * Contributions to the RESTeasy main Application, insert all your singletons RESTeasy services here.
	 */
	public static void contributeApplication(Configuration<Object> singletons, ObjectLocator locator)
	{
		singletons.add(locator.autobuild(MyDomainObjectResource.class));
	}

And enjoy.

Note:

If you get this exception:

Code Block
Caused by: java.lang.ClassCastException: com.sun.xml.stream.ZephyrParserFactory cannot be cast to org.codehaus.stax2.XMLInputFactory2

Add this to your system properties:

Code Block
javax.xml.stream.XMLInputFactory=com.ctc.wstx.stax.WstxInputFactory

like so:

Code Block
titlemvn jetty:run
<!-- Run the application using "mvn jetty:run" -->
<plugin>
	<groupId>org.mortbay.jetty</groupId>
	<artifactId>maven-jetty-plugin</artifactId>
	<configuration>
		<!-- Log to the console. -->
		<requestLog implementation="org.mortbay.jetty.NCSARequestLog">
			<!-- This doesn't do anything for Jetty, but is a workaround for a Maven bug
				 that prevents the requestLog from being set. -->
			<append>true</append>
		</requestLog>
		<systemProperties>
			<systemProperty>
				<name>tapestry.compress-whitespace</name>
				<value>false</value>
			</systemProperty>
			<systemProperty>
				<name>tapestry.production-mode</name>
				<value>false</value>
			</systemProperty>
			<systemProperty>
				<name>javax.xml.stream.XMLInputFactory</name>
				<value>com.ctc.wstx.stax.WstxInputFactory</value>
			</systemProperty>
		</systemProperties>
	</configuration>
</plugin>

Check google for more information: http://www.google.com/search?hl=en&q=com.sun.xml.stream.ZephyrParserFactory+cannot+be+cast+to+org.codehaus.stax2.XMLInputFactory2&aq=f&oq=&aqi=