Junos Space SDK > Developer Guides > Junos Space Application Developer Guide > Programming with the Junos Space SDK > Reference Applications > HelloWorld

Understanding Methods Created Using the REST Interface Wizard

This topic describes how a REST method created by the REST Creation Wizard maps to a corresponding EJB method. As an example, consider the following EJB method:

public Country getCountryById (int id) throws Exception

The corresponding REST method created by the REST Creation Wizard is:

@Path("countries/{countryId}")
@GET
@RBAC(type = { CRUDEnum.READ }, capability = { "HelloWorldCap" })
@Produces({
        VendorConstants.APP_DATATYPE_PREFIX + ".world.country+xml;version=1",
        VendorConstants.APP_DATATYPE_PREFIX + ".world.country+json;version=1" })
public vnd.jssdk.helloworld.rest.v1.Country getCountryById(
        @PathParam("countryId") int param0);


Note: The media types are generated according to the vendor ID provided at the time of installation. For the reference application it is retrieved from the VendorConstants class at the EJB layer and is pre-determined as "jssdk".

Method Details

The @Path("countries/{id}") and @GET annotations signify that this REST method will be invoked when an HTTP client hits the URL http:[server]:[port]/api/jssdk/hello-world/world/countries/{id}

The @Produces indicates that this method will produce a media type named vnd.jssdk.helloworld.world.country, which has two representations: XML and JSON.

The @PathParam annotation specifies the input argument to the REST method.

REST DTO Example

The REST Creation Wizard also generates a data transfer object used as a return type or method parameter of a REST method. The DTO contains fields based on your selections in the wizard.

For example, the Country DTO will be similar to the following:

Note: All annotations starting with @HATEOAS will build HATEOAS links.

package vnd.jssdk.helloworld.rest.v1;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import net.juniper.jmp.interceptors.hateoas.HATEOAS;
import net.juniper.jmp.interceptors.hateoas.HATEOAS.LinkTypeEnum;
import net.juniper.jmp.parsers.annotations.Filterable;
import net.juniper.jmp.parsers.annotations.Sortable;

/*******************************************************************************
 * FILE NAME: Country.java
 * PURPOSE:   These comments are auto generated
 * Revision History: 
 * DATE:                          AUTHOR:              CHANGE:  
 * Wed Jun 15 12:22:14 IST 2011               Auto generated       Initial Version  
 ******************************************************************************/

/*
 * Class: Country 
 * Description: This type represent a Country
 * @MediaType application/vnd.<VENDOR_ID>.hello-world.world.country+json;version=1
     application/vnd.<VENDOR_ID>.hello-world.world.country+xml;version=1
 */
@XmlRootElement(name = "country")
@XmlAccessorType(XmlAccessType.NONE)
public class Country {
  /**
   * Collection of States
   */
  @XmlElement(name = "states")
  @HATEOAS(uri = "/states", context = HATEOAS.LinkTypeEnum.URI)
  private States states = null;
  /**
   * Link to Country
   */
  @HATEOAS(uri = "")
  @XmlAttribute(name = "uri")
  private String uri = null;
  /**
   * Country Id
   */
  @XmlElement(name = "id")
  private int id;
  /**
   * Country name
   */
  @XmlElement(name = "name")
  private String name;
  /**
   * Country Population
   */
  @XmlElement(name = "population")
  private Integer population;

  /**
   * @param states
   */
  public void setStates(States states) {
    this.states = states;
  }

  /**
   * @return states
   */
  public States getStates() {
    return states;
  }

  /**
   * @param uri
   */
  public void setUri(String uri) {
    this.uri = uri;
  }

  /**
   * @return uri
   */
  public String getUri() {
    return uri;
  }
  /**
   * Class: States
   * Description: This type provides a collection of States.
   * @MediaType application/vnd..hello-world.world.states+xml;version=1
          application/vnd..hello-world.world.states+json;version=1
   * */
  @XmlRootElement(name = "states")
  @XmlAccessorType(XmlAccessType.NONE)
  public static class States {

    /**
     * Link to State
     */
    @XmlAttribute(name = "uri")
    private String uri = null;

    /**
     * Collection of States
     */
    @HATEOAS(href = "/world/states/{id}", context = LinkTypeEnum.APPLICATION, uri = "/{id}")
    @XmlElement(name = "state")
    private java.util.Collection states;

    /**
     * @param uri
     */
    public void setUri(String uri) {
      this.uri = uri;
    }

    /**
     * @return uri
     */
    public String getUri() {
      return uri;
    }

    /**
     * @param states
     */
    public void setStates(java.util.Collection states) {
      this.states = states;
    }

    /**
     * @return java.util.Collection
     */
    public java.util.Collection getStates() {
      return states;
    }
    /**
     * Class: State 
* Description: This type represent a State. * @MediaType application/vnd.<VENDOR_ID>.hello-world.world.state+xml;version=1 application/vnd.<VENDOR_ID>.hello-world.world.state+json;version=1 **/ @XmlRootElement(name = "state") @XmlAccessorType(XmlAccessType.NONE) public static class State { /** * State Id * @Sortable * @Filterable */ @XmlElement(name = "id") private int id; /** * State Name * @Sortable * @Filterable */ @XmlElement(name = "name") private String name; /** * href Link to state */ @XmlAttribute(name = "href") private String link = null; /** * State Population * @Sortable * @Filterable */ @XmlElement(name = "population") private Long population; /** * Link to state */ @XmlAttribute(name = "uri") private String uri = null; public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } /** * @param link */ public void setLink(String link) { this.link = link; } /** * @param population */ public void setPopulation(Long population) { this.population = population; } /** * @return String */ @Sortable(moAttrName = "name") @Filterable(moAttrName = "name") public String getName() { return name; } /** * @return link */ public String getLink() { return link; } /** * @param name */ public void setName(String name) { this.name = name; } /** * @return Long */ @Sortable(moAttrName = "population") @Filterable(moAttrName = "population") public Long getPopulation() { return population; } /** * @return int */ @Sortable(moAttrName = "id") @Filterable(moAttrName = "id") public int getId() { return id; } /** * @param id */ public void setId(int id) { this.id = id; } } } /** * @param population */ public void setPopulation(Integer population) { this.population = population; } /** * @return String */ @Sortable(moAttrName = "name") @Filterable(moAttrName = "name") public String getName() { return name; } /** * @param name */ public void setName(String name) { this.name = name; } /** * @return Integer */ @Sortable(moAttrName = "population") public Integer getPopulation() { return population; } /** * @return int */ @Sortable(moAttrName = "id") public int getId() { return id; } /** * @param id */ public void setId(int id) { this.id = id; } }

Understanding HATEOAS

HATEOAS is the acronym for "Hypermedia As The Engine Of Application State". HATEOAS is implemented as:

  1. Links (href and uri attributes)
  2. Method tags

The terms uri and href in the context of HATEOAS are defined in the next sections.

uri

In every context, the uri attribute means that the element that carries this attribute is a resource and is located at the URI specified. HEAD, GET, PUT, and DELETE are legal against this URI, although they may be denied by the resource. POST to any URI always means "try to consume this" and can result in many different things.

Collections will allow POST of XML or JSON for one of the collection's elements and react to it by creating a new item in the collection and possibly some additional dynamically created objects.

Primary collections can be considered for an example of a uri. A primary collection contains original objects instead of object references. For example, the URI /api/jssdk/hello-world/world/countries will give a collection of countries containing a list of primary country objects. For a primary collection, a HATEOAS link should be shown as uri={uri}

href

In every context, the href attribute means that the element that carries this attribute is a reference to another object, and the target object is located at the URI specified in the "href" attribute. All elements below this element are considered pull-through data and cannot be written. If the client attempts to write such elements with a PUT of the current resource, the changes below this element will be ignored. To actually change any of these elements, the client must follow the "href" to the target object and operate on it there.

Secondary collections can be considered for an example of an href attribute. A secondary collection contains references to object(s) in a primary collection. For example, /api/jssdk/hello-world/world/country/{id} will return a Country object, which will contain a list of states assigned to it that refers to the states present in the primary collection at /api/jssdk/hello-world/world/states. A HATEOAS link of a secondary collection should be shown as href={href}, while a reference itself can be represented as uri={uri}

Consider the following annotation from the Country class example above:

@HATEOAS(uri= "")

This annotation is used to build the <uri> tag in the representation of the country XML element. Note that the Country class has a property named as uri with its getter/setter and an XmlAttribute named uri. The postprocessors will automatically prepend the URI that was used to access the resource in the URI given in the annotation. That is why an empty string is used here.

Consider the following annotation from the States static inner class in the example above:

@HATEOAS(uri="/states")

This annotation is used to build the <uri> tag in the representation of the states XML element. Note that the States class has a property named uri which has an XMLAttribute named uri. The postprocessors will automatically prepend the URI that was used to access the resource in the URI given in the annotation. That is why only states are provided in the annotation.

Consider the following annotation from the States static inner class example above:

@HATEOAS(href = "/states/{id}",context = LinkTypeEnum.APPLICATION, uri = "/{id}")

This annotation is used to specify the <href> tag attributes for a single state and the <uri> tag attribute for its reference inside the Country. The following is the expected output in the XML format:

<country uri="/api/jssdk/hello-world/world/country/9">
 <id>9</id>
 <name>UnitedStates</name>
 <population>307006550</population>
 <states uri="/api/jssdk/hello-world/world/country/9/states">
   <state uri="/api/jssdk/hello-world/world/9/states/12" href="/api/jssdk/hello-world/world/states/12">
     <id>12</id>
     <name>California</name>
     <population>36961664</population>
   </state>
   <state uri="/api/jssdk/hello-world/world/9/states/13" href="/api/jssdk/hello-world/world/states/13">
     <id>13</id>
     <name>Maryland</name>
     <population>5699478</population>
   </state>
 </states>
</country>