users@jersey.java.net

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

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 24 Feb 2009 11:53:51 +0100

Hi,

The first part of the fix is in place.

I have modified WadlResource to depend on the injection of
WadlApplicationContext (see end of email):

     public WadlResource(@Context WadlApplicationContext wadlContext) {
         this.wadlContext = wadlContext;
         this.application = wadlContext.getApplication();
     }

Thus it is now very easy to write your own WADL resource by injecting
WadlApplicationContext and then connecting that resource to implicit
views. For example:


  @Path("api")
  @ImplicitProduces("text/html;qs=5")
  @Produces({"application/vnd.sun.wadl+xml", "application/xml",
"application/json"})
  public class MyWadlResource {
      @Context private WadlApplicationContext wadlContext;

      ...
  }

Next steps:

1) investigate the move of WadlResource and creation of further
classes into the API so that they can be
      extended. My initial thoughts on this is i want to be
conservative in terms of implicit views, implicit produces
      and produces media types. i.e. the developer should override or
replace as appropriate.
      Currently the patch for WadlResourceResource and
WadlPartialResource are really specific to implicit
      views because there are not actual resource methods present.
James, do you have any opinions on this?

2) Use a JAXB context resolver for returning a JAXB context for the
JAXB WADL Application and other types.
      If writing your own WADL resource you can of course add your own
context resolver.

Paul.



/**
  * A context to obtain WADL-based information.
  *
  * @author Paul.Sandoz
  */
public interface WadlApplicationContext {
     /**
      * Get a WADL builder initiated with the configured {_at_link
WadlGenerator}
      * for the Web application.
      *
      * @return the WADL builder.
      */
     WadlBuilder getWadlBuilder();

     /**
      * Get a new instance of a JAXB WADL {_at_link Application}
corresponding to all
      * the root resource classes.
      *
      * @return the application, the contents may be modified.
      */
     Application getApplication();

     /**
      * Get a new instance of a JAXB WADL {_at_link Application}
corresponding to all
      * the root resource classes, and configure the base URI.
      *
      * @param ui the URI information from which the base URI is set
on the
      * WADL application.
      * @return the application, the contents may be modified.
      */
     Application getApplication(UriInfo ui);

     /**
      * Get the default JAXB context associated with the {_at_link
WadlGenerator}
      * for the Web application.
      *
      * @return the default JAXB context.
      */
     JAXBContext getJAXBContext();

     /**
      * Get the default JAXB context path to create a {_at_link
JAXBContext}.
      *
      * @return the default JAXB context.
      */
     String getJAXBContextPath();
}

On Feb 20, 2009, at 3:38 PM, James Strachan wrote:

> 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/
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>