A reasonably undocumented feature of Play is the ease in which Web Services can be integrated into your application. This quick blog will show you how easy it is to create a Play Web Application to do a currency conversion calculation, using Live currency rates between some popular currencies.If you have not already done so, download the latest version of Play from http://www.playframework.org.
Open your command prompt at the directory where you have unzipped and type.
play new currency
Follow the on-screen prompts to set up your new application.
Next start the server by typing
play run currency
Now, open the file currency/app/views/Application/index.html.
In this page we want to have two drop down lists with common currencies to select, and a value field. Change the code so that it looks like the following.
#{extends 'main.html' /} #{set title:'Home' /} <h1>Play! Currency Converter</h1> <form action="@{Application.convert()}" method="POST"> Currency From: <select name="from"> <option value="USD">USD - US Dollar</option> <option value="GBP">GBP - UK Pound Sterling</option> <option value="EUR">EUR - Euro</option> </select><br /> Currency To: <select name="to"> <option value="USD">USD - US Dollar</option> <option value="GBP">GBP - UK Pound Sterling</option> <option value="EUR">EUR - Euro</option> </select><br /> Amount: <input type="text" name="amount" /> <br /> <input type="submit" name="conv" value="Convert" /> </form>
This code is fairly straightforward HTML. The only Play feature in the code is the form action which points to a Play action (which we will create next), using the @{Application.convert()}
code.
Next, we need to open the app/controllers/Application.java.
We need to add the convert action to send our form data to. The file should look like this.
package controllers; import play.mvc.*; import play.libs.*; import org.w3c.dom.Document; public class Application extends Controller { public static void convert(String from, String to, Float amount) { String wsReq = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">" + "<soap12:Body><ConversionRate xmlns=\"http://www.webserviceX.NET/\">" + "<FromCurrency>"+from+"</FromCurrency>" + "<ToCurrency>"+to+"</ToCurrency>"+ "</ConversionRate></soap12:Body></soap12:Envelope>"; Document doc = WS.url("http://www.webservicex.net/CurrencyConvertor.asmx").setHeader("Content-Type", "application/soap+xml").body(wsReq).post().getXml(); String rate = doc.getElementsByTagName("ConversionRateResult").item(0).getTextContent(); Float total = amount * Float.parseFloat(rate); render(from, to, amount, rate, total); } public static void index() { render(); } }
The main piece of code we are concerned about is the convert method. This method is called when the form is submitted (courtesy of the @{Application.convert()}
code in the index.html page).
The method takes 3 parameters, which Play automatically maps from the HTTP parameters sent by the form, so we have the values present immediately when the method is created.
The first thing we do in the method (Play calls these methods actions, so we will do the same from now on), is to create the XML for the soap request. The XML is a reasonably simple SOAP request containing the envelope and body, and the currency symbols we want to convert from and to.
Next, is the WebService part of Play. To use web services in Play, we need to use the play.libs.WS class. Let’s take a closer look at the Web Service call.
Document doc = WS.url("http://www.webservicex.net/CurrencyConvertor.asmx").setHeader("Content-Type", "application/soap+xml").body(wsReq).post().getXml();
The first part of the request specifies the URL that we want to connect to. Here I am using a free sample webservice for live currencies. The second part adds a header to the request. For the request to work, the request needs to specify that the content is soap-xml, which is why the header needs to be added. The third part sets the body of the request to the SOAP xml we created at the start of the action, and the final part sends the SOAP request using the post method.
The final part (getXml()
) returns the response as a Document object, ready for parsing.
The rest of the convert action simply gets the result from the returned XML, and calculates the total amount converted from the amount to convert multiplied by the exchange rate returned from the web service. All of the values (including the ones submitted by the form) are then passed through to the HTML page, so that they can be rendered, by calling the render method.
Finally, we need to output the results of the conversion. So let’s create a new file called app/views/Application/convert.html, and add the following code.
#{extends 'main.html' /} #{set title:'Converted' /} <h1>Total ${to} ${total}</h1> Converted ${amount} ${from} to ${to} at an exchange rate of ${rate}
We can now try out our application. Go to http://localhost:9000
and you will see a page like this.
If we choose USD and GBP and set an amount, then click convert, we should see the results similar to the following.
To achieve this result, our code called an external web service to look up the Live exchange rate between these two currencies, and then used the results in our controller to perform the necessary calculations to display the results on the screen.
How cool is that! A currency conversion application, using real LIVE currency rates, written in less than 50 lines of code.
Nice! I had no idea that the WS class existed. Up until now I was using the apache HTTPClient classes which are much more complex than WS.
Thanks for the tip!
The WS class does actually use the HTTPClient class behind the scenes. There are a few little gems like this hidden in Play. I will try to write more when time allows!
It looks like WS actually uses ning.com’s library, which in turn is built on top of netty:
http://github.com/ning/async-http-client
http://www.jboss.org/netty
The 1.0 branch of Play (the current stable release) uses apache.commons.httpclient.
If you are using a 1.1 branch, the core server has changed to use Netty, and the implementation of WS has changed to use ning as you have described.
Isn’t “Apache Axis” easier to use ?
I think it really depends on the use-case. But using WS, comes out of the box with Play, so no need to add any extra libraries.
Play! does not natively support SOAP WS but it is easy to set up JSON/REST API.
great article! I guess a rest sample would be quite similar, using the url instead of the body to pass data…
Indeed.
You can use
– WS.url(“http://yoururl”).get();
– WS.url(“http://yoururl”).put();
etc etc
As far as I know PLay can render xml too.
Is there a way to set up a groovy-like play template for the xmlrequest? Like this:
…
${from}
${to}
…
and then render the xml request out of it?
It would be much more nice!
Yes, play can render XML using groovy, but as part of the MVC pattern, so therefore as the View of an action request.
As the webservice is being used server side, and a the result of the webservice being displayed in the browser using a standard HTML view, this is not that easy.
It is not impossible, because you can access the groovy engine, but it is not a neat solution.
…and how can I access the groovy engine? And process a file/string with it?
In exactly the same way as you would for an HTML file.
As far as I know Play can render xml too.
Is there a way to set up a groovy-like Play template for the xmlrequest? Like this:
…
<FromCurrency>${from}</FromCurrency>
<ToCurrency>${to}</ToCurrency>
…
and then render the xml request out of it?
It would be much more nice!
…and how exactly can render a template into a String?
From a controller I can call render() / renderHtml()/ renderJson(), but I don’t know what is the target of the rendering.
My netbeansified project does not provide the actual source code of play classes, just method skeletons like this:
protected static void renderHtml(Object html) {
//compiled code
throw new RuntimeException(“Compiled Code”);
}
This way I cannot check the source code.
So you mean:
Template template = TemplateLoader.load(template(templateName));
String content = template.render(args);
…where the templateName is the name of the file, and args is a map is the contains all the bindings I want to use in this rendering.
Can you make a blog post with the other way around?
That is creating the Web Service in Play! for others to consume, or should one use another framework for that?
Play is exceptionally good at creating webservices for others to consume due to it’s RESTful nature. It is actually one of the chapters in my book.
However, a simple explanation would be to create a controller action, that is set up in the routes file to be of format XML, and using the normal play View to output XML. The only difference is, rather than calling your Groovy template actionMethodName.html, you would call your file actionMethodName.xml.
[…] https://playframework.wordpress.com/2010/08/15/web-services-using-play/ Bookmark on Delicious Digg this post Recommend on Facebook share via Reddit Share with Stumblers Tweet about it Subscribe to the comments on this post 未分类 ← Why be such a monster? My Tju….. pro git → /* */ […]
OK with play 1.2.1, but with play 1.2.3 I get reponse 400 : “Invalid header”.
It should be setHeader(“Content-Type”, “application/soap+xml”) with uppercase letter for c and t then it works with play 1.2.3 as well.
You constructed quite a few superb ideas inside your post, “Web Services using Play!
Wayne’s Play Framework Blog”. I will possibly be heading back to your page soon enough. Thx ,Temeka
This excellent blog post, “Web Services using Play!
Wayne’s Play Framework Blog” illustrates that you actually understand precisely what you are writing about! I personally completely agree with your blog. Many thanks ,Ezekiel
This particular posting, “Web Services using Play!
Wayne’s Play Framework Blog” ended up being superb. I am producing out a backup to demonstrate to my close friends. Thanks,Sheila
[…] https://playframework.wordpress.com/2010/08/15/web-services-using-play/ […]