jsr339-experts@jax-rs-spec.java.net

[jsr339-experts] Re: feedback from vraptor's and restfulie server side usage

From: Bill Burke <bburke_at_redhat.com>
Date: Mon, 14 Mar 2011 10:35:14 -0400

On 3/12/11 1:29 PM, Guilherme Silveira wrote:
> 2. Allows custom resource lookup:
> Extract the process of resource lookup and expose it. This allows
> anyone to provide its own UrlToResourceTranslator. The default is
> JAX-RS1 compatible.
> Other simple implementations are the ones where the verb GET is
> assumed by default, where getX means the get verb and so on. Every
> convention (as with the annotation approach)
> is a different implementation. Implementations can be combined through
> composition allowing backward *and* forward compatibility:
>
> public interface UrlToResourceTranslator {
>
> ResourceMethod translate(RequestInfo info)
> throws ResourceNotFoundException, MethodNotAllowedException;
>
> }
>

If I understand this correctly, you want a way to take in a request and
pick the class, instance, and method that you want the HTTP request
dispatched to? I really like this idea. Gives a lot of flexibility to
framework developers too to add in their own goodies and innovations.

How about being able to specify a @Path expression too so that you can
apply it to specific path groups?

i.e.

@Provider
@Path("/foo/{:.*}")
public MyRouter implements UrlToResourceTranslator {...}

On a related note, one thing I wish JAX-RS had was an SPI for plugging
in component models. It kinda sucks that each of us has their own way
of integrating with Spring. Would be much better for all of us if
Spring maintained this integration through one unifying SPI.




> 3. Support to a non-default parameter access convention using Java's
> debug information. This can be non-default so its up to the user to
> decide to use it. I surely prefer to be default:
>

While interesting, this I don't like. With an annotation framework you
should be able to look at a class and know exactly how it is going to
behave without having to refer to a configuration file.


> 4. Also support breaking the view layer from the control layer
>
> If a method does not serialize or return anything, assume a default
> behavior so you don't have to repeat yourself all over the place. For
> example, if the show method did not
> return anything it would go to "/software/show.jsp" or
> /software/show.json.jsp or /software/show.xml.jsp etc according to
> conneg. To implement it, the semantic model needs to be exposed again:
>


Not sure that works because @POST and @PUT methods already have a
default defined for "void" methods (return 200). I do think we need an
easier way to "forward" and "redirect" than what currently exists.
Forwarding and redirecting are features people have asked for.

As a side note, I'm very wary of adding MVC features to JAX-RS. There
are already a plethora of web frameworks out there, I'd much rather
focus on adding features to JAX-RS that make it easier to integrate with
existing frameworks than creating our own competing one.

> 5. URI Building
>
> This is one that bothers me a lot. We should be writing OO code, not
> xml-oriented, not annotation-oriented, not string-oriented. So why so
> many annotations, strings and just one object? This is the
> refactor-friendly version of URI builder that we use in VRaptor so
> people can refactor code and things are still working:
>

Your example doesn't make sense to me and I don't know what you are
trying to accomplish here, can you elaborate again, or link to
appropriate documentation or examples?

>
> This is the one that allows hypermedia resource generation in a
> refactor-friendly, non-annotation based way, i.e.:
>
> public class Basket implements HypermediaResource {
>
> public void configureRelations(RelationBuilder builder) {
> builder.relation("self").uses(BasketsController.class).show(id);
> builder.relation("payment").uses(PaymentsController.class).create(id, null);
> }
>
> }
>

The concept of a "RelationBuilder" sounds very interesting, but I'm not
fully understanding how you are using it here. I'd also like to see how
a RelationBuilder could be integrated (if at all) with JAXB.

>
>
> 6. Allow custom resource creation, so injection can be done in any way
> the client wants. Not only Java EE support in all JAX-RS
> implementations (done by the user, of course, unless we want to
> implement them also):
>
> public interface Container {
> <T> T instanceFor(Class<T> type);
> <T> boolean canProvide(Class<T> type);
> }
>
>

Yes! I talked about this above. We need an SPI to bridge to different,
and proprietary protocols. We have something very similar in RESTEasy
and it has worked pretty well in integrating with different component
models.





> 7. The heart of a new request. The semantic model for the HTTP<->Resource layer:
>
> public interface Router {
> void add(Route route);
> ResourceMethod parse(String uri, HttpMethod method, MutableRequest request)
> throws ResourceNotFoundException, MethodNotAllowedException,
> IllegalStateException;
> <T> String urlFor(Class<T> type, Method method, Object... params);
> List<Route> allRoutes();
> }
>
> And a route:
>
> public interface Route {
>
> boolean canHandle(String uri);
> EnumSet<HttpMethod> allowedMethods();
> String urlFor(Class<?> type, Method m, Object... params);
> boolean canHandle(Class<?> type, Method method);
> int getPriority();
> String getOriginalUri();
> }
>

+1. I'm all for adding extension SPIs like this.


>
> 8. Allow ordered interceptors. Most of the time behavior can be
> composed by using interceptors (as in servlet filters), without the
> need for global variables (threadlocals). Interceptor order
> might also be important:
>
> @Documented
> @Retention(RetentionPolicy.RUNTIME)
> @Target(ElementType.TYPE)
> @Stereotype
> public @interface Intercepts {
> Class<? extends Interceptor>[] before() default ExecuteMethodInterceptor.class;
> Class<? extends Interceptor>[] after() default ResourceLookupInterceptor.class;
> }
>

This kind of interceptor ordering declaration doesn't work very well
when, as a framework developer, you want to package a set of
interceptors and provide them to a user to build applications with.
Why? Well, as a framework developer you have no idea what other set of
interceptors written by some *other* framework developer will have on
your interceptors. And, you also don't want to make users manage,
define, and configure interceptor ordering.

In Resteasy, we have a @Precedence annotation in which you bind
interceptors to a specific "family" rather than defining a specific
order of interceptors. For example, instead of knowing which exact
interceptor you come after, you specify which slot you want to be in.
So, a Cache-Control interceptor that added a Cache-Control header, would
be slotted to the "HeaderDecorator" precedence. A gzip content encoder
would be slotted in the "Encoder" precedence.

Here's more doco on it:

http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html/Interceptors.html#interceptorPrecedence

This way of defining "interceptor family" groups has really made it much
easier to manage the growing number of packaged interceptors we're
providing out of the box.



-- 
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com