Академический Документы
Профессиональный Документы
Культура Документы
CONTACT US
API Management Integration Identity & Access Management Analytics Cloud Platform Architecture
Contents
REST Support in WSO2 Middleware
Reviewing Orders
Making Payments
Content Negotiation
CONTACT US
API Security
Caching
GUI Clients
Sample Artifacts
Disclaimer
package com.wso2.samples;
import java.util.Random;
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 2/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
GET /services/MathService/add?a=5&b=10
<p:add xmlns:p="http://samples.wso2.com">
<p:a>5</p:a>
<p:b>10</p:b>
</p:add>
One may also leverage the support for web applications provided by
WSO2 AS to deploy JAX-RS based pure REST applications. A JAX-RS
application developed using a framework such as Apache Wink or CXF
can be easily deployed on WSO2 AS. Starting from the next major
release of WSO2 AS, it will have first class support for JAX-RS. This
will make developing, packaging and deploying JAX-RS based RESTful
applications in WSO2 AS even easier.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 3/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
resource can only be used to receive and process REST calls whereas
CONTACT US
a proxy service can receive all types of requests. Also a resource
cannot publish a WSDL nor other WS-* modules (security, reliable
messaging etc) can be engaged on a resource.
GET /test/foo/bar
GET /test/foo/a?arg1=hello
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 4/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Here we have two REST APIs anchored at contexts “/foo” and “/bar”
CONTACT US
respectively. Each API is made of two resources. A GET request to the
path “/foo/test” will be received by the first API since it's anchored at
context “/foo”. Then it will be handed to resource A which is configured
to process GET requests with the URL pattern “/test/*”. Similarly a
POST request to the path “/foo/test” will be received by resource B in
the same API. PUT requests to the path “/bar/test” will be dispatched to
resource C in the second API and DELETE requests to the path
“/bar/abc” will be processed by resource D.
/order/{orderId}
/dictionary/{char}/{word}
All the identifiers within curly braces are considered variables. A URL
that matches the template “/order/{orderId}” is given below.
/order/A0001
In the above URL instance, the variable orderId has been assigned the
value “A0001”. Similarly following URL adheres to the template
“/dictionary/{char}/{word}”.
/dictionary/c/cat
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 5/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
In this case the variable “char” has the value “c” and the variable “word”
CONTACT US
is given the value “cat”. When a resource is associated with a URI
template, all requests that match the template will be processed by the
resource. At the same time ESB will provide access to the exact values
of the template variables through message context properties. For an
example assume a resource configured with the URI template
“/dictionary/{char}/{word}”. If the request “/dictionary/c/cat” is sent to the
ESB, it will be dispatched to the above resource and we will be able to
retrieve the exact values of the two variables using the get-property
XPath extension of WSO2 ESB:
<log level="custom">
<property name="Character" expression="get-
property('uri.var.char')"/>
<property name="Word" expression="get-
property('uri.var.word')"/>
</log>
An API definition is identified by the <api> tag. Each API must specify a
unique name and a unique URL context. One or more tags can be
enclosed within an API definition. Some example API definitions are
given below.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 6/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Note the last resource definition in API_3 which does not specify a URL
CONTACT US
mapping nor a URI template. This is called the default resource of the
API. Each API can have at most one default resource. Any request
received by the API but does not match any of the enclosed resource
definitions will be dispatched to the default resource of the API. In case
of API_3, a DELETE request on the URL “/payments” will be dispatched
to the default resource as none of the other resources in API_3 are
configured to handle DELETE requests.
Customer application
Barista application
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 7/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
orders and check payment status of individual orders. With that in mind
CONTACT US
we can come up with a high-level solution architecture for the
Starbucks coffee house scenario as follows.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 8/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
<Ports>
<Offset>1</Offset>
...
</Ports>
This will increment all the ports used by the ESB by 1. Without this
change both ESB and AS will try to listen on the same ports and will
run into bind exceptions. Once the above change is done in the ESB,
start both AS and ESB by executing the wso2server startup script in the
bin directory of each installation.
It will take a few seconds for the service to get deployed properly. You
can track the progress of the process by tracing the AS server log.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 9/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Once the service has been properly deployed, click on the “Web
Services > List” option. You will see that a new service named
“StarbucksOutletService” has been deployed on the server.
You can use a traditional SOAP client like SOAP UI to interact with this
service. Alternatively you can use the “Try-It” option provided by AS to
invoke the service and try it out.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 10/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
<inSequence>
<property name="STARBUCKS_HOST_NAME"
expression="$axis2:SERVICE_PREFIX" />
<payloadFactory>
<format>
<m0:addOrder>
<m0:drinkName>$1</m0:drinkName>
<m0:additions>$2</m0:additions>
</m0:addOrder>
</format>
<args>
<arg expression="//sb:drink" />
<arg expression="//sb:additions" />
</args>
</payloadFactory>
<send>
<endpoint key="DataServiceEndpoint" />
</send>
</inSequence>
<outSequence>
<property name="HTTP_SC" value="201" scope="axis2" />
<property name="uri.var.orderId"
expression="//m1:orderId"/>
<sequence key="StarbucksOrderInfo" />
<send />
</outSequence>
The request sent by the client (customer application) and the response
sent by the ESB are as follows.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 11/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Let's walk through the API configuration and try to understand how it
works. The first thing to note is the following property mediator instance
used in the in-sequence.
<property name="STARBUCKS_HOST_NAME"
expression="$axis2:SERVICE_PREFIX" />
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 12/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Note the format=”soap12” attribute. This tells the ESB that all
messages sent to the OMS endpoint should be in SOAP 1.2 format.
Therefore the ESB will wrap the XML payload in a SOAP 1.2 envelope
before sending it to the back-end service.
If everything works out fine, ESB will receive the following SOAP
response from AS. Note how the OMS has generated a unique ID for
the newly created order. This SOAP message will be mediated through
the out-sequence of the appropriate API resource. In our out-sequence
we have the following property mediator instance as the first entry.
The above property mediator changes the HTTP status code of the
response. According to proper RESTful design principles we should
send a 201 Created response for this scenario. But what we get from
the Starbucks OMS is a 200 OK response (typical SOAP endpoint
behavior). The above configuration will change that to 201 Created so
the client receives the correct response.
<property name="Location"
expression="concat($ctx:STARBUCKS_HOST_NAME,
'order/', //m1:orderId)"
scope="transport" />
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 13/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Reviewing Orders
Once an order has been placed in the system, the customer should be
able to review it. This is done by sending a HTTP GET request to the
URL specified in the 201 Created responses. In our API configuration
we have defined a separate resource to process these GET requests.
Note how we have used a URI template to specify the incoming request
URL format. The order ID part of the URL has been specified as a
variable (orderId) because each order will have its own unique
identifier. In the in-sequence we construct a getOrder SOAP payload
using the payload factory mediator. There we utilize the value of the
orderId variable.
<payloadFactory>
<format>
<m0:getOrder>
<m0:orderId>$1</m0:orderId>
</m0:getOrder>
</format>
<args>
<arg expression="$ctx:uri.var.orderId" />
</args>
</payloadFactory>
curl -v http://localhost:8281/order/my-order-id
curl -v http://localhost:8281/order/bogus-order-id
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 14/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
In this case the Starbucks OMS will return an empty payload to the
CONTACT US
ESB. The out-sequence of the corresponding ESB resource has been
configured to detect this condition and respond with a HTTP 404 Not
Found response. Therefore if you try the above Curl command, you will
get an output similar to the following.
Making Payments
We are going to skip ahead a couple of steps and see how payments
can be handled in our solution. In Webber’s article, payments are
treated as a separate type of resources. Therefore making a payment is
equivalent to creating a new payment resource. Once a payment
resource has been created, the user and the barista should be able to
read the payment resources too.
To try this out add the following XML payload to a file named
payment.xml.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 15/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Once a payment has been made, the customer can review the payment
details by making a GET request. Find the unique ID of the payment
resource and execute the following Curl command (replace order-id
with the actual ID of the payment resource you want to review).
curl -v http://localhost:8281/payment/order/order-id
HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8
Server: WSO2 Carbon Server
Date: Wed, 15 Aug 2012 13:17:39 GMT
Transfer-Encoding: chunked
Connection: Keep-Alive
The Starbucks barista can use the above feature to check whether an
order has been paid for before the drink is released to the customer. If
the payment hasn’t been made for a particular order, the API will return
a 404 Not Found response.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 16/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
A simple switch case can further filter out the OPTIONS requests within
the resource.
<switch source="$ctx:REST_METHOD">
<case regex="OPTIONS">
<property name="NO_ENTITY_BODY" value="true"
scope="axis2" type="BOOLEAN" />
<filter source="//m1:locked" regex="false">
<then>
<property name="Allow"
value="GET,PUT" scope="transport" />
</then>
<else>
<property name="Allow"
value="GET" scope="transport" />
</else>
</filter>
</case>
...
</switch>
The resource can then consult the Starbucks OMS to check whether
the order is modifiable or not. Depending on the response from the
OMS, a suitable HTTP response can be formulated in the ESB.
HTTP/1.1 200 OK
Allow: GET,PUT
Server: WSO2 Carbon Server
Date: Wed, 15 Aug 2012 13:22:36 GMT
Content-Length: 0
Connection: Keep-Alive
Actual order updates are carried out by making a HTTP PUT call. The
payload of the request should contain an updated description of the
order. We have configured our API resource in the ESB to handle PUT
requests as follows.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 17/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Try this out by putting the following XML payload to a file named
update.xml and executing the given Curl command (replace order-id
with the actual order ID).
If all goes well, you will receive a 200 OK response confirming the
update operation.
HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8
Location: http://127.0.0.1:8281/order/764cc8b5-e612-47e1-818b-
225cb35b0c3f
Server: WSO2 Carbon Server
Date: Wed, 15 Aug 2012 13:24:48 GMT
Transfer-Encoding: chunked
Connection: Keep-Alive
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 18/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
The resource will simply contact the back-end OMS service to retrieve
the list of pending orders in SOAP format. Then in the out-sequence we
apply an XSLT transformation to convert the SOAP response into a
valid Atom feed.
<xslt key="OrderFeedGenerator">
<property name="SystemDate" expression='get-
property("SYSTEM_DATE", "yyyy-MM-dd'T'hh:mm:ss'Z'")'/>
<property name="SystemURL"
expression="$ctx:STARBUCKS_SYSTEM_URL"/>
</xslt>
Now to try this API out send a GET request from Curl as follows.
curl -v http://localhost:8281/orders
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 19/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Before the barista can deliver a drink, he should check whether the
customer has paid for the drink. Our StarbucksPaymentAPI already
supports this. If the barista knows a particular order ID, he can check
the payment status of the order by sending a HTTP GET request to the
corresponding payment resource.
curl -v http://localhost:8281/payment/order/order-id
To try this action out, execute the following Curl command. Replace
order-id with an actual order ID string.
HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8
Server: WSO2 Carbon Server
Date: Wed, 15 Aug 2012 13:38:20 GMT
Transfer-Encoding: chunked
Connection: Keep-Alive
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 20/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
To ensure that the order has been removed from the list, send a GET
CONTACT US
request to StarbucksOrderListAPI and check the returned Atom feed.
Content Negotiation
Real world client applications usually have their own preferred content
types. For an example a web browser would usually prefer HTML. A
Java based desktop application is likely to prefer POX. A mobile
application would usually prefer JSON. In order to maintain
interoperability, the server side applications should be prepared to
serve content using any of these formats. Using content negotiation the
client can indicate its content type preferences to the server, and the
server can serve the requests using a content type preferred by the
client.
Let’s see how we can add some basic content negotiation support to
our solution. In this example we are not going to pay attention to any
priority values sent by the client. Rather we are going to have our own
priority order for handling multiple preferences. We’ll use the
StarbucksOrderListAPI as our guinea pig. First of all we need to
retrieve the value of the Accept header sent by the client. We do this in
the in-sequence as follows.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 21/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
2. HTML
3. JSON
4. POX
To try this out, invoke the following Curl commands and see how the
response format changes according to the value of the Accept header.
curl -v http://localhost:8281/orders
curl -v -H "Accept: application/xml"
http://localhost:8281/orders
curl -v -H "Accept: application/json"
http://localhost:8281/orders
curl -v -H "Accept: text/html" http://localhost:8281/orders
Also try accessing the same API from several Web browsers. Most web
browsers send the Accept: text/html header with the requests.
Therefore if you try to access the above URL from a browser like
FireFox or Chrome, you will get a nicely formatted HTML page in
return. Internet Explorer however doesn’t seem to send the Accept
header. As a result IE will render the page using its built-in Atom feed
reader.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 22/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
CONTACT US
API Security
The message will not even get dispatched to the resource. It will be
forwarded to the main sequence of the ESB which is configured to
return a 403 Forbidden response.
The only way you can now access the StarbucksPaymentAPI is via
HTTPS. Invoke the following Curl command to try this out. You should
get the usual 201 response.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 23/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Now that we have some transport level security implemented for our
payment API, let’s see how we can add some authentication logic into
the solution. REST APIs in WSO2 ESB support a concept known as
handlers. One or more handlers can be engaged on a given API where
they can intercept the message flows and add various QoS functionality
into the APIs. For the purpose of this article, we are going to use a
custom handler that provides HTTP basic authentication functionality.
Shutdown the ESB server if it’s already running. Download the WSO2-
REST-BasicAuth-Handler-1.0-SNAPSHOT.jar and copy it into the
repository/components/lib directory of the ESB installation. Now add
the following handler definition to the StarbucksPaymentAPI.
<handlers>
<handler class="org.wso2.rest.BasicAuthHandler"/>
</handlers>
You must pass in the basic auth credentials (user: admin, password:
admin) for the API to be accessible.
You can try this out using a web browser as well. Note how the browser
will display the standard authentication dialog when you try to access it
without passing in the credentials.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 24/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
CONTACT US
Since we have the basic auth handler engaged on our payment API, all
the requests to the API are first processed through the handler. This
handler checks whether the required basic auth headers are present on
the message. If not it returns a 401 response and terminates the flow.
You can find the source code of this custom handler here.
The above custom handler is not a very sophisticated one. You can see
in the source code that the user credentials are actually hard coded into
it. In a real world situation, the security handlers should contact some
kind of a database or an identity provider to authenticate and authorize
users. For WSO2 API Manager product, we have developed such an
advanced API handler. That implementation secures APIs using OAuth
and works in conjunction with the WSO2 Identity Server components.
The API handler concept can be used to implement various other QoS
features too. Important non-functional requirements such as throttling,
monitoring and usage tracking can be implemented as separate
handlers and engaged on your APIs.
Caching
The response time of some of the API calls can be significantly
improved by introducing some caching features into our solution.
Webber’s article suggests that the list of pending orders should be
cached so that the Atom feed generation can be performed without
overloading the backend servers. We can implement this in WSO2 ESB
using the cache mediator. The cache mediator stores the responses in
an in-memory cache keyed by the DOM hash of the requests.
Therefore if the same request is sent multiple times, only the first
invocation will be mediated to the backend service. All subsequent calls
will be served from the cache. Following example shows how the cache
mediator can be engaged in one of the ESB sequences.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 25/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
The number of responses to cache and the cache timeout duration are
CONTACT US
configurable.
GUI Clients
Now that the application integration is complete, we can start working
on some UI clients to consume our REST APIs. From a real world
perspective, the UI client could be a website, a standalone desktop
application or even a mobile app.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 26/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
CONTACT US
Feel free to go through the source code of the client application as well.
Most of the code related to actual HTTP invocations are in the
HTTPUtils class.
Note: This particular GUI client expects the payment API to be exposed
over HTTP without any form of authentication. So if you have added
any security features to the payment API, please revert those
modifications before you attempt to run the client application.
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 27/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
Once we got our solution up and running, we started exploring the ways
to further improve it. We discussed several concepts such as content
negotiation, security and caching in detail and how those features can
be incorporated into our WSO2 ESB based solution. Finally we looked
at a sample UI application which can be used to interact with the REST
APIs we have developed.
From this exercise it becomes clear that WSO2 ESB and rest of the
WSO2 platform in general have everything required to build
comprehensive solutions based on REST application architecture.
WSO2 AS can be used to host native REST applications and WSO2
ESB can be used as a centralized router and mediator of REST calls.
Further it can be used as a bridge between RESTful applications and
non-RESTful applications. It provides a convenient and powerful way to
expose existing systems over clean and well-defined RESTful APIs.
Sample Artifacts
Starbucks OMS (web service) -
https://svn.wso2.org/repos/wso2/people/hiranya/rest-
sample/bin/StarbucksOutletService.aar
ESB configuration -
https://svn.wso2.org/repos/wso2/people/hiranya/rest-
sample/bin/synapse-configs.zip
Starbucks UI client -
https://svn.wso2.org/repos/wso2/people/hiranya/rest-
sample/bin/starbucks-rest-sample.jar
Author
Hiranya Jayathilaka, Project Lead, WSO2 Enterprise Service Bus
Disclaimer
Starbucks and the Starbucks logo (used in the UI client) are registered
trademarks of Starbucks
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 28/29
5.03.2020 How to GET a Cup of Coffee the WSO2 Way
©2020 WSO2 Legal Privacy Do Not Sell My Info Cookie Policy Modern Slavery Statement Report a Problem With This Page
https://wso2.com/library/articles/2012/09/get-cup-coffee-wso2-way/ 29/29