Aaron Johnson Now with 50% less caffeine!

Posted
8 March 2005 @ 6pm

Tagged
J2EE, SOAP, Software Development, Struts, XML

Using Betwixt, Struts and REST

My latest project at work launched a couple weeks ago, unfortunately there isn’t much to look at, but it’s not like I’m a Flash developer, so unless I start writing Windows apps, no one will ever be able to see my work anyway. Alas, a major portion of the project involved consolidating some business logic behind a SOAP API (I’ll go into that some other time). We were supposed to be moving our front end to ASP.NET but at the last minute, the ASP.NET migration didn’t happen so we ended up needing something that ASP could use as well, which meant REST. With the business logic wrapped up behind business delegates, all that was needed as a Servlet Filter to map requests for /myapp/xml to a Struts Action class, which invoked the business delegates and then returned XML to the client. Now on the SOAP end of things (Axis embedded in Tomcat), I didn’t have to deal with XML (Axis handles all the XML serialization and deserialization). But with REST you’re in conundrum: do you create toXML() methods on all of your JavaBeans? do you put the JavaBean or collection of beans in the Request scope and then generate the XML using JSP? Those options all seemed error prone and harder to test. I looked at JAXB (makes more sense when you have XML that you want to turn into a JavaBean) and Castor (same thing) but finally decided on using Betwixt, a Jakarta Commons library that provide a simple way of turning a JavaBean into XML. The end result looked something like this:

public class RESTAction extends DispatchAction {
  public ActionForward doSomething(...) {
    MyBean bean = BusinessLogic.getBean();
    response.setContentType("text/xml");
    OutputStream sos = response.getOutputStream();
    BeanWriter beanWriter = new BeanWriter(sos);
    BindingConfiguration config = beanWriter.getBindingConfiguration();
    config.setMapIDs(false);
    beanWriter.enablePrettyPrint();
    String declr = "<?xml version='1.0' encoding='UTF-8' ?>";
    beanWriter.writeXmlDeclaration(declr);
    beanWriter.write("mybean", bean);
    beanWriter.flush();
    beanWriter.close();
    return null;
  }
}

which when combined with this action mapping:

<action
  path="/xml"
  type="com.mycompany.web.actions.RESTAction"
  name="xmlForm"
  scope="request"
  parameter="method"
  validate="false">
  <forward name="error" path="/WEB-INF/views/xml/error.jsp" />
</action>

is invoked like so:

http://myserver/myapp/xml?method=doSomething

I’m not 100% sold on this as the “way”, but I do like how simple Betwixt is. If you’ve got a different idea, comment away.


6 Comments

Posted by
Roger Benningfield
12 March 2005 @ 8am

Aaron: I’m no RESTian, but what you’ve described above isn’t actually a RESTful implementation.

For example, your example implies that you can GET the provided URI and, well, “doSomething”. In RESTland, GET should *never* do anything ‘cept return a message. It should have zero effect on the state of any server-bound data.

If I’ve misunderstood, or inferred too much from the example, my apologies in advance.


Posted by
Cristiane
19 August 2005 @ 10am

Hi, have you experience with betwixt? I’m trying to convert an XML to an array of beans. Do you know how to do that?

Tks


Posted by
AJ
7 October 2005 @ 10pm

hi Cristiane,

Betwixt is used to map beans to XML, not the other way around.

AJ


Posted by
Amarish
14 November 2006 @ 3pm

Hi Cristiane,

You might want to look at XStream:

xstream.codehaus.org

Amarish


Posted by
vj
17 October 2007 @ 6pm

Hi Amarish,

hoz xstream with hibernate?

-Vj


Posted by
marginlee
6 June 2008 @ 1am

thanks, quite clear!


Leave a Comment

Fun with HTTP User Agents Donald Knuth on NPR