restful web service with jboss fuse
TRANSCRIPT
Building JSON RESTful Web ServicesUsing JBoss Fuse
About THis PresentationThis presentation will focus on:
● RESful Web Service● JSON Format - No detail about XML or other format message transformation● JAX-RS standard - No detail about JAX-WS● Apache CXF● JBoss Fuse 6.2
RESTful Web Service
RESTful Web Services - INTRODUCTIONRepresentational State Transfer(REST)
● a software architecture style that centers around the transmission of data over HTTP, using only the four basic HTTP verbs.
● everything is a resource
● The state/data of the resource can be retrieved, changed, deleted commonly using HTTP verbs (GET, POST, PUT, DELETE, etc.)
● resource identified by Uniform Resource Identifiers (URIs), for example /people/unyil
Resource RepresentationCommonly used:
● JSON
{ "ID": "1", "Name": "Unyil Kucing", "Email": "[email protected]", "Country": "Indonesia"}
● XML
<Person> <ID>1</ID><Name>Unyil Kucing</Name><Email>[email protected]</Email><Country>India</Country></Person>
Request - Response ExamplePOST http://hostname/Person/ HTTP/1.1Host: hostnameContent-Type: text/xml; charset=utf-8Content-Length: 123
<?xml version="1.0" encoding="utf-8"?><Person> <ID>1</ID> <Name>Unyil Kucing</Name> <Email>[email protected]</Email> <Country>Indonesia</Country></Person>
HTTP/1.1 200 OKServer: ejlp-web-engine 1.0Content-Length: 263Content-Type: application/json; charset=utf-8
{ "ID": "1", "Name": "Unyil Kucing", "Email": "[email protected]", "Country": "Indonesia"}
Commonly URI & HTTP Method Usage Resource GET PUT POST DELETE
Collection URI, such as
http://api.example.com/resources/
List the URIs and perhaps
other details of the
collection's members.
Replace the
entire collection
with another
collection.
Create a new entry in the
collection. The new entry's
URI is assigned
automatically and is usually
returned by the operation.[11]
Delete the
entire
collection.
Element URI, such as
http://api.example.com/resources/item17
Retrieve a representation
of the addressed member
of the collection,
expressed in an
appropriate Internet media
type.
Replace the
addressed
member of the
collection, or if it
does not exist,
create it.
Not generally used. Treat the
addressed member as a
collection in its own right
andcreate a new entry in it.[11]
Delete the
addressed
member of
the
collection.
HTTP MethodMethod Operation performed on server Quality
GET Read a resource. Does not have any effect on the original value of the resource
PUT Insert a new resource or update if the resource already exists.
Gives the same result no matter how many times you perform it
POST Insert a new resource. Also can be used to update an existing resource.
N/A
DELETE Delete a resource . Gives the same result no matter how many times you perform it
OPTIONS List the allowed operations on a resource.
Does not have any effect on the original value of the resource
HEAD Return only the response headers and no response body.
Does not have any effect on the original value of the resource
HTTP Response Code200 OK General success status code. This is the most common code. Used to indicate success.201 CREATEDSuccessful creation occurred (via either POST or PUT). Set the Location header to contain a link to the newly-created resource (on POST). Response body content may or may not be present.
204 NO CONTENTIndicates success but nothing is in the response body, often used for DELETE and PUT operations.
400 BAD REQUESTGeneral error for when fulfilling the request would cause an invalid state. Domain validation errors, missing data, etc. are some examples.
401 UNAUTHORIZEDError code response for missing or invalid authentication token.
403 FORBIDDENError code for when the user is not authorized to perform the operation or the resource is unavailable for some reason (e.g. time constraints, etc.).
404 NOT FOUNDUsed when the requested resource is not found, whether it doesn't exist or if there was a 401 or 403 that, for security reasons, the service wants to mask.
HTTP Response Code405 METHOD NOT ALLOWEDUsed to indicate that the requested URL exists, but the requested HTTP method is not applicable. For example, POST /users/12345 where the API doesn't support creation of resources this way (with a provided ID). The Allow HTTP header must be set when returning a 405 to indicate the HTTP methods that are supported. In the previous case, the header would look like "Allow: GET, PUT, DELETE"
409 CONFLICTWhenever a resource conflict would be caused by fulfilling the request. Duplicate entries, such as trying to create two customers with the same information, and deleting root objects when cascade-delete is not supported are a couple of examples.
500 INTERNAL SERVER ERRORNever return this intentionally. The general catch-all error when the server-side throws an exception. Use this only for errors that the consumer cannot address from their end.
JSON FORMAT
JSON over XML● Still readable by human● Simple ● JSON does not have many concepts found in XML such as namespaces,
attributes or entity references● Support interface definition? YES
○ WADL○ Swagger○ RAML○ API Blueprint
Swagger UI
Swagger Example{ "swagger": "2.0", "info": { [...] }, "schemes": ["https"], "consumes": ["application/json"], "produces": ["application/json"], "paths": { "/user": { "get": { "responses": { "200": { "description": "users retrieved", "schema": { "type": "array", "items": { "$ref": "#/definitions/User" } } } } } } },
"definitions": { "User": { "type": "object", "additionalProperties": false, "properties": { "uid": { "type": "string" }, "email": { "type": "string" }, "phone": { "type": "string" } }, "required": ["uid", "email", "phone"] } }}
JSON and RESTful WS in
JBoss Fuse
RESTful Web Service in JBoss Fuse● RESTful Web Service is supported in JBoss Fuse by Apache CXF component● CXF implement JAX-RS standard● CXF can be used as REST Client or Server
Apache CFXCXF provides:
● Java API for building Web Service using JAX-WS○ Generating WSDL from Java classes and generating Java classes from WSDL○ WS-* standards support e.g. WS-Addressing, WS-Policy, WS-ReliableMessaging and
WS-Security○ etc
● Java API for RESTful Web Services JAX-RS 2.0 (JSR-339), JAX-RS 1.1 (JSR-311)○ Generating WADL from services, generating Java Interface from WADL
● Can be embedded in standalone app, used in Java EE Server app or in OSGi engine (JBoss Fuse)
RESTful Web Services in JBoss FuseCan be developed WITH or WITHOUT Camel
● WITH Camel○ Good for RESTful-ized a non JAX-RS Java Class ○ URI defined in config file (blueprint.xml)○ Options:
■ Using CXFRS component (http://camel.apache.org/cxfrs.html)■ Using REST wrapper layers
● REST DSL (in camel-core)
● Rest component (in camel-core)
● WITHOUT Camel:○ Good for Atomic Service○ No Routing (Integration flow)○ Create a RESTful (JAX-RS) web service using CXF and expose it with the OSGi HTTP
Service.○ URI, HTTP method is defined in Java Class using Anotation○ Quickstart project: https://github.com/jboss-fuse/quickstarts/tree/5715944/rest
RESTful service in CamelWrapper Layer:
● REST DSL (in camel-core)
● Rest component (in camel-core)
rest("/say").get("/hello/{name}") .route() .transform() .simple("Hello ${header.name}");
from("rest:get:say:/hello/{name}") .transform() .simple("Hello ${header.name}");
RESTful service in Camel● Spark-Rest component (in camel-spark-rest)
● Restlet component (in camel-restlet)● Servlet component (in camel-servlet)
JAX-RS1. The root URI for the resources exposed
by the service2. Public constructor3. HTTP verbs
4. Sub-resource, URI for the sub-resource, as specified using the the @Path annotation, is customerservice/order/id
Install & Run FuseBefore building and running this quick start you need:
● Maven 3.0.4 or higher
● JDK 1.6 or 1.7
● JBoss Fuse 6.2.1
unzip ~/RH_JBOSS_INSTALLER/Fuse_6.2.1/jboss-fuse-full-6.2.1.redhat-084.zip -d /Servers/
sed -i.orig 's/#admin/admin/g' /Servers//jboss-fuse-6.2.1.redhat-084/etc/users.properties
/Servers/jboss-fuse-6.2.1.redhat-084/bin/start
tail -f /Servers/jboss-fuse-6.2.1.redhat-084/data/log/fuse.log
$FUSE_HOME=/Servers/jboss-fuse-6.2.1.redhat-084
1. Install Fuse 6.2.12. Uncomment line “#admin” (remove “#”) to
set a username and password3. Start Fuse4. See the log file
Open to Fuse Client
cd /Servers/jboss-fuse-6.2.1.redhat-084/
./client
Fuse Directory Structure
Folder quickstart:
Simple sample project
Import Quickstart Project● Open Eclipse (JBDS), Create new Workspace● File > Import, “Existing Maven Projects”, Next● Root Directory: “/Servers/jboss-fuse-6.2.1.redhat-084/quickstarts/”● Next, Finish
Eclipse/JBDS Setting● Help > Preferences● Type “Maven” in the search textbox● Select Errors/Warning, change “Plugin execution…” to “Ignore”
Eclipse/JBDS Setting● Help > Preferences● Type “Maven” in the search textbox● JBoss Maven Integration > “Configure Maven Repositories..”
Maven repo: https://repository.jboss.org/nexus/content/groups/ea/
Project Structure
Some POJOs(Business Objects)
RESTful Service
OSGi Configuration File
Maven Configuration File
For real project, better to separate Business Object and Service classes in different
Maven Project
Navigate to Package Explorer view, and expand “cfx-rest” project
JAX-RS Service ProviderUsing Java annotation to define URI of the
service and documentation
Defining HTTP method, URI, resource type, documentation, HTTP
response code
Imported Package
JAX-RS
SWAGGER
OSGI-INF/bluerprint/blueprint.xml
Define the Service Provider bean to be
able to used by other
Documentation: JAX-RS Endpoint: https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_Fuse/6.2.1/html/Apache_CXF_Development_Guide/JAXRSEndpointConfig.html
http://cxf.apache.org/docs/jaxrs-services-configuration.html#JAXRSServicesConfiguration-Blueprint
Create a REST serveraddress: http://hostname:
port/cfx/crm
Create a REST serveraddress: http://hostname:
port/cfx/crm
blueprint.xmlXML Namespace for JAX-RS using CXF
Prefix Namespace
(default) http://www.osgi.org/xmlns/blueprint/v1.0.0
cxf http://cxf.apache.org/blueprint/core
jaxrs http://cxf.apache.org/blueprint/jaxrs
blueprint.xmlDocumentation (Fuse 6.2.1):
● 6.1.2. jaxrs:server Attributes
● 16.1.3. jaxrs:server Child Elements
https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_Fuse/6.2.1
Install Projectosgi:install -s mvn:org.jboss.quickstarts.fuse/cxf-rest/6.2.1.redhat-084
OSGi Server InformationOSGi > Server
Standaloneserver
information
JBoss FUSE Management ConsoleAccess to http://localhost:8181/hawtio
$FUSE_HOME/etc/jetty.xml:
<Property name="jetty.port" default="8181"/>
$FUSE_HOME/etc/org.ops4j.pax.web.cfg:
org.osgi.service.http.port=8181
Install New Bundle (Application)OSGi > Bundles
Textbox for Maven library
MAVEN REPOSITORY DIRECTORY:
Files as a result of Maven build and install command:`mvn clean install`
Click this to deploy application (cxf-res-6.2.1.redhat-084.jar)
OSGi Bundle ListOSGi > Bundles - Click Table View button
New installed bundle
Bundle Detail Information and ActionsOSGi > Bundles - Click “JBoss Fuse Quickstart: rest”
Action Button: Stop, Start, Refresh,
Update, Delete
Bundle Information● Maven Repo location● Some info from Maven POM file● Start level: order number when
Fuse starting
OSGi ServiceAdditional info
CFX REST Service Example
● http://localhost:8181/cxf/crm?_wadl● http://localhost:8181/cxf/crm/customerservice?_wadl&_type=xml
CFX REST Service Example
OSGi FeaturesOSGi > Features Select package
to see available
features that not installed
YET
CXF’s JAX-RSAdditional Topics
CXF: Attaching a WADL document<jaxrs:server address="/rest" docLocation="wadl/bookStore.wadl"> <jaxrs:serviceBeans> <bean class="org.bar.generated.BookStore"/> </jaxrs:serviceBeans></jaxrs:server>
CXF: Schema validationTo enable schema validation on incoming messages:
<jaxrs:server address="/rest" docLocation="wadl/bookStore.wadl"> <jaxrs:serviceBeans> <bean class="org.bar.generated.BookStore"/> </jaxrs:serviceBeans> <jaxrs:schemaLocations> <jaxrs:schemaLocation>classpath:/schemas/person.xsd</jaxrs:schemaLocation> <jaxrs:schemaLocation>classpath:/xsd/</jaxrs:schemaLocation> </jaxrs:schemaLocations></jaxrs:server>
CXF: Specifying the data bindingTo enable schema validation on incoming messages
<jaxrs:server id="jaxbbook" address="/jaxb"> <jaxrs:serviceBeans> <ref bean="serviceBean" /> </jaxrs:serviceBeans> <jaxrs:dataBinding> <bean class="org.apache.cxf.jaxb.JAXBDataBinding"/> </jaxrs:dataBinding></jaxrs:server>
<jaxrs:dataBinding> <bean class="org.apache.cxf.aegis.databinding.AegisDatabinding"> <property name="aegisContext"> <bean class="org.apache.cxf.aegis.AegisContext"> <property name="writeXsiTypes" value="true"/> </bean> </property> </bean> </jaxrs:dataBinding>
CXF: Extension mappingsto map the .xml or .json suffix automatically
OR
<jaxrs:server id="customerService" address="/"> <jaxrs:serviceBeans> <bean class="org.apache.cxf.jaxrs.systests.CustomerService" /> </jaxrs:serviceBeans> <jaxrs:extensionMappings> <entry key="json" value="application/json"/> <entry key="xml" value="application/xml"/> </jaxrs:extensionMappings></jaxrs:server>
GET /resource.xml HTTP/1.1
GET /resource.json HTTP/1.1
CXF: RESTful services without annotationsWe can defining REST services with XML (Model schema)
<jaxrs:server id="customerService" address="/customers" modelRef="classpath:/org/example/schemas/customer-resources.xml" />
https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_Fuse/6.2.1/html/Apache_CXF_Development_Guide/JAXRSEndpointConfig-Model.html
<model xmlns="http://cxf.apache.org/jaxrs"> <resource name="org.apache.cxf.systest.jaxrs.BookStoreNoAnnotations" path="bookstore" produces="application/json" consumes="application/json"> <operation name="getBook" verb="GET" path="/books/{id}" produces="application/xml"> <param name="id" type="PATH"/> </operation> <operation name="getBookChapter" path="/books/{id}/chapter"> <param name="id" type="PATH"/> </operation> <operation name="updateBook" verb="PUT"> <param name="book" type="REQUEST_BODY"/> </operation> </resource> <resource name="org.apache.cxf.systest.jaxrs.ChapterNoAnnotations"> <operation name="getItself" verb="GET"/> <operation name="updateChapter" verb="PUT" consumes="application/xml"> <param name="content" type="REQUEST_BODY"/> </operation> </resource></model>
CXF: Swagger
<jaxrs:server id="xx" address="/address" /> <jaxrs:features> <bean class="io.fabric8.cxf.endpoint.SwaggerFeature">
<property name="title" value="Fabric8:CXF:Quickstarts - Customer Service" /><property name="description" value="Sample REST-based Customer Service" /><property name="version" value="${project.version}" />
</bean> </jaxrs:features></jaxrs:server>
CXF: Swagger http://localhost/cxf/crm/api-docs
Testing REST
REST Sample Testingcurl -X POST -T src/test/resources/add_customer.xml -H "Content-Type: application/xml" http://localhost:8181/cxf/crm/customerservice/customers
curl http://localhost:8181/cxf/crm/customerservice/customers/123
curl -X PUT -T src/test/resources/update_customer.xml -H "Content-Type: application/xml" http://localhost:8181/cxf/crm/customerservice/customers
curl -v -H "Accept: application/json" http://localhost:8181/cxf/crm/customerservice/customers/123
curl http://localhost:8181/cxf/crm/customerservice/customers/123?_type=json
Thank You :-) .