Go Light with Apache Struts 2 and REST by Don Brown
After attending Dan's talk on REST, I stayed in the same room and listened to Don Brown talk about Struts 2's support for building RESTful applications. Below are my notes from the event.
What is wrong with today's web applications? You're using a modern web framework and you've cleanly separated your presentation and business logic. The biggest problem in modern web applications is Confusing URLs.
A URL should be a resource indicator - not a method invocation. Often, web applications have little or no caching. People use GET to perform data manipulation and POST may or may not change state (especially with JSF). Another big issue with modern web frameworks is there's too many abstraction layers that hide HTTP headers and it's difficult to manipulate them.
Today's applications are "information silos". There's a lot of information in your applications, but it's all buried in HTML, JavaScript and CSS. There's no way to get this information out of your application unless you explicitly expose it.
The answer to many of these problem is REST. It's the Way of the Web. To solve the information silo problem, you can create a single interface that has multiple representation of the same resource. There's one URI for all types of resources - be it XML, JSON or HTML. How does this work w/o modifying the URL? You modify the URL's extension.
Struts 2 has a couple of plugins that make developing RESTful services easier. The first is the Codebehind plugin and the 2nd is the REST plugin. Don is doing a demo with the REST plugin and shows that there's no Struts configuration files needed (no struts.xml and no struts.properties). The only thing that's necessary is to specify an "actionPackages" init-param on the DispatcherFilter in web.xml. This activates the Codebehind plugin that uses conventions to determine the view template's path.
In Don's demo, he's creating an "OrdersController" that implements ModelDriven. After implementing a setId() method (to set the id from the request parameters), a getModel() method (to return the Order object) and implementing a show() method that returns HttpHeaders, Don starts up his server and shows that http://localhost:8080/order/5 returns an HTML page. Changing the URL to end in /5.json returns JSON, /5.xml returns XML.
public HttpHeaders create() { service.save(order); return new DefaultHttpHeaders("success").setLocationId(order.getId()); }
The Poster Plugin for Firefox is great when you're working with REST services. Don used this plugin to show us that it's possible to post to JSON and get back JSON results. His demo was impressive, especially the fact that there was no XML configuration required for Struts. I also like how the DefaultHttpHeaders class allows you to manipulate headers in a type-safe manner.
To use the REST plugin, you'll want to use Struts 2.1. If you're using Maven, all you need to depend on is struts-rest-plugin. The struts-codebehind-plugin (as well as struts-core) will be pulled in by transitive dependencies.
One disadvantage of REST vs. WS-* is you can't generate client code from a WSDL. You'll have to write your client by hand. However, one advantage of REST is there's already lots of clients - your browser, curl, etc.
The Struts REST Plugin hasn't been officially released, but hopefully will be in Struts 2.1.1. You can checkout the code from SVN using the URL below. The documentation is located here.
http://svn.apache.org/repos/asf/struts/struts2/trunk/plugins/rest
Great talk Don - and excellent work on the REST plugin for Struts. I can't wait to try it out.
Posted by Don Brown on November 16, 2007 at 03:51 PM MST #
Thanks for this post. I was looking for similiar concept and yet use struts.
Many times, i thought, i should stick with vanilla jsp app. (basically MVC 1 model :) )
Posted by ashish jain on November 16, 2007 at 04:30 PM MST #
Posted by me on November 16, 2007 at 07:22 PM MST #
Posted by Stefan Tilkov's Random Stuff on November 16, 2007 at 07:38 PM MST #
Posted by Don Brown on November 16, 2007 at 08:03 PM MST #
Posted by Don Brown on November 16, 2007 at 08:06 PM MST #
"Confusing URLs are hardly the 'biggest problem in modern web applications'. "
They are in Java. They indicate badly designed frameworks in the same way doing evrything through managers indicate badly designed middlware.
Frankly, web architecture seems lost on most Java devs, so let me put in terms you might actually understand: make your URLs object-oriented. And prepare to be unpleasantly surprised at how difficult that can be in Javaland.
http://www.dehora.net/journal/2007/07/struts_1_problems.html
read down the section called "Conceptual mismatch with the Web". This mismatch problem extends to the servlets spec itself.
Posted by Bill de hOra on November 16, 2007 at 09:35 PM MST #
Posted by Thiago HP on December 12, 2007 at 04:32 PM MST #
Posted by Nicola on March 18, 2008 at 05:45 PM MDT #
Posted by Mike W on May 18, 2008 at 09:43 PM MDT #
Posted by Matt Raible on May 29, 2008 at 03:22 AM MDT #
Posted by deebak on July 23, 2008 at 12:26 PM MDT #
Posted by keith on December 23, 2008 at 04:33 PM MST #
Hi Don, I included struts rest plugin 2.1.6 and trying to call action from the JSP using Struts tag <s:action name="test-url" executeResult="true" />
But this does not call the action method. How do I call REST actions from my JSP?
Posted by Kumar on April 03, 2009 at 10:37 PM MDT #
Posted by oscar on April 26, 2009 at 01:58 PM MDT #
struts.xml
This configuration means, that when requesting webapp, first it tries to map request to action in old-style, if no one action was found - it tries to map request to action in REST style.
Posted by xzr on May 22, 2009 at 12:05 AM MDT #
Is there any way to replace the DefaultContentTypeHandlerManager with my own ContentTypeHandlerManager?
Currently, the plugin look at the URL or the request to determine the output format (xml,json, etc.). I want to have my own ContentTypeHandlerManager which will look at the passing parameter (ie, http://.../rest/v1/car/1?format=xml ) to determine the output format.
Thank you
Posted by tk on June 03, 2009 at 10:13 PM MDT #
Hi! I am trying to configure my project using REST and Actions annotations, but only when I REST works the same settings.
Example: If I make the settings to use REST, the annotations do not work, if I remove the settings of REST, the annotations back to work.
My Settings struts.xml:
Posted by Rodrigo on May 31, 2011 at 08:22 PM MDT #