Web Services

Here we have a link to a Tapestry page that acts as a REST-like web service.
PersonFind/1
The page gets the Person, copies the data wanted from Person into a Person01 object, uses Java's JAXB to marshal the Person01 into XML, and returns the XML as a StreamResponse. Easy!

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</h3>
    
    Here we have a link to a Tapestry page that acts as a REST-like web service.<br/>

    <div class="eg">
        <t:pagelink page="examples/ws/PersonFind" context="literal:1">PersonFind/1</t:pagelink>
    </div>  
    
    The page gets the Person, copies the data wanted from Person into a Person01 object, uses Java's JAXB to marshal 
    the Person01 into XML, and returns the XML as a StreamResponse. Easy!<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/WebServices.tml"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/ws/WebServices.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/PersonFind.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 WebServices {
}


.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 javax.ejb.EJB;
import javax.servlet.http.HttpServletResponse;
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 org.apache.tapestry5.StreamResponse;
import org.apache.tapestry5.services.Response;

public class PersonFind {

    // Generally useful bits and pieces

    @EJB
    private IPersonFinderServiceLocal personFinderService;

    // The code

    Object onActivate(final Long personId) {

        return new StreamResponse() {
            private InputStream inputStream;

            @Override
            public void prepareResponse(Response response) {
                Person01 person01 = findPerson(personId);

                if (person01 == null) {
                    try {
                        response.sendError(HttpServletResponse.SC_NOT_FOUND, "Resource not found");
                    }
                    catch (IOException e) {
                        throw new RuntimeException("Failed to redirect?", e);
                    }
                }

                else {
                    try {
                        JAXBContext context = JAXBContext.newInstance(person01.getClass());
                        Marshaller marshaller = context.createMarshaller();
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                        marshaller.marshal(person01, 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 Person01 findPerson(Long personId) {
        Person01 response = null;

        // Ask business layer to find the person

        Person person = personFinderService.findPerson(personId);

        // If person exists, create a response object

        if (person != null) {
            response = new Person01(person.getId(), person.getFirstName(), person.getLastName(), person.getRegion(),
                    person.getStartDate());
        }

        return response;
    }
}


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;
    }

}