Skip to content
carterpage edited this page Oct 31, 2012 · 2 revisions

This page is currently out of date. We are working on an updated tutorial. - 10/31/2012

Suppose you have an existing User domain object, that you would like to expose as a REST resource:

public class User
{
    private long _id;
    private String _name;
    private Set<Artist> _favoriteArtists;

    public long getId()
    {
        return _id;
    }

    public String getName()
    {
        return _name
    }

    public Set<Artist> getFavoriteArtists()
    {
        return _favoriteArtists;
    }
}

1. Maven

Import the relevant Yoga projects.

Add the following to your pom.xml, and define yoga.version to the current number (0.2.0 as of this writing):

<dependency>
    <groupId>org.skyscreamer</groupId>
    <artifactId>yoga-core</artifactId>
    <version>${yoga.version}</version>
</dependency>
<dependency>
    <groupId>org.skyscreamer</groupId>
    <artifactId>yoga-springmvc</artifactId>
    <version>${yoga.version}</version>
</dependency>

2. Controllers

Make sure your SpringMVC controller supports RESTful URLs. In this example, we are supporting GET requests to /user (to retrieve all users) and /user/{id} (to retrieve a single user by id number)

@Controller
@RequestMapping("/user")
public class UserController extends AbstractController<User>
{
    @RequestMapping
    public List<User> getUsers()
    {
        return _userService.findAllUsers();
    }

    @RequestMapping("/{id}")
    public User getUser( @PathVariable long id )
    {
        return _userService.findUser( id );
    }
}

3. Configuration

Next, using the Spring-RestEasy integration, configure your RestEasy application as follows:

<context:component-scan base-package="org.skyscreamer.yoga.demo.resteasy.resources" />
<context:component-scan base-package="org.skyscreamer.yoga.resteasy" use-default-filters="false">
<context:include-filter type="annotation" expression="javax.ws.rs.ext.Provider"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
</context:component-scan>

<import resource="classpath:springmvc-resteasy.xml"/>

<bean id="resteasy.spring.bean.processor" class="org.skyscreamer.yoga.resteasy.util.RESTEasySpringListener"/>

<bean id="resteasy.dispatcher" class="org.jboss.resteasy.core.SynchronousDispatcher"
    depends-on="resteasy.intializer">
    <constructor-arg ref="resteasy.providerFactory" />
    <property name="mediaTypeMappings">
        <map>
        	<entry key="json" value="application/json" />
        	<entry key="xml" value="application/xml" />
        	<entry key="xhtml" value="text/html" />
        </map>
    </property>
</bean>

You can see that we have elected to support rendering your REST resources in JSON, XML, or XHTML response format. Of course, you can remove any formats that you don't wish to support from the dispatcher configuration.

Finally, in your application context register the ResultTraverser, which will navigate your nested object graph to return results that match what is requested by the Selector:

<bean id="resultTraverser" class="org.skyscreamer.yoga.mapper.ResultTraverser" />

4. Deploy and Run

Start your server. You can now issue a browser request to your controller, passing in selector as a request parameter to determine what fields of the User object will be rendered in the response:

/user.json?selector=:(id,name)

Check out the other supported formats:

/user.xml?selector=:(id,name)
/user.xhtml?selector=:(id,name)

Notice that the User object has a property named favoriteArtists, which is a complex property type (set of Artist objects). If the Artist object has properties to render, you can name them in a nested selector. This request retrieves data for the user with ID#1, along with some information about his favorite artists:

/user/1.json?selector=:(id,name,favoriteArtists:(name,currentRecordLabel))

5. Using @Core Annotation

As you can imagine, these selector strings can get very verbose for rich resources or complex object graphs. To simplify the selectors, you can designate certain properties of your REST resource as Core properties. Core properties will always be returned when the resource is rendered, and do not need to be named in the Selector.

One way to designate a property as a Core property is to use the @Core annotation that is supplied with the Yoga libraries. Here, we apply the annotation to two getter methods of the User class:

@Core
public long getId()
{
    return _id;
}

@Core
public String getName()
{
    return _name
}

Now, the following request will render the id and name properties of the User resource.

/user/1.json

And this request will render the id and name fields of the User resource as well as the name and currentRecordLabel fields of all of the user's favorite artists.

/user/1.json?selector=:(favoriteArtists:(name,currentRecordLabel))

6. Advanced Yoga

This is a great example for getting started quickly, and seeing what you can do with selectors in Yoga. We've been operating under the naive (but fun!) assumption that all of the data you would like to expose to REST requests is encapsulated in properties on your model objects, and that you want to expose all of your model data to anyone who asks.

To learn how to perform a more controlled deployment of Yoga, proceed to Configuring Resources with FieldPopulators