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 in Java at Nov 15 2007, 06:12:58 PM MST 18 Comments
Comments:

Thanks for the write up. I made the slides available here.

Posted by Don Brown on November 16, 2007 at 09:51 AM 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 10:30 AM MST #

Confusing URLs are hardly the 'biggest problem in modern web applications'. Users don't usually type URLs by hand (only the 'main' application URL, or just click a link in a portal). SOME 'modern web applications' do have this kind of requirement, but this is not the norm. If beautiful URLs can ease application development (and you have real evidence on that), REST may be the way for world peace. If not, it's just yet another hype.

Posted by me on November 16, 2007 at 01:22 PM MST #

[Trackback] This is very interesting: Matt Raible reports from a talk by Don Brown about Struts2’s REST support (via Mike Herrick)....

Posted by Stefan Tilkov's Random Stuff on November 16, 2007 at 01:38 PM MST #

The way I tried to presented it was that there were three problems of applications today, of which confusing URLs was just one. There were four issues that I highlighted:
  1. Improper use of GET - breaks cache proxies.
  2. URI's should describe resources, not methods to call. This breaks user expectations and usually results in an explosion of URLs, increasing the surface area of your application.
  3. Extra, useless characters in the URL - not a big issue, but makes your app look sloppy, as URLs are bookmarked and sent around via email, IM, etc.
  4. Improper use of query parameters - required identifying information should be in the URI, again affects caching by proxies
The bottom line is at the center of your application are your URLs, so it isn't about easing application development, but your users. More consistent, properly behaved URLs make an application easier to use and open the door for nice features like multiple representation types down the road. Web applications are built on HTTP and it is about time they stop abusing it.

Posted by Don Brown on November 16, 2007 at 02:03 PM MST #

Clarification:
There were four issues that I highlighted:
I meant four issues in confusing URLs. The other two problems in web applications were little or no caching, and being information silos.

Posted by Don Brown on November 16, 2007 at 02: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 03:35 PM MST #

They are in Java. They indicate badly designed frameworks in the same way doing evrything through managers indicate badly designed middlware.
Your blog talks about Struts, but it is *not* the only Java web framework out there. There are dozen of them. If you want a framework that has semantic URLs, take a look at Tapestry 5 sites like http://thedailytube.com/. written

Posted by Thiago HP on December 12, 2007 at 10:32 AM MST #

Hi! Thank for your amazing plugin... I'm starting to use it in my web app, where I have already adopted Struts2, Hibernate3 and Spring2... My problem is the initialization of my service beans, that usually I delegate to Spring (it manages my transactions and so on...). How can I ask to Spring to build my beans? Thank you, Nicola

Posted by Nicola on March 18, 2008 at 11:45 AM MDT #

Any idea when Struts 2.1 is due for GA release?

Posted by Mike W on May 18, 2008 at 03:43 PM MDT #

A 2.1.2 Beta was recently released. I don't know when a GA version will be released. I haven't contributed to the project in quite some time.

Posted by Matt Raible on May 28, 2008 at 09:22 PM MDT #

I tried to use the REST plugin but it did not work. I can't find this filter "StrutsPrepareAndExecuteFilter" in any version of Struts2.

Posted by deebak on July 23, 2008 at 06:26 AM MDT #

i also encountered problems using the spring plugin to manage my beans. Otherwise, all experience showed this is the Greatest Plugin ever.

Posted by keith on December 23, 2008 at 10:33 AM 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 04:37 PM MDT #

I visit this page again and again try to find some discuss on struts2.1.6 + REST plugin. it is a new version, few people have much experiment. 2 month passed, still not much materials found on the internet, my project is fully based on struts2+rest. I encounter lots of problems.canot even find a place to discuss. so,any information is helpful ,from you.

Posted by oscar on April 26, 2009 at 07:58 AM MDT #

For those people, who want to use REST plugin along with Struts 2 default-style actions...

struts.xml
...
	<!-- Enable the composite action mapper. --> 
	<constant name="struts.mapper.class" value="composite"/>
	
	<!-- Provide action mappers for the composite mapper. Order is sensible. --> 
	<constant name="struts.mapper.composite" value="struts,rest"/>

	<package name="default" extends="rest-default">
	...
	</package>
...

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 21, 2009 at 06:05 PM 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 04: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:

<!--  Overwrite Convention -->
<constant name="struts.convention.action.mapAllMatches" value="true"/>
<constant name="struts.convention.default.parent.package" value="rest-default"/>
<constant name="struts.convention.package.locators" value="example"/>
   
<!-- Enable the composite action mapper. --> 
<constant name="struts.mapper.class" value="composite"/>
	
<!-- Provide action mappers for the composite mapper. Order is sensible. --> 
<constant name="struts.mapper.composite" value="rest,struts"/>

Posted by Rodrigo on May 31, 2011 at 02:22 PM MDT #

Post a Comment:
  • HTML Syntax: Allowed