Web Services More

Some more examples of Tapestry pages acting as a REST-like web service.
PersonsFind
PersonsFind?namefilter=a
For a more RESTful implementation try tapestry-resteasy.

References: PageLink, JAXB, StreamResponse, Response, REST.

Home


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- We need a doctype to allow us to use special characters like &nbsp; 
     We use a "strict" DTD to make IE follow the alignment rules. -->
     
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"> 
<body class="container">
    <h3>Web Services More</h3>
    
    Some more examples of Tapestry pages acting as a REST-like web service.<br/>
    
    <div class="eg">
        <t:pagelink page="examples/ws/PersonsFind">PersonsFind</t:pagelink><br/>
        <t:pagelink page="examples/ws/PersonsFind" parameters="{'namefilter':'a'}">PersonsFind?namefilter=a</t:pagelink><br/>
    </div>
    
    For a more RESTful implementation try <a href="http://www.tynamo.org/tapestry-resteasy+guide">tapestry-resteasy</a>.<br/><br/>

    References: 
    <a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/PageLink.html">PageLink</a>, 
    <a href="http://en.wikipedia.org/wiki/Java_Architecture_for_XML_Binding">JAXB</a>, 
    <a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/StreamResponse.html">StreamResponse</a>,
    <a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/services/Response.html">Response</a>,
    <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>.<br/><br/>
    
    <t:pagelink page="Index">Home</t:pagelink><br/><br/>
    
    <t:tabgroup>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/ws/WebServicesMore.tml"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/ws/WebServicesMore.java"/>
        <t:sourcecodetab src="/web/src/main/resources/META-INF/assets/css/examples/plain.css"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/ws/PersonsFind.java"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/models/examples/ws/Persons01.java"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/models/examples/ws/Person01.java"/>
    </t:tabgroup>
</body>
</html>


package jumpstart.web.pages.examples.ws;

import org.apache.tapestry5.annotations.Import;

@Import(stylesheet = "css/examples/plain.css")
public class WebServicesMore {
}


.eg {
                margin: 20px 0;
                padding: 14px;
                border: 1px solid #ddd;
                border-radius: 6px;
                -webkit-border-radius: 6px;
                -mox-border-radius: 6px;
}


package jumpstart.web.pages.examples.ws;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.ejb.EJB;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import jumpstart.business.domain.person.Person;
import jumpstart.business.domain.person.iface.IPersonFinderServiceLocal;
import jumpstart.web.models.examples.ws.Person01;
import jumpstart.web.models.examples.ws.Persons01;

import org.apache.tapestry5.StreamResponse;
import org.apache.tapestry5.annotations.ActivationRequestParameter;
import org.apache.tapestry5.services.Response;

public class PersonsFind {
    static private final int MAX_RESULTS = 30;

    // Query string parameters

    @ActivationRequestParameter(value = "namefilter")
    private String partialName;

    // Generally useful bits and pieces

    @EJB
    private IPersonFinderServiceLocal personFinderService;

    // The code

    StreamResponse onActivate() {

        return new StreamResponse() {
            private InputStream inputStream;

            @Override
            public void prepareResponse(Response response) {
                Persons01 persons = null;

                if (partialName == null) {
                    persons = findPersons();
                }
                else {
                    persons = findPersons(partialName);
                }

                try {
                    JAXBContext context = JAXBContext.newInstance(persons.getClass());
                    Marshaller marshaller = context.createMarshaller();
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    marshaller.marshal(persons, outputStream);

                    inputStream = new ByteArrayInputStream(outputStream.toByteArray());

                    // Set content length to prevent chunking - see
                    // http://tapestry-users.832.n2.nabble.com/Disable-Transfer-Encoding-chunked-from-StreamResponse-td5269662.html#a5269662
                    response.setHeader("Content-Length", "" + outputStream.size());
                }
                catch (JAXBException e) {
                    throw new IllegalStateException(e);
                }
            }

            @Override
            public String getContentType() {
                return "text/xml";
            }

            @Override
            public InputStream getStream() throws IOException {
                return inputStream;
            }
        };

    }

    public Persons01 findPersons() {

        // Ask business layer to find the persons

        List<Person> persons = personFinderService.findPersons(MAX_RESULTS);

        // Create a response object

        Persons01 response = new Persons01();

        // Populate the response object from the list

        for (Person person : persons) {
            Person01 person01 = new Person01(person.getId(), person.getFirstName(), person.getLastName(),
                    person.getRegion(), person.getStartDate());
            response.add(person01);
        }

        return response;
    }

    public Persons01 findPersons(String partialName) {

        // Ask business layer to find the persons

        List<Person> persons = personFinderService.findPersons(partialName, MAX_RESULTS);

        // Create a response object

        Persons01 response = new Persons01();

        // Populate the response object from the list

        for (Person person : persons) {
            Person01 person01 = new Person01(person.getId(), person.getFirstName(), person.getLastName(),
                    person.getRegion(), person.getStartDate());
            response.add(person01);
        }

        return response;
    }
}


package jumpstart.web.models.examples.ws;

import java.util.ArrayList;
import java.util.List;

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


@XmlRootElement(name = "persons")
@XmlAccessorType(XmlAccessType.FIELD)
public class Persons01 {

    @XmlElement(name = "person")
    private List<Person01> persons = new ArrayList<Person01>();

    public Persons01() {
    }

    public void add(Person01 person) {
        persons.add(person);
    }

}


package jumpstart.web.models.examples.ws;

import java.io.Serializable;
import java.util.Date;

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

import jumpstart.business.domain.person.Regions;

@XmlRootElement(name = "person")
@XmlAccessorType(XmlAccessType.FIELD)
@SuppressWarnings({ "serial", "unused" })
public class Person01 implements Serializable {

    @XmlAttribute(name = "id")
    private Long id;

    private String firstName;
    private String lastName;
    private Regions region;
    private Date startDate;

    private Person01() {
    }

    public Person01(Long id, String firstName, String lastName, Regions region, Date startDate) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.region = region;
        this.startDate = startDate;
    }

}