RESTful Services With GWT and Apache CXF

44
1 Building and consuming RESTful JSON services with Apache CXF and Google Web Toolkit Adrian Trenaman, Distinguished Consultant, IONA Technologies [email protected]

Transcript of RESTful Services With GWT and Apache CXF

  • 1Building and consuming RESTful JSON services with Apache CXF and Google Web Toolkit

    Adrian Trenaman, Distinguished Consultant, IONA [email protected]

  • 2 2008 IONA Technologies

    IntroductionGoogle Web Toolkit provides an excellent toolkit for RESTful AJAX clients.

    but doesnt provide a compelling solution for the server side.

    Apache CXF provides a framework for building RESTful servers.GWT and CXF together offer a compelling solution.

    Agenda:GWT overviewA RESTful Hello, World (in time honoured tradition)A document-oriented RESTful serviceConvention-based servicesUsing JSON payloadGWT client techniques

    This is a technical session; expect to learn enough about GWT and CXF to go out and build your own solutions.

    This is a technical session; expect to learn enough about GWT and CXF to go out and build your own solutions.

  • 3 2008 IONA Technologies

    Google Web Toolkit (GWT) a brief overview

  • 4 2008 IONA Technologies

    GWT overview

    GWT allows you to build dynamic web applications in Java Your Java is compiled into cross-browser Javascript.

    Key components: JRE emulation library, web UI library, java-to-jscompiler, and a hosted web browser for debugging.

  • 5 2008 IONA Technologies

    GWT overview (cont)GWT is available as open-source under Apache Public License (APL) 2.0. Website: http://code.google.com/webtoolkit

    Benefits of GWT: Small application footprint (~100Kb) Excellent GUI performance Faster time-to-development: design, develop, debug, refactor in Java using your

    favourite IDE, then deploy as JS.

  • 6 2008 IONA Technologies

    :

    :Tomcat

    GWT and RPC

    GWT provides an RPC approach based on serialized Java over HTTP.

    Host a GWT service in a servlet engine the GWT servlet will handle serialization of parameters, return values and exceptions.

    Easy to use, but limits the reusability of services.

    :ServiceImpl

    :ServiceImpl

    :Client

    :Client

    Serialised Java Objects over HTTP

  • 7 2008 IONA Technologies

    GWT and AJAX

    GWT supports AJAX-style services Use asynchronous HTTP requests to transmit text-based payload such as XML

    or JSON. Apache CXF (Fuse) can provide the server-side solution.

    Rapidly produce JSON and XML services for GWT clients.

    :

    :Tomcat

    :ServiceImpl

    :ServiceImpl

    :Client

    :Client

    JSON or XML over HTTPCXF

  • 8 2008 IONA Technologies

    RESTful JSON Services with Fuse Service Framework / Apache CXF

  • 9 2008 IONA Technologies

    RESTful services with FUSEApproach:

    Annotate your Java service.Deploy - in Spring Framework, Tomcat, J2EE, or standalone.Consume most likely from AJAX clients.

    ContactsService.javaContactsService.java@WebService

    interface ContactsService {@Get

    @HttpResource(location=/contacts/id={id})public Contact getContact(int id);

    }

    @WebService

    interface ContactsService {@Get

    @HttpResource(location=/contacts/id={id})public Contact getContact(int id);

    }

    http://frodo:9000/contacts/id=123 Go >

    AdeTrenamanIONA TechnologiesPrincipal [email protected]+353-86-6051026

    frodo:

    :ContactsService

    :ContactsService

    HTTP 9000GET

  • 10 2008 IONA Technologies

    RESTful services with FUSE (cont)No formal interface definition language (WSDL, IDL) is used.

    However, XSD is often used for data definition.

    A services parameters are passed via payload and URL, e.g.: http://localhost:9000/contacts/id=007

    FUSE supports XML and JSON payloads

    Services make use of a natural mapping from HTTP verbs to CRUD operations.

    POST: Create a new item of data on the service.GET: Retrieve data from the service.PUT: Update data on the service.DELETE: Delete data from services.

  • 11 2008 IONA Technologies

    A RESTful Hello, World

  • 12 2008 IONA Technologies

    Hello WorldA simple Hello, World application:

    A client performs a HTTP GET using a URL like: http://localhost:9000/hw/sayHello/user=ade&msg=helloThe server receives the parameters and returns a string value.

    Steps: Write a simple Java bean to match the URI template: in this case, to hold the user and msg parameters.Write your business logic in JavaUse a browser, or tools such as curl or wget, to perform a HTTP GET.

  • 13 2008 IONA Technologies

    Parameters beanInput parameters for the sayHello operation can be modelled easily as a Java bean.

    Parameters map to bean fields with appropriate getters and setters.

    URI: http://localhost:9000/hw/sayHello/user=ade&msg=hello

    Java bean:public class SayHello {private String user;private String msg;

    public String getMsg() { }public void setMsg(String message) {}public String getUser() {}public void setUser(String user) {}

    }

  • 14 2008 IONA Technologies

    Business Logic

    @WebServicepublic class HelloWorld {

    @Get@HttpResource(

    location="/sayHello/user={user}&msg={msg})public String sayHello(SayHello params) {

    System.out.println(params.getUser() + " said '" + params.getMsg() + "'");

    return "Thanks for your message!";}

    }

    Annotate the class as a web service.

    Annotate the class as a web service.

    This method will respond to a HTTP GET

    This method will respond to a HTTP GET

    at this location!

    at this location!

    Everything else is just plain old Java.

    Everything else is just plain old Java.

  • 15 2008 IONA Technologies

    Deploying your serviceYou can deploy your service into a Spring container, Tomcat, a J2EE application server, or run as a Java mainline.

    Boiler plate code:

    String URL = "http://localhost:9000/hw/";

    JaxWsServerFactoryBean svc = new JaxWsServerFactoryBean();svc.setBindingId(HttpBindingFactory.HTTP_BINDING_ID);svc.setAddress(URL);svc.setServiceBean(new HelloWorld());svc.getServiceFactory().setWrapped(false);svc.create();

    System.out.println(Listening on " + URL);

  • 16 2008 IONA Technologies

    Testing your serviceYou can test your REST services by simply pointing a browser at the URL.

    This will implicitly perform a GET on your service.

    Alternatively, you can use command-line tools like wget or curlcurl X GET

    http://localhost:9000/hw/sayHello/user=ade&msg=hello

    The output should be:

    Thanks for your message!

    Namespace derived from Java package.

    Namespace derived from Java package.

  • 17 2008 IONA Technologies

    Hello, world: lessons learntThe Hello, World example shows how expose a Java method as a RESTful service

    with the use of just a few annotations.By default the response payload is returned as XML; later well see how to easily change this to JSON.

    This approach works well for algorithmic services.Like calculate my tax.

    The next section focuses on more resource-based service.Like retrieve customer details for customer 007654321, or create new customer.

  • 18 2008 IONA Technologies

    A RESTful resource-based service.

  • 19 2008 IONA Technologies

    Resource-based serviceConsider a resource such as Customer contact details.

    Perhaps you have this modelled as a Java class.Alternatively, you might have this modelled as an XML Schema.

    If so, then you can easily generate an equivalent Java class using the JAX-B support provided by FUSE.

    You want a RESTful service providing CRUD operations for your document:

    Create, retrieve, update, delete customer contacts.

    FUSE supports this via the use of URI templates (as before), along with @Post, @Get, @Post, @Delete annotations.

    FUSE will marshal the payload (if any) into your parameters.

  • 20 2008 IONA Technologies

    Update

    Delete

    CreateRetrieve

    RESTful HTTP verbsYou can use the full palette of HTTP verbs:

    GET http://.../contacts

    GET http://.../contacts/id=123

    PUT http://.../contacts/id=123

    POST http://.../contacts/id=123

    DELETE http://.../contacts/id=123

    GET http://.../contacts/name=ade

  • 21 2008 IONA Technologies

    RESTful HTTP verbsHowever: client technologies may only support GET and POST.

    Tip: design your service for the lowest common denominator.

    Update

    Delete

    CreateRetrieve

    GET http://.../contacts

    GET http://.../contacts/id=123

    PUT POST http://.../contacts/id=123

    POST GET http://.../contacts/create

    DELETE GEThttp://.../contacts/del/id=123

    GET http://.../contacts/name=ade

  • 22 2008 IONA Technologies

    Contact service: interfaceDefining an interface for the ContactService:

    @WebServicepublic interface ContactService{

    @Get@HttpResource(location="/contacts/create")public Contact createContact() throws CannotCreate;

    @Get@HttpResource(location="/contacts/delete/id={id}") public void removeContact(RemoveContact params);

  • 23 2008 IONA Technologies

    Contacts service: interface (cont)@Get@HttpResource(location="/contacts")public Contacts getContacts();

    @Get@HttpResource(location="/contacts/id={id}")public Contact getContact(GetContact gc) throws NotFound;

    @Get@HttpResource( location="/contacts/firstName={firstName}&lastName={lastName}

    )public Contacts findContacts(FindContactsByName params);

  • 24 2008 IONA Technologies

    Contacts service: interface (cont)

    @Post@HttpResource(location="/contacts/{id}") public void updateContact(Contact params);

  • 25 2008 IONA Technologies

    Convention-based RESTful-services

  • 26 2008 IONA Technologies

    RESTful services by conventionFUSE can introspect a Java class and deploy as a RESTful service.

    You dont have to provide annotations.FUSE adopts a number of conventions to give an intuitive deployment.

    The introspection process must determine:What HTTP verb to use POST, PUT, GET or DELETE?What URL context should the method relate to?

    Examples:removePerson(long id) DELETE /people/{id}

    updatePerson(long id) PUT /people/{id}

  • 27 2008 IONA Technologies

    ConventionsConventions are intuitive; best learnt by example.

    Method: Collection getContacts()Maps to: GET /contacts.

    Method: Contact getContact(long id)Maps to: GET /contacts/{id}.Note the use of a pluralizer in constructing the URI template.

    Method: void updateContact(long id, Contact c)Maps to: PUT /contacts/{id}.The contact information is transferred as XML payload.

  • 28 2008 IONA Technologies

    Conventions (cont)Method: void removeContact(long id)

    Maps to: DELETE /contacts/{id}Methods that begin with remove or delete are mapped to HTTP DELETE.

    Method: void createContact(Contact c)Maps to: POST /contactsMethods that begin with create or add are mapped to HTTP POST.The contact information is transferred as XML payload.

  • 29 2008 IONA Technologies

    Support for JSON

  • 30 2008 IONA Technologies

    JSON - JavaScript Object NotationThe RESTful services shown previously return data formatted as XML.

    FUSE can generate XML from JAX-B annotated classes, and classes without annotations (applying suitable conventions).

    Alternative payload formats, such as JSON, may be preferred for RESTful services.

    JSON (JavaScript Object Notation) is a simple name-value format that facilitates rapid marshalling and unmarshalling:

    See http://www.json.org.May be preferred by web developers writing Javascript clients.

    FUSE supports JSON by replacing the XML marshaller with a JSON marshaller.

  • 31 2008 IONA Technologies

    Badgerfish vs. mapped notationRecall: XML elements are typically qualified with their namespace.

    JoeBlogsIONA Technologies Consultant [email protected] +353-1234567+353-1234567

  • 32 2008 IONA Technologies

    Badgerfish vs. mapped notation (cont)When marshalling as JSON, the XML namespaces can be inserted in a mangled form, using Badgerfish notation.

    {"getContactResponse":{"@xmlns":{"$":"http:\/\/easyrest\/"},"ns2:Contact":{

    "@xmlns":{"ns2":"http:\/\/www.iona.com\/demo\/contact"},"@id":"123","firstName":{"$":"Joe"}, "lastName":{"$":"Blogs"},"company":{"$":"IONA Technologies"},"title":{"$":" Consultant"},"email":{"$":"[email protected]"},"mobile":{"$":"+353-1234567"},"phone":{"$":"+353-1234567"}

    }}}

  • 33 2008 IONA Technologies

    Badgerfish vs. mapped notation (cont)Some prefer to perform an explicit namespace mapping:

    {"easyrest.getContactResponse":{"contact.Contact":{

    "@id":"123","firstName":"Joe","lastName":"Blogs","company":"IONA Technologies","title":"Consultant","email":"[email protected]","mobile":"+353-1234567","phone":"+353-1234567"

    }}}

  • 34 2008 IONA Technologies

    Configuring an endpoint for JSONFUSE supports both Badgerfish and mapped approaches; to use Badgerfish:

    Map properties = ;

    BadgerFishXMLInputFactory xif = new BadgerFishXMLInputFactory();

    properties.put(XMLInputFactory.class.getName(), xif);

    BadgerFishXMLOutputFactory xof = new BadgerFishXMLOutputFactory();

    properties.put(XMLOutputFactory.class.getName(), xof);

    endpoint.setProperties(properties);

  • 35 2008 IONA Technologies

    Configuring an endpoint for JSON (cont)For mapped JSON:

    HashMap nstojns = ;nstojns.put("http://www.iona.com/demo/contact", "contact");nstojns.put("http://easyrest/", "easyrest");

    MappedXMLInputFactory xif = new MappedXMLInputFactory(nstojns);

    properties.put(XMLInputFactory.class.getName(), xif);

    MappedXMLOutputFactory xof = new MappedXMLOutputFactory(nstojns);

    properties.put(XMLOutputFactory.class.getName(), xof);

    endpoint.setProperties(properties);

  • 36 2008 IONA Technologies

    Aside: HTTP content-typeWhen returning JSON payload, the HTTP Content-Type header should be set to something other than text/xml

    After all, the payload isnt XML, its JSON.

    Use the properties map to set the content-type: properties.put("Content-Type", "text/plain");

    Could also set to application/json if preferred.

  • 37 2008 IONA Technologies

    GWT client code

  • 38 2008 IONA Technologies

    GWT and AJAX boilerplate Java code

    RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, "http://...");

    try {Request req = builder.sendRequest(null, new RequestCallback() {public void onError(Request request, Throwable exception) {}

    public void onResponseReceived(Request request,Response response) {

    }});

    } catch (RequestException e) {}

  • 39 2008 IONA Technologies

    GWT and AJAX boilerplate Java code - notes

    The RequestBuilder approach is favoured. An alternative approach, using the raw HTTPRequest class, is internally-

    focussed and may be deprecated.

    RequestBuilder only supports HTTP GET and POST.DELETE and PUT and other verbs not supported, due to a bug in Safari

    implementation of the XMLHTTPRequest.

  • 40 2008 IONA Technologies

    GWT support for JSON

    GWT provides support for creating and parsing JSON payload. See classes in package com.google.gwt.json.client.

    public String toJSON() { JSONObject obj = new JSONObject();obj.put("firstName", new JSONString(Ade));obj.put("lastName", new JSONString(Trenaman));

    JSONObject contact = new JSONObject();contact.put("er.Contact", obj);return contact.toString();

    }

    {"er.Contact":{"firstName":"Ade","lastName":"Trenaman"}}{"er.Contact":{"firstName":"Ade","lastName":"Trenaman"}}

  • 41 2008 IONA Technologies

    GWT support for JSON (cont)A similar API exists for parsing JSON.

    JSONValue jsonValue = JSONParser.parse(responseText);JSONObject obj = jsonValue.isObject();JSONValue contact = obj.get("er.Contact");JSONValue firstName = contact.isObject().get("firstName");

  • 42 2008 IONA Technologies

    Summary

  • 43 2008 IONA Technologies

    Summary

    Use CXF (Fuse) to provide JSON services for AJAX clients.Native support for RESTful JSON and XML payloads using explicit or implied conventions.CXF first implementation of JSR-311 Java API for RESTful Web Services.

    Use GWT to build dynamic, flexible browser-based clients.Full API for JSON and AJAX interactions.

    Drawbacks: GWTs JSON API makes you do a lot of the hard work for marshalling and unmarshalling.

    Perhaps leverage JSNI?

  • 44 2008 IONA Technologies

    ResourcesGoogle Web Toolkit:

    Go to http://code.google.com/webtoolkit

    CXF, Fuse Service Framework and IONA:Learn more: http://open.iona.com/Download: http://open.iona.com/downloads/Browse demos:

    samples/restful_http_bindingsamples/restful_dispatch

    Contribute!

    Need help? Visit the forums on Apache and open.iona.com. Contact us: [email protected]