Upload
chrgomez
View
29
Download
2
Embed Size (px)
Citation preview
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]