Friday, January 09, 2009

JAX-RS: A proposal for resource URI identification and resolution

In my latest two posts I talked about the problem of clearly defining and resolving the URI of a REST resource in JAX-RS, and then described a possible solution.

I discussed this topic in the Resteasy dev mailing list (here is the thread), and Solomon Duskis suggested to identify resources with a unique logical name rather than with a class name, in order to support multiple REST resources in the same JAX-RS resource, and have less syntax burden.

Building on that suggestion, I've enhanced my proposal and I have to say I'm very happy with it now: as always, feedback is very welcome.

Resource URI identification.

The URI identifying a particular resource is defined by the ResourceUriFor annotation which must be applied to the JAX-RS resource method annotated with the path expression of the URI.
Here it is:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface ResourceUriFor {

public String resource();

public String[] subResources() default {};

public Class locator() default Void.class;
}

The resource argument is the only mandatory one: it defines the logical name of the resource, wich must be unique among all resources.
The subResources argument, optional, defines the logical names of all sub-resources eventually returned by the identified resource, which in this case would act as a locator.
The locator argument, optional, defines the class of the eventual resource locator for the identified resource, which in this case would actually be a sub-resource.

Resource URI resolution.

Resolving a resource URI identified by the above defined annotation is a simple method call:


public interface ResourceResolver {

public URI resolveResourceUriFor(
Class resourceClass,
String resourceName,
String uriBase,
Object... uriParameters);

}


The resourceClass parameter is the class of the JAX-RS resource containing the ResourceUriFor annotation.
The resourceName is the logical name of the resource whose URI has to be resolved.
The uriBase is the base path.
The uriParameters are the objects to use for eventually filling the URI template values.

Resource URI resolution algorithm.

1) Start from resourceClass.
2) Lookup a method annotated with a ResourceUriFor annotation whose logical name is resourceName.
3a) If the ResourceUriFor annotation has no locator, we already have all the elements for resolving the URI.
3b) If the ResourceUriFor annotation has a locator class, go to 4.
4) Go to locator class.
5) Lookup a method annotated with a ResourceUriFor annotation whose subResources contains resourceName of the resource in 2, and go back to 3a.

No comments: