Structural linking with Jersey + Moxy – an AspectJ solution

The requirement

In a REST resource representation, structural links can be embedded in the resource to allow the client to navigate to subresources. This is in contrast to so-called transitional links, which represent state transitions.

    <parent id="100">
        <!-- I am a transitional link -->
        <link href="http://myserver/parents/100" rel="delete">  

        <!-- We are child resources with structural links to our full representation -->
        <child id="1" href="http://myserver/children/1"/>       
        <child id="2" href="http://myserver/children/2"/>
    </parent>

The JAX-RS project has a good discussion of the differences, as well as some explanation of why transitional links are so much easier to support than structural links.

I’ve been struggling to find a good way to implement structural links, especially as I want to add a couple more constraints:

  1. The domain model must not be touched. Even when you do have access to the source code, I simply don’t think it’s kosher to pollute a domain model with cross-cutting concerns like serialization to a particular format.
  2. I won’t put up with death-by-boilerplate, such as creating a DTO for each domain model class.

I posted this problem as a Stack Overflow question along with some candidate approaches. This blog post is about the first candidate, the AspectJ solution.

The solution sketch

This solution uses Jersey’s very handy declarative linking capability. You can add a field to a model class and Jersey will populate it for you. Even more impressively, you can simply point Jersey at a method in your REST API and Jersey will derive your link from the @Path annotations on that method. Too easy. Just too bad this violates my #1 constraint, that the model not be touched.

Enter AspectJ. We can use an intertype declaration to add the field, and everything just works.

The downside of this solution is that the structural link configuration is not truly externalized (with respect to the model). Yes, we’ve avoided altering the model source code – which, IMHO, is no small win, as preserving the expressive power of the model source code is a pretty high priority for me. However, at the byte code level, we have most definitely altered the model, at least within this compilation unit. The new fields will be visible to any reflection-driven framework and may pop up in other representations. If we can live with that, this is a pretty clean solution.

Example code

This code is also available on BitBucket.

Model classes

package testing;

import java.util.ArrayList;
import java.util.List;

public class Planet {

    private int id = 1;
    private String name = "test";
    private double radius = 3.0;

    private List<Moon> moons = new ArrayList<Moon>(0);
    
    public void addMoon(Moon moon) {
    	moons.add(moon);
    }
}
package testing;

public class Moon {
	
	private String name;
	
	// No-arg constructor is a requirement of JAXB
	public Moon() {
	}
	
	public Moon(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}

}

Resource class

For the proof-of-concept, we’re just serving an freshly created instance of the model.

package testing;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/services")
@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
public class Services {
	
	private Planet initPlanet() {
		Planet p = new Planet();
		p.addMoon(new Moon("moon1"));
		p.addMoon(new Moon("moon2"));
		return p;
	}

	@GET
	public Planet planet () {
		return initPlanet();
	}
	
	@GET @Path("/moons/{moonid}")
	public Moon moon (@PathParam("moonid") String name) {
		return new Moon(name);
	}
	
}

Jersey configuration

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>test</display-name>
  
  <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
	<init-param>
	    <param-name>javax.ws.rs.Application</param-name>
	    <param-value>testing.MyApplication</param-value>
	</init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
  
</web-app>

Application class

This is the class pointed to by the web.xml, and it really just exists so we can register the declarative linking feature.

package testing;

import org.glassfish.jersey.linking.DeclarativeLinkingFeature;
import org.glassfish.jersey.server.ResourceConfig;

public class MyApplication extends ResourceConfig {
	
    public MyApplication() {
        packages("testing");
        register(DeclarativeLinkingFeature.class);
    }

}

Moxy configuration

Moxy’s ability to configure JAXB mappings entirely from an external file is a cornerstone of my approach to serving up unmodified domain objects.

jaxb.properties

This is how we let Jersey know we want to use Moxy as the JAXB provider.

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

The moxy mapping file, planets.oxm.xml

Note that the href elements mentioned in the mapping file do not exist in the model source code.

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="testing"
    xml-mapping-metadata-complete="true"
    xml-accessor-type="NONE">
    <java-types>
        <java-type name="Planet">
            <xml-root-element/>
            <java-attributes>
	           	<xml-attribute java-attribute="href"/>
                <xml-element java-attribute="name"/>
                <xml-element java-attribute="radius"/>
 				<xml-element java-attribute="moons" name="moon">
 					<xml-element-wrapper name="moons"/>
 				</xml-element> 	
            </java-attributes>
        </java-type>
        <java-type name="Moon">
            <xml-root-element/>
        	<java-attributes>
	           	<xml-attribute java-attribute="href"/>
        		<xml-element java-attribute="name"/>
        	</java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Moxy context resolver

This is how we supply Moxy with the correct mapping file. The @Provider annotation lets Jersey automatically find our context resolver.

package testing;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

@Provider
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class MyMoxyContextResolver implements ContextResolver<JAXBContext> {
    private JAXBContext context = null;
 
    public JAXBContext getContext(Class<?> type) {
	System.out.println("Invoking MyMoxyContextResolver.getContext");
    	if (context == null || context != null) {
	        try {
	        	System.out.println("MyMoxyContextResolver - Creating new JAXBContext");
	            Map<String, Object> properties = new HashMap<String, Object>(1);
	            properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "testing/planets.oxm.xml");
	            context = JAXBContext.newInstance(new Class[] {Planet.class}, properties);
	            
	        } catch(JAXBException e) {
	            throw new RuntimeException(e);
	        }
    	}
       return context;
    }

}

Custom MessageBodyWriter

As per this StackOverflow question, we need to add a custom MessageBodyWriter to convince Jersey to marshall a completely unannotated model. Again, Jersey picks this up automatically.

package testing;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.Providers;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;


@Provider
@Produces("application/xml")
public class MyMessageBodyWriter implements MessageBodyWriter<Object> {

	@Context
	protected Providers providers;

	@Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return true;
    }
 
    @Override
    public long getSize(Object les, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return -1;
    }
 
    @Override
    public void writeTo(Object les, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
        try {
        	ContextResolver<JAXBContext> resolver = providers.getContextResolver(JAXBContext.class, mediaType);
        	JAXBContext context = resolver.getContext(type);
        	
        	Marshaller m = context.createMarshaller();
			m.marshal(les, entityStream);

        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
    
}

The aspect

This is what makes it all work. As this project is laid out all in one package, all you need to do is compile with the AspectJ compiler and this aspect will be woven into the model classes. In a more realistic project, you’d have the model classes on the inpath and this aspect on the aspectpath.

package testing;

import org.glassfish.jersey.linking.InjectLink;
import org.glassfish.jersey.linking.Binding;

public aspect HrefInjector {
	
	private String Planet.href;
	declare @field : * Planet.href : @InjectLink(
										resource=Services.class, 
										style=InjectLink.Style.ABSOLUTE
									) ;

	private String Moon.href;
	declare @field : * Moon.href : @InjectLink(
										resource=Services.class,
										method="moon",
										bindings={@Binding(
												name="moonid", value="${instance.name}"
												)},
										style=InjectLink.Style.ABSOLUTE
									) ;

}

Project layout

Screenshot from 2014-06-27 16:40:30

(click to enlarge)

Dependencies

As they appear in the gradle build file:

dependencies {
   compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.9'
   compile 'org.glassfish.jersey.media:jersey-media-moxy:2.9'
   compile 'org.glassfish.jersey.ext:jersey-declarative-linking:2.9'
   
   providedCompile 'javax.servlet:servlet-api:2.5'
}

As always, you can run

./gradlew dependencies

to see the full list of transitive dependencies.

Sample output

XML

	<planet href="http://localhost:8080/reststructlinks/rest/services">
		<name>test</name>
		<radius>3.0</radius>
		<moons>
			<moon href="http://localhost:8080/reststructlinks/rest/services/moons/moon1">
				<name>moon1</name>
			</moon>
			<moon href="http://localhost:8080/reststructlinks/rest/services/moons/moon2">
				<name>moon2</name>
			</moon>
		</moons>
	</planet>

JSON

{
  "href": "http://localhost:8080/reststructlinks/rest/services",
  "name": "test",
  "radius": 3,
  "moons": {
    "moon": [
      {
        "href": "http://localhost:8080/reststructlinks/rest/services/moons/moon1",
        "name": "moon1"
      },
      {
        "href": "http://localhost:8080/reststructlinks/rest/services/moons/moon2",
        "name": "moon2"
      }
    ]
  }
}

Conclusion

A few concluding comments:

  1. There are only two source files concerned with structural linking – the mapping file, and the aspect. The rest of the system operates exactly as per usual. This satisifies the requirement for structural linking to be separated out as a crosscutting concern.
  2. It’s entirely appropriate that the mapping file is involved, as it means you can control when and where you want the structural links by modifying the mapping file.
  3. The aspect requires no special configuration, as it is using bog-standard built-in Jersey functionality.
  4. Jersey’s built-in UriBuilder approach to transitional linking co-exists happily with this aspect-driven approach.
  5. Of course, some people/projects are allergic to AspectJ for whatever reason, so it would still be good to see another candidate solution emerge.

Hope this helps!

Unconfuse yourself about REST, HATEOAS, and API design

I set out to create a simple REST API about a week ago. Having got a basic proof of concept working, I thought I’d look up the accepted wisdom on API design. Well! After a couple of days hacking through the seething jungle of opinion, holy wars and plain misinformation, I now realize it might be a little too soon for “accepted”. However, there were three things I found after much labour that really helped clarify my thinking, so I thought I’d call those out here.

Roy Fielding’s semi-rant on the hypermedia constraint

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

This article opened my eyes to the larger issues that REST was originally designed to address. It also is a handy test – if, like me, you find that much of the terminology in this article is unfamiliar, that’s a good sign that you haven’t really engaged with the work that’s been done on those issues. Knowing what you don’t know is always a good thing.

There’s a lot of nonsense not particularly useful stuff out there in the blogosphere about API discoverability, with the proponents struggling to come up with a really convincing benefit, and the opponents holding up the chimera of completely automated discoverability by a completely generic automaton as a kind of reductio ad absurdum. Fielding makes it clear that, while the automaton might be nice if you can afford to build it, a discoverable API is just as important for that most ubiquitous of generic user agents, the next generation of application programmers.

“REST is software design on the scale of decades: every detail is intended to promote software longevity and independent evolution.” – Roy Fielding, comment #8

What’s a media type and how do you create one?

Two things become clear in the comment stream from the above article (and other sources):

  1. Fielding sees “out-of-band” information (that is, the stuff that the parties in a client-server interaction have to know that is not contained within the interaction itself) as a threat to API longevity
  2. More importantly, and apparently not widely understood, Fielding doesn’t see the media type definition as being out-of-band. In fact it’s the media type definition that saves you from needing out-of-band information.

So what’s a media type and how do you create one? This is apparently widely misunderstood (including by me), and it’s surprisingly hard to find a simple answer.

In fact, there is a very simple answer. A media type is an information standard. You create one by writing it down. You can share it globally by registering it with IANA. The MIME types with which we are all familiar are simply pointers to this registry. Or, you can share it locally by just telling your mates where the standards document is. Here’s an incredibly simple example.

http://www.iana.org/assignments/media-types/media-types.xhtml
http://www.iana.org/assignments/media-types/application/activemessage

Again, the waters are muddied by people leaping immediately to the most difficult case, that of automatic discovery by generic automatons. If your “user agents” are developers, all you need in your media type documentation is human-readable text.

How to design a mashup

You can’t, of course. That’s the point of a mashup. You just “expose” some information and the genius of the crowd will then mash it together with other things in ways that you couldn’t possibly imagine, right? Hands-up everyone who thought that designing REST APIs is about exposing information (I have both hands up at this point). Unfortunately, this is utter nonsense, and even more unfortunately it doesn’t take much thinking to see that it’s nonsense. Who really believes that Google didn’t know people would be embedding maps with pins on them?

Fortunately, the talented guys at Jayway wrote a very nice article called Why hypermedia APIs? which reminded me that designing API’s is very closely related to designing applications (remember what the “A” and the “P” in API stand for?).

http://www.jayway.com/2012/10/06/why-hypermedia-apis/

Designing applications starting with use cases is something I know how to do. Of course it’s blindingly obvious that API’s must also be designed with use cases in mind, but I had allowed myself to be almost terminally distracted by the mashup rhetoric along with with an abundance of bad examples.

Conclusion

Those were my three biggest pain points, which I’ll just restate here for easy access:

  1. What on earth is this HATEOAS stuff all about and what does it mean for my design?
  2. What’s a media type (really)
  3. How do I design something that will be used in “limitless and unimaginable ways”?

The resources I’ve pointed to in this post were invaluable in unconfusing me, so I hope they’ll help you too.

Using Moxy with Jersey for XML Part 3

See part 1 for my initial confused ramblings, and part 2 for a workaround. This third and final part will hopefully bring some clarity to both the initial problem and the solution.

Firstly, a brief statement of how I went astray:

The use case

The requirement is to create a REST API for manipulating an existing domain model. While I do have access to the domain model source code, I’m reluctant to alter it for this specific scenario, so anything requiring annotating the domain model is out. Similarly, while it’s possible to create an intermediate model (e.g. a set of DTO’s) and annotate that, that approach has always seemed to me like excessive double handling. To my mind, XML is supposed to be the dumb DTO format. I know there are use cases which require all these layers, but I also know that most of the time YAGNI.

The solution sketch

  1. JAX-RS seems to be a nicely concise, annotation-driven way to create REST services on a servlet container
  2. Jersey is a JAX-RS implementation with some traction, and some useful integrations with various containers and format providers
  3. By using JAXB with Jersey, we remove the need to write the XML marshalling/unmarshalling layer
  4. JAXB by default is completely annotation-driven, but Moxy is a JAXB implementation that can be configured via an external mapping document. Happily, Jersey ships with Moxy integration.
  5. Finally, Moxy gives us JSON capability for free.

So that was the plan. Implement that stack of frameworks, create a mapping file, and serve up both XML and JSON based on the one unannotated domain model. There are lots of examples around to help get started:

plus many more linked from the above. There’s no example I could find that reproduces all the elements of my solution sketch – Jersey + JAXB + Moxy + external mapping file + unannotated file – but surely there’s enough to get started.

What the documentation doesn’t tell you

Spot the flaw in my thinking:

  1. Jersey integrates with Moxy out of the box – TRUE
  2. Moxy supports the use of an external mapping file – TRUE
  3. When you use Moxy with the external mapping, you don’t need any annotations on the model – TRUE
  4. The Jersey docs even show you how to configure Moxy with a mapping file – TRUE
  5. Therefore, you can use Jersey + Moxy without annotations on the model – FALSE

Stumbled at the last hurdle. To add to the bafflement, this all works flawlessly for JSON marshalling, but fails for XML. I’ll go into more detail below as to why this is so, but for now, here’s what you need to know:

Jersey’s Moxy integration does not expose all of Moxy’s functionality for the XML case. There is still some of the standard annotation-driven JAXB code in the mix, and to get past that your model must be annotated at least with @XmlRootElement

Once you’ve satisified Jersey’s default JAXB provider by adding that one annotation, Jersey will happily hand you over to Moxy and all the external mapping goodness works just fine.

Is there a better way?

But wait, I started off by saying I didn’t want to annotate my model. If you really don’t want to or can’t annotate the model, there is another way. You need to register your own provider. This example gives the basic idea, although I needed to tweak it a bit to get it to work (more on that below). This is in fact what Jersey’s Moxy code does for the JSON case, which is why that works and the XML case doesn’t.

Example code

Most of this example code is identical to all the other examples out there, but I’ll collect it here as the full description of what finally worked for me. This is using Jersey 2.9 and EclipseLink Moxy 2.5 on Java 7. This code can also be found on bitbucket.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>test</display-name>
  
  <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>testing</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
  
</web-app>

JAX-RS service definition

Without the custom provider described further down, this code works for the JSON case (/json) and the two endpoints that use the annotated model (/json2 and /xml2), but fails for the unannotated XML case (/xml).

package testing;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/services")
public class Services {

	@GET @Path("/json")
	@Produces(MediaType.APPLICATION_JSON)
	public Planets serviceListJSON () {
		return new Planets();
	}
	
	@GET @Path("/xml")
	@Produces(MediaType.APPLICATION_XML)
	public Planets  serviceListXML () {
		return new Planets();
	}
	
	@GET @Path("/json2")
	@Produces(MediaType.APPLICATION_JSON)
	public PlanetsAnnotated serviceListJSON2 () {
		return new PlanetsAnnotated();
	}
	
	@GET @Path("/xml2")
	@Produces(MediaType.APPLICATION_XML)
	public PlanetsAnnotated  serviceListXML2 () {
		return new PlanetsAnnotated();
	}
	
}

Model classes

package testing;

public class Planets {

    private int id = 1;
    private String name = "test";
    private double radius = 3.0;


}
package testing;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class PlanetsAnnotated {

    private int id = 1;
    private String name = "test";
    private double radius = 3.0;


}

Mapping file

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="testing"
    xml-mapping-metadata-complete="true"
    xml-accessor-type="NONE">
    <java-types>
        <java-type name="Planets">
            <xml-root-element/>
            <java-attributes>
                <xml-element java-attribute="id"/>
                <xml-element java-attribute="name"/>
                <xml-element java-attribute="radius"/>
            </java-attributes>
        </java-type>
         <java-type name="PlanetsAnnotated">
            <xml-root-element/>
            <java-attributes>
                <xml-element java-attribute="id"/>
                <xml-element java-attribute="name"/>
                <xml-element java-attribute="radius"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

jaxb.properties

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Context resolver

This is one of several ways to give Moxy the mapping file.

package testing;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;

import org.eclipse.persistence.jaxb.JAXBContextProperties;

@Provider
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class MyMoxyContextResolver implements ContextResolver<JAXBContext> {
    private JAXBContext context = null;
 
    public JAXBContext getContext(Class<?> type) {
	System.out.println("Invoking MyMoxyContextResolver.getContext");
    	if (context == null) {
	        try {
	            Map<String, Object> properties = new HashMap<String, Object>(1);
	            properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "testing/planets.oxm.xml");
	            context = JAXBContext.newInstance(new Class[] {Planets.class}, properties);
	        } catch(JAXBException e) {
	            throw new RuntimeException(e);
	        }
    	}
       return context;
    }

}

Custom provider

This is the part that makes the XML case finally work without annotations. For a full solution this would implement MessageBodyReader as well.

package testing;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.Providers;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;

@Provider
@Produces("application/xml")
public class MyMessageBodyWriter implements MessageBodyWriter<Object> {

	@Context
	protected Providers providers;

	@Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return true;
    }
 
    @Override
    public long getSize(Object les, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return -1;
    }
 
    @Override
    public void writeTo(Object les, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
        try {
        	ContextResolver<JAXBContext> resolver = providers.getContextResolver(JAXBContext.class, mediaType);
        	JAXBContext context = resolver.getContext(type);
        	
            context.createMarshaller().marshal(les, entityStream);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
    
}

Source code layout

This is my example structure for a gradle project.

src/
   main/
      java/
           jaxb.properties
           MyMessageBodyWriter.java
           MyMoxyContextResolver.java
           Planets.java
           planets.oxm.xml
           PlanetsAnnotated.java
           Services.java
   webapp/
      WEB-INF/
           web.xml 

Help!

This is a super-simple proof-of-concept. No doubt it has all sorts of sub-optimal choices, and for all I know breaks all sorts of other use cases while solving mine. However, as far as I can tell there is no other example out there for this specific scenario. It would be great if this could be evolved into something more robust, so please let me know if you have any suggestions.

The gory details

This is a sketch of what’s happening in the innards of Jersey when using JAXB to marshal the results of a service call. I’m including this as background to any future discussion on what a supported solution might look like. For example, maybe MoxyXmlFeature should register a provider that relaxes the requirement for @XmlRootAnnotation.

Jersey

At startup time:

  • Jersey registers built-in providers
  • Features (discovered on the classpath) register providers and context resolvers
  • The jaxb.properties file defines the JAXBContextFactory to be used

At request processing time:

  • The annotated JAX-RS service method returns a Java object
  • Jersey’s interceptor fires (triggered by the @Produces annotation)
  • Jersey searches its list of providers based on the class of the returned Java object and on the media type required
  • The chosen provider searches for a context resolver that is configured to provide a context for the Java class
  • The chosen context resolver obtains and configures a JAXBContext and returns it to the provider
  • The JAXBContext returns a marshaller
  • The provider invokes the marshaller, which emits the marshalled representation of the Java object

Each provider has a list of rules defining what it will handle. For example, there’s a built-in XmlRootElementProvider, which will only handle classes annotated with @XmlRootElement for media type application/xml. If no matching provider can be found, an exception is thrown.

So, on to Moxy. The jersey-media-moxy module, which ships with Jersey and provides Moxy integration, registers two features – MoxyJsonFeature and MoxyXmlFeature.

MoxyJsonFeature registers a provider, ConfigurableMoxyJsonProvider, which will handle marshalling any object where the media type is application/json. You can then use either the MoxyJsonConfig method or register your own ContextResolver to configure a mapping file if so desired.

MoxyXmlFeature, on the other hand, does not register a provider. For annotated models, one of Jersey’s built-in providers will work just fine, but for non-annotated models that means that no provider will be found and an exception will be thrown. MoxyXmlFeature does register a context resolver, thus providing a mechanism for configuring a mapping file, but without any annotations to get you past the Jersey provider that context resolver will never be invoked. Hence the need to create our own provider.

Using Moxy with Jersey for XML Part 2

In part 1 I described the ways in which the documented approach doesn’t work. This post is about my first workaround, but for a comprehensive debrief, see part 3.

The approach that works is:

  1. Build with the jersey-media-moxy module – so
  2. Put the jaxb.properties file in the right place – so
  3. Create a mapping file – so
  4. Create a ContextResolver – example. This will be used for JSON but not for XML.
  5. Create a MessageBodyWriter – example. This will be used for XML.
  6. Most importantly, write and let me know where on earth I went wrong to need to jump through all these hoops :)
  7. Check out this little demo project to see how it all fits together.

Using Moxy with Jersey for XML

This post is about my initial attempts to get Jersey and Moxy working the way I want. See part 3 for the full analysis of why I was having trouble and my eventual solution.

Jersey is an implementation of JAX-RS, the Java standard for REST web services. To this you can add JAXB, which allows your REST services to use declarative metadata to map domain objects to a wire format, typically either JSON or XML.

The downside of the JAXB reference implementation is that the metadata is expressed as annotations on the domain model. Personally, I think that this kind of mapping is definitely a cross-cutting concern and is to be kept out of the domain model source code at all costs. Moxy comes to the rescue! You can plug Moxy in as your JAXB provider, replacing the reference implementation entirely, and Moxy supports externalizing the mapping metadata to an XML file. So, how to get it working?

The Jersey documentation is very simple and to the point. To use Moxy for JSON binding, just place the appropriate jar on the classpath – see instructions. You can then use a custom JAXB context resolver to set Moxy up with a mapping file, and away you go.

The documentation for using Moxy for XML binding is even simpler. The simplest way is:

… use the standard JAXB mechanisms to define the JAXBContextFactory from which a JAXBContext instance would be obtained (for more on this topic, read JavaDoc on JAXBContext)…

That boils down to putting a jaxb.properties file alongside your model, as documented here.

The alternative mechanism is to manually configure Jersey, registering and configuring the MoxyXmlFeature.

However, neither mechanism actually works. It appears that, while Jerseys Moxy JSON feature registers a MessageBodyWriter to handle JSON writes, the XML feature does not do anything of the sort, instead falling back onto Jersey’s default XML MessageBodyWriter. Unfortunately, the default XML writer appears to completely ignore any registered ContextResolvers you’ve registered. Thus, while you can marshall a completely unannotated domain object to JSON, if you try to marshall the same object to XML you’ll get an exception.

See https://bitbucket.org/jmetcher/resttest for a small project showing Jersey setup strictly according to the documentation. Check out the master branch for the basic setup.

The solution is to register your own custom MessageBodyWriter, as described here. Sadly, as far as I can tell this is 100% missing from the documentation. Check out the MBW branch of the above project to see what it looks like with the recommended MessageBodyWriter approach. Unfortunately, this doesn’t work either. It appears that, contrary to about a dozen examples dotted around the web, injection of the ContextResolver does not work, as you’ll see by the NPE if you run that code.

Finally, have a look at the MBW_Better branch of the project. As this one actually works, I’ll pull it out into a separate post.

Simple way to marshall POJOs using JAXB

JAXB is a specification for marshalling and unmarshalling java objects to and from XML. The normal way (i.e. most commonly documented) to use it is to annotate your Java object. The annotations give you a lot of control, but even if you’re happy with the default settings, you still need to at least provide the @XMLRootElement annotation to make your class visible to JAXB, like so:

package jaxbtest;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class ServiceDTO {
	public MyDomainClass mdc;
	
    public ServiceDTO() {}
    
    public ServiceDTO(MyDomainClass mdc) {
    	this.mdc = mdc;
    }
}

OK, this isn’t a real DTO. The next step would be to copy all the required data from the domain class into fields of the DTO. But it will serve our purpose for the moment.

To marshal ServiceDTO to XML, we can then do this:

    	MyDomainClass mdc = new MyDomainClass();

    	JAXBContext jc = JAXBContext.newInstance(ServiceDTO.class);
    	Marshaller marshaller = jc.createMarshaller();
    	marshaller.marshal(new ServiceDTO(mdc), System.out);

What if you can’t or don’t want to add JAXB annotations to your domain? See this very helpful post by the very helpful Blaise Doughan. You can still get fine-grained control over marshalling and unmarshalling by using Moxy to external JAXB configuration.

There is another way, though. In the java doc for JAXBContext, we find this intriguing statement:

Not only the new context will recognize all the classes specified, but it will also recognize any classes that are directly/indirectly referenced statically from the specified classes

That means that, given the above code, we can also marshal the domain object directly, like this:

marshaller.marshal(mdc, System.out);

As long as your class is referenced by an annotated class, it’s fair game for the marshaller.

I haven’t seen this technique mentioned at all in my research, so I presume there are some fundamental limitations to it. If you know of any, please let me know in the comments.

Eclipse WTP + Gradle

This post is a collection of handy guides for setting up Eclipse and Gradle for servlet development.

Why do this? Eclipse is a nice development environment, and Eclipse WTP with its servlet container integration provides a slick code/compile/deploy/debug cycle. But Eclipse is not a build system. In particular, if you want transitive dependency management, you’ll need something like Gradle or Maven. The downside is that you then have two completely separate configurations to manage. However, both Gradle and Maven supply utilities to assist in keeping the two in sync.

So, the guides:

http://www.vogella.com/tutorials/EclipseWTP/article.html
This is a great guide for setting up and testing an Eclipse WTP environment with embedded Tomcat

You may then run into this bug in Eclipse:
http://stackoverflow.com/questions/14791843/eclipse-add-tomcat-7-blank-server-name

and, on Ubuntu, this bug:
http://stackoverflow.com/questions/13423593/eclipse-4-2-juno-cannot-create-a-server-using-the-selected-type-in-tomcat-7

Gradle uses a different default project layout to the default Eclipse dynamic web project layout. Both are configurable, but the path of least resistance is to set up your project the Gradle way, like this:
https://weblogs.java.net/blog/manningpubs/archive/2013/03/18/building-java-web-application-gradle

and then import that configuration into eclipse:
http://www.gradle.org/docs/current/userguide/eclipse_plugin.html
and
http://www.gradle.org/docs/current/dsl/org.gradle.plugins.ide.eclipse.model.EclipseWtp.html

At this point, you know enough to create a single project that you can fire up on Tomcat within Eclipse, or Jetty via Gradle. Any container-specific configuration will be a problem, of course, and unfortunately the Jetty Eclipse adapter is no longer maintained. There is a Tomcat plugin for Gradle, but I haven’t yet tried it.

One way to destroy trust in professional learning

Hayes Mizell describes 3 ways to build trust in professional learning. This is all good stuff, but there’s at least one essential prerequisite for any of this to work: you do have to actually trust the professionals (in this case, teachers). And there’s nothing that says “We don’t trust you” like a professional learning requirement that is externally imposed, mandatory, and micro-managed.

To pick just one of the three ways: number 2 reads “[Leaders should] Organize professional learning that teachers experience as appropriate and helpful”. Let’s pick that apart:

  1. In a mature, self-regulated profession, there is no distinction between leaders and the rest. Rather, the profession as a whole is seen to be leading society. There are leading members of the profession, but they are rarely to be found organizing PL.
  2. It’s a subtle point, but training is “organized for” workers who are passive recipients. PL might be “offered to” professionals, but just as often they will define for themselves what constitutes PL.
  3. In a mature, empowered profession, no professional endures PL that is not appropriate and helpful – not for very long, anyway. Try to waste even five minutes of a senior surgeon’s time, and you’ll find yourself looking at a receding surgeon’s back. It’s a measure of a profession that is desperately disenfranchised that it’s even possible to waste days of teachers’ time on poor PL.

Perhaps we as a society don’t actually trust teachers? OK- then we must strictly regulate training requirements, remove self-agency, and concern ourselves with how we are using their time. But in that case we must also stop calling teaching a profession, and we must absolve teachers of responsibility for school outcomes. Personally, I hope it doesn’t come to that.

Note 1: I’m using Mizell’s post as an example of how the language around teacher PL reflects widespread contradictory attitudes towards professionalism in teaching. I’m not suggesting that Mizell himself is inconsistent or otherwise opposed to teacher empowerment.

Note 2: Mizell is writing in the North American context, but my direct observations of the teaching profession are all Australian.

Vagrant and Ansible on Windows hosts

Vagrant runs nicely on Windows. Ansible does not. It can, at a pinch, with Cygwin etc – but that setup doesn’t work with the Vagrant Ansible provisioner.

There is a solution: use Vagrant’s shell provisioner to fire up Ansible on the guest, something like this. It adds a bit of overhead having to install another copy of Ansible on every guest, but this approach does work unchanged on both Linux and Windows hosts. We can still keep the config scripts centralized on the host, and access them via VirtualBox shared folders. Or can we?

TL;DR:

  • All the VirtualBox shared folders options have issues when the host is Windows and the guest is Linux.
  • The safest workaround is to copy your whole config scripts directory to a local directory on the guest, and run Ansible entirely on guest.

If you do keep your config scripts on the host, you’ll eventually run into the dreaded “atomic move” issue. That is, Unix file systems support an atomic move operation, and Windows file systems do not. See the archetypal gedit vs virtualbox pass-the-bug fest for a typical manifestation.

When using vboxfs synced folders, host file system semantics remain in place. That means even though you’re running Ansible on the Linux guest, your Windows host is still going to get you. You can provoke this just by using the Ansible template module, even when only the source file is on the host filesystem. To be defensive, you’d have to assume any command or program on the Linux side could have problems with vboxfs folders until proven otherwise. Oracle appears to be in no hurry to fix this or even admit that it needs fixing. Do you really want to spend your life tripping over all of the problem cases?

Ok, no problem, vagrant also supports rsync and smb for synced folders. Rsync would have to work, because the files end up on the guest where Windows can’t get at us anymore, and SMB must be easy because it’s Windows’ native protocol, right? Actually, not so simple.

Rsync requires an rsync.exe on the path of the host. You can get that by installing Cygwin. That might be acceptable for your own dev machine, but if you are using Vagrant to distribute demo environments, expecting all users to turn their machines into a bizarre Unix/Windows hybrid is probably not realistic. And there’s no installer-free Cygwin anymore (or any other Windows rsync port, for that matter), so the rsync route ends up being just too invasive.

SMB must just work out of the box, though, right? Unless you’re on Windows 8, wrong. Vagrant’s smb support needs Powershell 3.0. Powershell 3.0 needs .Net 4.0. On Windows 7 that’s two more installers, and even then it won’t work unless your version of Vagrant is very recent.

So what’s the solution? Obviously, get a Mac or a dedicated Linux dev box. But what about those of us working at home on a personal project, with only one machine that has to be a Windows machine because all our users run Windows and because dogfooding, and because running Windows as a guest isn’t great for anything graphics intensive? In that case – get *everything* over onto the guest as quickly and simply as possible, and then stay entirely on the guest. Vboxfs works fine for simple copying, or if your config is in a public repo maybe just pull it down straight onto the guest.

Gradle, AspectJ and non-transitive project dependencies

To set up a multi-project build such that the output of one project is on the inPath of another, do this in the build file of the dependant project:

  1.  
  2. apply plugin: ‘aspectj’
  3.  
  4. dependencies {
  5.         ajInpath project(path: ‘:weavemeplease’, transitive: false)
  6. }
  7.  

‘weavemeplease’ is the name of the project to be woven. We want this dependency to be non-transitive so we don’t end up weaving all of the upstream dependencies as well.

Gradle 1.11 and AspectJ 1.7

See the Gradle docs for more about multi-project builds, and the gradle-aspectj plugin for how to build with AspectJ.

The other hot tip regarding the gradle-aspectj plugin is this: apply the java plugin first, then configure the java stuff, *then* apply the aspect plugin. Finally, you can add aspect-specific configuration. The aspectj plugin works by copying state from the java configuration, so it helps if the java configuration actually exists. I really don’t know what controls execution order in Gradle, but evidently it does fall back to source code order in at least some circumstances.

PS: I’m posting this because this has taken me three hours of slightly wrong examples and completely cryptic error messages to work out. Groovy experts can laugh, but I know zero Groovy and have just started with Gradle. I’m beginning to suspect that the above syntax is a literal Map argument to the project() method of the DependencyHandler object – but given I don’t actually know what Groovy map syntax looks like, I’m not sure, and I have no idea what the meaningful keys and values in that map might be.

Do you need to know Groovy to use Gradle? I’m beginning to think it would help a lot. But even with no Groovy, it’s a lot better than maven’s eyeball-melting XML files.