Wednesday, July 13, 2011

Auttomatic XML Schema generation for Jersey WADLs

I have been doing a little bit of work recently on Jersey implementation and one of the precursors to this has been to try to get the WADL that Jersey will generation by default to contain just a little bit more information with regards to the data being transferred. This makes it possible to help the user when generating client code and running testing tools against resources.

To this end I have put together a WADL generator decorator that examines all the JAX-B classes used by the -RS application and generates a bunch of XML Schema files. This is now in 1.9-SNAPSHOT which you can download from the Jersey web site in the normal way. (If you want to use the JResponse part of this you will need a build after the 13th of July)

This feature is not enabled by default in 1.9; but hopefully with some good feedback and a small amount of caching I might convince the Jersey bods to make this the default. For the moment you need to create and register a WsdlGeneratorConfig class to get this to work. So your class might look like this:

package examples;

import com.sun.jersey.api.wadl.config.WadlGeneratorConfig;
import com.sun.jersey.api.wadl.config.WadlGeneratorDescription;
import com.sun.jersey.server.wadl.generators.WadlGeneratorJAXBGrammarGenerator;

import java.util.List;

public class SchemaGenConfig extends WadlGeneratorConfig {

    @Override
    public List<WadlGeneratorDescription> configure() {
        return generator( 
                WadlGeneratorJAXBGrammarGenerator.class   ).descriptions();
    }
}

You then need to make this part of the initialization of the Jersey servlet, so your web.xml might looks like this:

<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
  <servlet>
    <servlet-name>jersey</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.WadlGeneratorConfig</param-name>
      <param-value>examples.SchemaGenConfig</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>jersey</servlet-name>
    <url-pattern>/jersey/*</url-pattern>
  </servlet-mapping>
</web-app>

For the purposes of this blog I am just going to show the three basic references to entities that the code supports. So at the moment if will obviously process classes that are directly referenced and either a return value or as the entity parameter on a method. The code also supports the Jersey specific class JResponse, which is a subclass of Response that can have a generic parameter. (Hopefully this oversight will be fixed in JAX-RS 2.0)

package examples;

import com.sun.jersey.api.JReponse;

import examples.types.IndirectReturn;
import examples.types.SimpleParam;
import examples.types.SimpleReturn;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@Path("/root")
public class RootResource {
    
    @GET
    @Produces("application/simple+xml")
    public SimpleReturn get() {
        return new SimpleReturn();
    }
    
    @GET
    @Produces("application/indrect+xml")
    public JResponse<IndirectReturn> getIndirect() {
        return JResponse.ok(new IndirectReturn() )
            .type( "application/indrect+xml" ).build();
    }
    
    @PUT
    @Consumes("application/simple+xml")
    public void put(SimpleParam param) {
        
    }
        
}

The type classes are all pretty trivial so I won't show them here. The only important factor is that they have the @XmlRootElement annotation on them. Although not shown here you can also use the JAX-B annotation @XmlSeeAlso on the resource classes to reference other classes that are not directly or indirectly referenced from the resource files. The most common use case for this is when you have a subtype of a class.

So enough of the java code, lets see what the WADL that is generated looks like:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://wadl.dev.java.net/2009/02">
    <doc xmlns:jersey="http://jersey.java.net/" jersey:generatedBy="Jersey: 1.9-SNAPSHOT 07/13/2011 11:13 AM"/>
    <grammars>
        <include href="application.wadl/xsd0.xsd">
            <doc xml:lang="en" title="Generated"/>
        </include>
    </grammars>
    <resources base="http://localhost:7101/JerseySchemaGen-Examples-context-root/jersey/">
        <resource path="/root">
            <method name="GET" id="get">
                <response>
                    <representation xmlns:ns2="urn:example"
                        mediaType="application/simple+xml" element="ns2:simpleReturn"/>
                </response>
            </method>
            <method name="PUT" id="put">
                <request>
                    <representation xmlns:ns2="urn:example"
                        mediaType="application/simple+xml" element="ns2:simpleParam"/>
                </request>
            </method>
            <method name="GET" id="getIndirect">
                <response>
                    <representation xmlns:ns2="urn:example"
                        mediaType="application/indrect+xml" element="ns2:indirectReturn"/>
                </response>
            </method>
        </resource>
    </resources>
</application>

In this example there is only one schema in the grammar section; but the code supports multiple schemas being generated with references between them. Let look at the schema for this example, note I did say the classes were trivial!

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema version="1.0" targetNamespace="urn:example"
    xmlns:tns="urn:example" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="indirectReturn" type="tns:indirectReturn"/>
    <xs:element name="simpleParam" type="tns:simpleParam"/>
    <xs:element name="simpleReturn" type="tns:simpleReturn"/>
    <xs:complexType name="indirectReturn">
        <xs:sequence/>
    </xs:complexType>
    <xs:complexType name="simpleReturn">
        <xs:sequence/>
    </xs:complexType>
    <xs:complexType name="simpleParam">
        <xs:sequence/>
    </xs:complexType>
</xs:schema>

There is still some internal work to be done on caching; but the basics are in place. Feedback would be appreciated, particularly in cases where the code doesn't see the referenced classes. Finally thanks to Pavel Bucek for being patient as I learned the ropes.

Update 5th September 2011 This feature has been enabled by default so you no longer have to perform any of the WadlGeneration configuration when working with 1.9 final release of Jersey.

Friday, July 8, 2011

Slightly tidier version of super-type tokens without anonymous inner classes

If you have ever used or written a fluent API eventually you have to deal with the fact that in Java generic types are erased. For example in the current Jersey client API you find the following problems:


   // Can't do generic class literals, compile error

   List<Employee> result = resource.get(List<Employee>.class);

   // Code won't function as it doesn't know the generic type

   List<Employee> result = resource.get(List.class);

Most API's solve this using Grafter's Gadget which creates a class where a trivial subclass bakes in the generic type. For example in REST the class in called GenericType:


   // Creates a anonymous instance of GenericType with the generic parameters
   // baked in

   List<Employee> result = resource.get(new GenericType<List<Employee>>() {});

I have never liked this because well it is just a little bit untidy for my liking, creating an inner class for this one time use doesn't feel right. You can of course extract this to a constant; but I was looking for a better way to define a literal. It turns out that with a big of playing about you can write code to do the following:


   private static final GenericType<List<String>> LIST_STRING =
           GenericType.field();

The trick here is to examine the calling stack when creating the GenericType instance to final the class that the field be being attached to. You can then go back and work out generic type of the field is when the constants is used. Here is a rough sketch of the code integrating with the Jersey GenericType:



public class GenericType<T> {

    public static final <U> GenericType<U> field()
    {
       return new FieldGenericType<U>();
    }

    // Rest of GenericType implementation
    // .....
}



class FieldGenericType<T>
      extends GenericType<T> {

    // TODO if we are not allowed to create a security manager just
    // use new Exception().getStackTraceElement() and then get hold
    // of the string name of the class
    static class ModifiedSecurityManager extends SecurityManager {

        public Class[] getClassContext() {
            return super.getClassContext();
        }
    }
    static final ModifiedSecurityManager sm = new ModifiedSecurityManager();


    /**
     * Provide an adapted version of the paramaterized type based on the
     * value of the field.
     */

    static class AdaptedParameterizedType implements ParameterizedType {

            // Find the class that created us, a few steps up the stack
            private Class owningClass = sm.getClassContext()[4];
            // The owning instances, can't be set in the constructor
            private FieldGenericType instance;
            private ParameterizedType type;

            /** Lazily create the type **/
            private ParameterizedType getType() {

                // TODO make thread safe
                //

                if (type == null) {

                    // Look for a field of type GenericType which is the same
                    // references the "instance" of the FieldGenericType
                    //

                    found:
                    for (Field field : owningClass.getDeclaredFields()) {
                        final Class<?> fieldType = field.getType();
                        if (GenericType.class.isAssignableFrom(fieldType))
                        {
                            try {
                                field.setAccessible(true);
                                if (field.get(owningClass) == instance) {
                                    // We need the generic parameter of the GenericType class
                                    //
                                    type = (ParameterizedType)
                                            ((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0];
                                }
                            } catch (IllegalArgumentException ex) {
                                Logger.getLogger(Example.class.getName()).log(Level.SEVERE, null, ex);
                            } catch (IllegalAccessException ex) {
                                Logger.getLogger(Example.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }

                    //

                    throw new Error("Cannot find the related field");
                }

                return type;
            }

            public Type[] getActualTypeArguments() {
                return getType().getActualTypeArguments();
            }

            public Type getRawType() {
                return getType().getRawType();
            }

            public Type getOwnerType() {
                return getType().getOwnerType();
            }

            public String toString() {
                return getType().toString();
            }
        }     


    public FieldGenericType() {
        super(new AdaptedParameterizedType() );

        // Inject the this value, now it has been created
        ((AdaptedParameterizedType)getType()).instance = this;


    }
}

Perhaps not that much tidier for day to day coding; but not using anonymous inner classes just feels like the right thing to do. I guess time will tell if I actually end up using it. I can see it being very useful when trying to generate boilerplate code in an IDE.

Monday, July 4, 2011

Off-loading your test execution using Hudson

One of the annoyances if you have a load of tests for a particular project is that running them can tie up your machine for a while. There are also sometimes consistency issues when running on different machines with different window managers and operating system versions. One thing we do is for every main hudson job we create a copy just to run the tests for a particular developer. It solves the "it runs on my machine" dilemma and frees up the developer to get on with other work. In our part of the organization running the tests on another machine is a mandatory step before merging to main.

This example uses subversion; but it most likely work equally well with any other source control system with a similar interface. It also assumes that all the developers are working on branches, you are doing this right?.

First of all you take a copy of you original job, in my case I am running test for the abbot project so I am starting with "abbot_SF", and create a copy of this job with a suitable postfix. In our case the job is called "abbot_SF_TestTrans". You need to first disable any normal build triggers so this job only gets used when there is a manual action. We keep the results separate as it makes the normal build results much easier to interpret.

So to this new job add a new Parameter "BRANCH" of type string and update the repository URL to contain this parameter, so in my case https://abbot.svn.sourceforge.net/svnroot/abbot/abbot/branches/$BRANCH. You will also notice that I have the used the description setting plugin to capture the branch name automatically. (You could also just put the $BRANCH parameter in the description field and leave the RegEx blank). After you have finished you have something like this, ignore the red ink as that appears to be a local configuration issue.

Now if you click build on the job you get a nice interface where you can ask Hudson to build a particular branch, leaving the developer to get on with the next job while the build machine does it's business.

Speaking of that, it looks like I have some bugs to fix...

P.S. You might also want to tick the "Execute Concurrent Builds if necessary" flag so that if you have more than one developer you can make proper use of your farm.