Nowadays, all web applications have to connect with external services. Delegating difficult or complex computations to them or interacting on a social network are just some examples among thousands. Indeed, this means that our application can focus on what it is built for and it will ask other applications for specific needs.
This leads to the SOA architecture, which is more prone to the separation of concerns among services that have a clean and simple definition. A web service is one such dedicated service but is available online. In this chapter, we will discuss how to integrate a Play! Framework 2 application with such an architecture involving web services.
This kind of distributed architecture can lead to some problems because it relies on remote services, which most of the time don't have guaranteed SLAs. So they might block the server until a response is given or a timeout has occurred; meanwhile, other users who could have sent requests to the server will be queued.
For such cases, Play! Framework 2 comes with non-blocking helpers that will ease the work with long or potentially long tasks. This is mainly based on the underlying Akka system. To demonstrate this, we will cover the following points:
In this section, we'll see how we can access remote services through HTTP using the Web Service API (WS API) that Play! Framework 2 has defined for our use.
A web service can have several meanings, such as access to certain resources or functionalities, but it can also have completely different architectures and data representations, where the popular ones are JSON and XML.
So, integration with such third parties through a simple and common API requires quite a lot of abstraction. Hopefully, Play! Framework 2 has prepared the field with an API sharing concepts used in controllers' actions, such as body parsers, for instance. So it won't take that much effort to understand how we can use it.
Actually, all that we'll need is a single endpoint for Java and another one for Scala:
play.libs.WS
class declares plenty of static methods dealing with web servicesplay.api.libs.ws.WS
object, which contains the same functions as in Java, but with a Scala flavorIndeed, these classes define all of the methods we'll need to interact efficiently with our HTTP services.
WS
defines two important classes: WSRequestHolder
and Response
. WSRequestHolder
enables multiple request creation and execution of all kinds (GET, POST, streams, files, and so on). Response
is obviously the opposite, that is, it holds the result of our request after processing including the status, data, and so on.
But in fact, we'll never create any of them because Play! Framework 2 also abstracts their usage through the function url
in WS
. This function is able to create WSRequestHolder
using the String
argument we must pass in, which is the base URL. The following screenshot shows the skeleton of the WS
class:
Ok, now what does WSRequestHolder
stand for? In simple terms, it provides the abstraction over the creation of HTTP requests.
So, with such an instance of WSRequestHolder
, we can prepare the query by setting some parameters using setQueryParameter
, and give it some authentication information using setAuth
(and so on for other preparation methods).
Having prepared the query, the resulting instance can be sent using methods such as get
, put
, post
, delete
, head
, or option
. The methods put
and post
are overloaded several times because they can be assigned with a body content; that's the purpose of methods such as put(InputStream body)
or post(String body)
.
That was for the request part; let's see what's reserved for us by Play! Framework 2 on the response side. But, before moving to this part, we should take a look at the return type of the send methods (get
, put
, post
, and so on):
In the previous screenshot, which presents one of the put
methods available to send a body to a web service using the HTTP PUT
method, we can see the Promise<Response>
result type.
Promise is a structure that is nowadays more and more popular across languages because of its worth in the Web world. For instance, jQuery.Deferred
is one good example a Promise
object because of its heavy usage in the jQuery framework. In a way, it represents an AJAX call.
The main purpose of Promise
is to create a task that will be processed at some time, asynchronously, that is, in a non-blocking way. Actually, it is built upon another concept called Future
, which is the real asynchronous piece as its name intuitively implies. So, the put
method is promising the invoker that a Response
instance will be available. Hence, Play! is able to react in such a way that it will suspend this action once the result has arrived.
We can now get back to our Response
type, which is the generic type of the Promise
object we've just discussed—which declares that a sent request is promised to get some response at some point.
Great! Finally, a response is exactly the same as an action definition; it presents methods that are very similar to the ones we've seen up until now. Indeed, the highlighted methods are shortcuts that enable us to retrieve the response's body (remember, for actions it was the body of the request) that is parsed and represented as well-known and traversable structures such as XML, JSON, and so on.
The amazing hidden feature that is provided in Play! 2 is that the body is handled, parsed, and translated in a completely reactive fashion, thanks to the Iteratee
pattern that is used, similar to what was done for the requests' body.
Now that we've got the overview of the API, we'll look at it in action. For that, we'll choose a third-party service and try to integrate it smoothly into our application.
Let's take Twitter as this third-party service. Twitter exposes an API on top of its social network which enables us to do almost everything that we would like to do with Twitter, such as tweeting a small message, recovering others based on a hashtag, or even searching for new users. Even though most of the functions provided by this service require an authentication, others aren't. As the implementation of such an authentication protocol (such as OAuth 2) is beyond the scope of this book, let's focus on the ones that don't require authentication.
There is an amazing Play! add-on (plugin) that eases integration with external services, especially for social ones. Some information regarding the add-on can be found at http://securesocial.ws.