users@jersey.java.net

Re: [Jersey] [PATCH] to allow the API of RESTful services to be rendered using hierarchial Implicit Views

From: James Strachan <james.strachan_at_gmail.com>
Date: Fri, 20 Feb 2009 14:38:36 +0000

2009/2/20 Paul Sandoz <Paul.Sandoz_at_sun.com>:
>
> On Feb 19, 2009, at 4:42 PM, James Strachan wrote:
>
>> 2009/2/19 Paul Sandoz <Paul.Sandoz_at_sun.com>:
>>>
>>> Hi James,
>>>
>>> This looks really interesting! thanks for doing this.
>>
>> No worries - it was fun! I was surprised how easy it was to reuse the
>> WadlResource in an implicit view with really minor changes to Jersey!
>>
>
> Index:
> jersey-server/src/main/java/com/sun/jersey/server/impl/uri/rules/SubLocatorRule.java
> ===================================================================
> ---
> jersey-server/src/main/java/com/sun/jersey/server/impl/uri/rules/SubLocatorRule.java
> (revision 2021)
> +++
> jersey-server/src/main/java/com/sun/jersey/server/impl/uri/rules/SubLocatorRule.java
> Thu Feb 19 14:03:33 GMT 2009
> @@ -47,6 +47,8 @@
> import com.sun.jersey.spi.inject.Injectable;
> import com.sun.jersey.spi.uri.rules.UriRule;
> import com.sun.jersey.spi.uri.rules.UriRuleContext;
> +import com.sun.jersey.spi.uri.rules.UriRules;
> +
> import java.lang.reflect.InvocationTargetException;
> import java.lang.reflect.Method;
> import java.util.Iterator;
> @@ -95,7 +97,14 @@
> context.pushResource(resource);
>
> // Match sub-rules on the returned resource class
> - final Iterator<UriRule> matches =
> context.getRules(resource.getClass()).
> + if (resource == null) {
> + return false;
> + }
> + UriRules<UriRule> rules = context.getRules(resource.getClass());
> + if (rules == null) {
> + return false;
> + }
> + final Iterator<UriRule> matches = rules.
> match(path, context);
> while(matches.hasNext())
> if(matches.next().accept(path, resource, context))
>
> Was there something going wrong that forced the above changes. I am trying
> to work out if there is a deeper problem here.
>
> I think one problem is that a sub-resource locator can return a null value,
> which was not checked before.
>
> IIRC if "resource" is not null there will always be a non-null "rules"
> returned. Did you have a case where this was null?

Sorry forgot that was still there. I had some NPE's and wasn't exactly
sure the reason - I think it was the resource being null, not the
rules being null. I think it was when I was trying a URI that didn't
correctly map to a resource bean; but would rather see 404's returned
than NPE's and a stack dump :).


> Do you think there might be value in letting the developer plugin in the
> required WadlResource, extending from a base class? this might make it
> easier to allow developers to evolve the code as they require e.g a property
> for a class, or instance, that extends WadlResource.
>
> Or... to support it using it in a conventional way e.g.
>
> @Path("/api")
> public CamelWadlResource extends WadlResource {
> ...
> }
>
> and have things injected correctly on WadlResource. The runtime could check
> in any resource class implements WadlResource and if none do it can supply a
> default (if JAXB is present in the classpath).

Ah thats a neat idea! The most likely place for new methods would
probably be on the WadlResourceResource to be honest when rendering a
specific resource's documentation; but am sure others might think of
other things they want to add when rendering the documentation for
their API (e.g. querying some database/wiki/CMS for extra content to
render?).

One thing I was gonna add to this patch was a helper method that
returns a kinda multi-map of method REST verbs as keys then for each
verb, the various methods. e.g. for GET find the N representations
(methods) of GET rather than just navigating a flat list. As when
rendering you might just want the list of all the GET methods for
example.

Though other than that I can't think of too many other methods I might
want to add to the resource classes - but am sure others might think
of something. Its kinda easy to wrap up any custom view functions
inside a custom tag these days - e.g. here's the <api:resource> tag
I'm using...
https://svn.apache.org/repos/asf/camel/trunk/components/camel-web/src/main/webapp/WEB-INF/tags/api/resource.tag

and to show the doc of a resource/method
https://svn.apache.org/repos/asf/camel/trunk/components/camel-web/src/main/webapp/WEB-INF/tags/api/doc.tag

But it is kinda nice keeping helper methods on the resources and
sharing the common code in Jersey


> Or do you think the modifications on the WADL-based resources will be
> sufficient that no further modification would be required?

I think it would offer more flexibility and control; provided we
expose an overloadable factory method in WadlResource to allow custom
WadlResourceResource implementations to be created too.

Also it would let you keep all your implicit view templates in the
same package structure (e.g. org/apache/camel/web/resources/* in my
case) rather than some there and some in com/sun/jersey/whatever...

So yes - I think its a good idea!

-- 
James
-------
http://macstrac.blogspot.com/
Open Source Integration
http://fusesource.com/