injecting @Context fields on sub resources...

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|

injecting @Context fields on sub resources...

jstrachan
if you had a Container and Element resources like this... (please
excuse the scala syntax...)

class Container extends Foo {
  @GET
  @Path("{id}")
  def getElement(@PathParam("id") key : String) = {
    doSomething
    new Element(key)
 }
  ...
}

class Element(key: String) extends Foo {
  @GET
  def index = {
    // this will fail here...
    doSomething
  }

...
}

abstract class Foo {
  @Context
  protected var servletContext: ServletContext = _

  def doSomething: Unit = {
    if (servletContext == null) throw IllegalArgumentException("no
servletContext injected! Probably a sub resource :)")
  }
}


Using @Context injection is very handy; however right now only root
resources get injected causing code like above to barf.

Is there any way to get Jersey to do injection of user created sub
resources (e.g. the Element instance) after its been created, but
before its methods have been invoked.
 e.g. after the Container.getElement is invoked and an Element
created, but before the Element.index method is invoked?

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

Paul Sandoz
Administrator
Hi James,

There are currently two ways for the application to instantiate  
resource classes:

1) Injected @Context ReosurceContext rc then call  
rc.getResource(MyClass.class);

     https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/core/ResourceContext.html

    def getElement(@PathParam("id") key : String, @Context  
ReosurceContext rc) {
      doSomething;
      val e = rc.get(classOf[Element]);
      e.setKey(e);
      return e;
    }

2) Using Jersey's @Inject (i know it is an unfortunate clash with 330).

    def getElement(@PathParam("id") key : String, @Inject  
Injectable<Element> ie) {
      doSomething;
      val e = ie.get();
      e.setKey(e);
      return e;
    }

None are quite what you want :-)

Injecting after instantiation sort of breaks the life-cycle contract  
(injection onto fields or setter methods should occur after  
construction and before any post construct method is invoked).

Paul.

On Apr 20, 2010, at 2:51 PM, James Strachan wrote:

> if you had a Container and Element resources like this... (please
> excuse the scala syntax...)
>
> class Container extends Foo {
>  @GET
>  @Path("{id}")
>  def getElement(@PathParam("id") key : String) = {
>    doSomething
>    new Element(key)
> }
>  ...
> }
>
> class Element(key: String) extends Foo {
>  @GET
>  def index = {
>    // this will fail here...
>    doSomething
>  }
>
> ...
> }
>
> abstract class Foo {
>  @Context
>  protected var servletContext: ServletContext = _
>
>  def doSomething: Unit = {
>    if (servletContext == null) throw IllegalArgumentException("no
> servletContext injected! Probably a sub resource :)")
>  }
> }
>
>
> Using @Context injection is very handy; however right now only root
> resources get injected causing code like above to barf.
>
> Is there any way to get Jersey to do injection of user created sub
> resources (e.g. the Element instance) after its been created, but
> before its methods have been invoked.
> e.g. after the Container.getElement is invoked and an Element
> created, but before the Element.index method is invoked?
>
> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
On 20 April 2010 15:01, Paul Sandoz <[hidden email]> wrote:

> Hi James,
>
> There are currently two ways for the application to instantiate resource
> classes:
>
> 1) Injected @Context ReosurceContext rc then call
> rc.getResource(MyClass.class);
>
>
>  https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/core/ResourceContext.html
>
>   def getElement(@PathParam("id") key : String, @Context ReosurceContext rc)
> {
>     doSomething;
>     val e = rc.get(classOf[Element]);
>     e.setKey(e);
>     return e;
>   }
>
> 2) Using Jersey's @Inject (i know it is an unfortunate clash with 330).
>
>   def getElement(@PathParam("id") key : String, @Inject Injectable<Element>
> ie) {
>     doSomething;
>     val e = ie.get();
>     e.setKey(e);
>     return e;
>   }
>
> None are quite what you want :-)

Thanks though - its good to know there is a way to do it!


> Injecting after instantiation sort of breaks the life-cycle contract
> (injection onto fields or setter methods should occur after construction and
> before any post construct method is invoked).

Though if I'm creating the sub resource object by hand, there will be
no post construction method invoked anyway - we're already outside of
the IoC post construction rules, since the IoC container isn't
creating the object - we're just invoking a constructor on the object.

It would be nice to be able to enable JAXRS injection into sub
resources - maybe as an optional extension?; it would leave the code
more dry. I find when creating sub resources I tend to create a custom
constructor for the root resource to invoke to keep code small & DRY.
It does seem a bit odd that you can share a base class/trait between a
root and sub resource and its not possible to have any of the
injections fire in the sub resources.

I wonder how hard it'd be to add as an option? I remember seeing in
both Guice and Spring for example a one line method call to perform
any remaining injections on an object if you create it outside of the
IoC container?

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

Paul Sandoz
Administrator
Hi James,

>> Injecting after instantiation sort of breaks the life-cycle contract
>> (injection onto fields or setter methods should occur after  
>> construction and
>> before any post construct method is invoked).
>
> Though if I'm creating the sub resource object by hand, there will be
> no post construction method invoked anyway - we're already outside of
> the IoC post construction rules, since the IoC container isn't
> creating the object - we're just invoking a constructor on the object.
>
> It would be nice to be able to enable JAXRS injection into sub
> resources - maybe as an optional extension?; it would leave the code
> more dry. I find when creating sub resources I tend to create a custom
> constructor for the root resource to invoke to keep code small & DRY.
> It does seem a bit odd that you can share a base class/trait between a
> root and sub resource and its not possible to have any of the
> injections fire in the sub resources.
>
> I wonder how hard it'd be to add as an option? I remember seeing in
> both Guice and Spring for example a one line method call to perform
> any remaining injections on an object if you create it outside of the
> IoC container?
>

One problem is for the code that processes the return instance from  
the sub-resource locator to determine whether the returned instance is  
managed or not (it could be managed by Jersey, Guice, Spring, CDI or  
whatever is plugged in). As we do not want to perform re-injection.

Currently there is no way in Jersey to determine if an instance is  
managed, or if the class of the instance is "in-scope". Is it possible  
in Guice/Spring/CDI to determine that?


If we can assume the case of when the instance is not managed it is  
reasonably easy to support injection. Perhaps we could support an  
annotation on a sub-resource locator and leave it up to the developer  
to do the right thing? We could also expose out the injection support  
in ResourceContext.

   ResourceContext.inject(Object o);


I would really like a type safe way of doing constructor injection  
with additional parameters but have not worked out a way that could be  
like Guice's assisted inject and work across the DI containers.

Paul.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
On 20 April 2010 16:39, Paul Sandoz <[hidden email]> wrote:

> Hi James,
>
>>> Injecting after instantiation sort of breaks the life-cycle contract
>>> (injection onto fields or setter methods should occur after construction
>>> and
>>> before any post construct method is invoked).
>>
>> Though if I'm creating the sub resource object by hand, there will be
>> no post construction method invoked anyway - we're already outside of
>> the IoC post construction rules, since the IoC container isn't
>> creating the object - we're just invoking a constructor on the object.
>>
>> It would be nice to be able to enable JAXRS injection into sub
>> resources - maybe as an optional extension?; it would leave the code
>> more dry. I find when creating sub resources I tend to create a custom
>> constructor for the root resource to invoke to keep code small & DRY.
>> It does seem a bit odd that you can share a base class/trait between a
>> root and sub resource and its not possible to have any of the
>> injections fire in the sub resources.
>>
>> I wonder how hard it'd be to add as an option? I remember seeing in
>> both Guice and Spring for example a one line method call to perform
>> any remaining injections on an object if you create it outside of the
>> IoC container?
>>
>
> One problem is for the code that processes the return instance from the
> sub-resource locator to determine whether the returned instance is managed
> or not (it could be managed by Jersey, Guice, Spring, CDI or whatever is
> plugged in). As we do not want to perform re-injection.

Ah I see...

I was actually only thinking of just the JAXRS/Jersey injection here,
not arbitrary Spring/Guice stuff. e.g. injecting @Context stuff only
(servletContext, request parameters and all that jazz).


> Currently there is no way in Jersey to determine if an instance is managed,
> or if the class of the instance is "in-scope". Is it possible in
> Guice/Spring/CDI to determine that?

Not too sure. It sounds a bit tricky. I've seen cases with Spring and
Guice in the past where they can create an instance of type X
(injecting its dependencies) without X being defined in the
configuration (spring XML or guice modules) so I guess that might be
hard.


> If we can assume the case of when the instance is not managed it is
> reasonably easy to support injection. Perhaps we could support an annotation
> on a sub-resource locator and leave it up to the developer to do the right
> thing? We could also expose out the injection support in ResourceContext.
>
>  ResourceContext.inject(Object o);
>
>
> I would really like a type safe way of doing constructor injection with
> additional parameters but have not worked out a way that could be like
> Guice's assisted inject and work across the DI containers.

How about if we only consider the JAXRS injections via @Context;
allowing those to be injected on sub resources via an optional flag in
Jersey?

I guess if you did create the object via Guice/Spring then that have
already done the JAXRS injections already. I guess in the grand scheme
of things doing the @Context injection twice is not a huge biggie -
plus am sure we could eventually keep a little cache of objects we've
injected to avoid doing it twice. Maybe using an annotation on each
sub resource might be more specific?

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

Paul Sandoz
Administrator
Hi James,

Another problem is if the resource instance is not managed then we do  
not know the scope of that instance, it could be even a static  
instance (bad practice i know!),

Thus probably the only reliable thing we can do under these  
circumstances is perform field injection (no setter method injection)  
of singleton dependencies, which would include all of the @Context you  
require plus what Jersey additional defines (or what the user adds  
too). Jersey's injection support will not inject if a field value is  
non-null.

Hence we could have init param to support this a re-injection of  
fields should not have any side effects if it has occurred already.  
Can you log an issue?

Paul.

On Apr 20, 2010, at 6:24 PM, James Strachan wrote:

> On 20 April 2010 16:39, Paul Sandoz <[hidden email]> wrote:
>> Hi James,
>>
>>>> Injecting after instantiation sort of breaks the life-cycle  
>>>> contract
>>>> (injection onto fields or setter methods should occur after  
>>>> construction
>>>> and
>>>> before any post construct method is invoked).
>>>
>>> Though if I'm creating the sub resource object by hand, there will  
>>> be
>>> no post construction method invoked anyway - we're already outside  
>>> of
>>> the IoC post construction rules, since the IoC container isn't
>>> creating the object - we're just invoking a constructor on the  
>>> object.
>>>
>>> It would be nice to be able to enable JAXRS injection into sub
>>> resources - maybe as an optional extension?; it would leave the code
>>> more dry. I find when creating sub resources I tend to create a  
>>> custom
>>> constructor for the root resource to invoke to keep code small &  
>>> DRY.
>>> It does seem a bit odd that you can share a base class/trait  
>>> between a
>>> root and sub resource and its not possible to have any of the
>>> injections fire in the sub resources.
>>>
>>> I wonder how hard it'd be to add as an option? I remember seeing in
>>> both Guice and Spring for example a one line method call to perform
>>> any remaining injections on an object if you create it outside of  
>>> the
>>> IoC container?
>>>
>>
>> One problem is for the code that processes the return instance from  
>> the
>> sub-resource locator to determine whether the returned instance is  
>> managed
>> or not (it could be managed by Jersey, Guice, Spring, CDI or  
>> whatever is
>> plugged in). As we do not want to perform re-injection.
>
> Ah I see...
>
> I was actually only thinking of just the JAXRS/Jersey injection here,
> not arbitrary Spring/Guice stuff. e.g. injecting @Context stuff only
> (servletContext, request parameters and all that jazz).
>
>
>> Currently there is no way in Jersey to determine if an instance is  
>> managed,
>> or if the class of the instance is "in-scope". Is it possible in
>> Guice/Spring/CDI to determine that?
>
> Not too sure. It sounds a bit tricky. I've seen cases with Spring and
> Guice in the past where they can create an instance of type X
> (injecting its dependencies) without X being defined in the
> configuration (spring XML or guice modules) so I guess that might be
> hard.
>
>
>> If we can assume the case of when the instance is not managed it is
>> reasonably easy to support injection. Perhaps we could support an  
>> annotation
>> on a sub-resource locator and leave it up to the developer to do  
>> the right
>> thing? We could also expose out the injection support in  
>> ResourceContext.
>>
>>  ResourceContext.inject(Object o);
>>
>>
>> I would really like a type safe way of doing constructor injection  
>> with
>> additional parameters but have not worked out a way that could be  
>> like
>> Guice's assisted inject and work across the DI containers.
>
> How about if we only consider the JAXRS injections via @Context;
> allowing those to be injected on sub resources via an optional flag in
> Jersey?
>
> I guess if you did create the object via Guice/Spring then that have
> already done the JAXRS injections already. I guess in the grand scheme
> of things doing the @Context injection twice is not a huge biggie -
> plus am sure we could eventually keep a little cache of objects we've
> injected to avoid doing it twice. Maybe using an annotation on each
> sub resource might be more specific?
>
> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
On 21 April 2010 09:43, Paul Sandoz <[hidden email]> wrote:
> Hi James,
>
> Another problem is if the resource instance is not managed then we do not
> know the scope of that instance, it could be even a static instance (bad
> practice i know!),

Yeah. Though if folks use container injection annotations on
singletons that are given to the container to invoke which also have
request specific stuff in there which their code depends on, their
code's already broken whether Jersey injects or not :)


> Thus probably the only reliable thing we can do under these circumstances is
> perform field injection (no setter method injection) of singleton
> dependencies,
> which would include all of the @Context you require plus what
> Jersey additional defines (or what the user adds too). Jersey's injection
> support will not inject if a field value is non-null.

Great!

> Hence we could have init param to support this a re-injection of fields
> should not have any side effects if it has occurred already.

Sounds great!

> Can you log an
> issue?

Done...
https://jersey.dev.java.net/issues/show_bug.cgi?id=513

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

Paul Sandoz
Administrator

On Apr 21, 2010, at 12:46 PM, James Strachan wrote:

> On 21 April 2010 09:43, Paul Sandoz <[hidden email]> wrote:
>> Hi James,
>>
>> Another problem is if the resource instance is not managed then we  
>> do not
>> know the scope of that instance, it could be even a static instance  
>> (bad
>> practice i know!),
>
> Yeah. Though if folks use container injection annotations on
> singletons that are given to the container to invoke which also have
> request specific stuff in there which their code depends on, their
> code's already broken whether Jersey injects or not :)
>
>
>> Thus probably the only reliable thing we can do under these  
>> circumstances is
>> perform field injection (no setter method injection) of singleton
>> dependencies,
>> which would include all of the @Context you require plus what
>> Jersey additional defines (or what the user adds too). Jersey's  
>> injection
>> support will not inject if a field value is non-null.
>
> Great!
>
>> Hence we could have init param to support this a re-injection of  
>> fields
>> should not have any side effects if it has occurred already.
>
> Sounds great!
>
>> Can you log an
>> issue?
>
> Done...
> https://jersey.dev.java.net/issues/show_bug.cgi?id=513
>

Thanks!
Paul.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
In reply to this post by Paul Sandoz
On 20 April 2010 15:01, Paul Sandoz <[hidden email]> wrote:

> Hi James,
>
> There are currently two ways for the application to instantiate resource
> classes:
>
> 1) Injected @Context ReosurceContext rc then call
> rc.getResource(MyClass.class);
>
>
>  https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/core/ResourceContext.html
>
>   def getElement(@PathParam("id") key : String, @Context ReosurceContext rc)
> {
>     doSomething;
>     val e = rc.get(classOf[Element]);
>     e.setKey(e);
>     return e;
>   }
>
> 2) Using Jersey's @Inject (i know it is an unfortunate clash with 330).
>
>   def getElement(@PathParam("id") key : String, @Inject Injectable<Element>
> ie) {
>     doSomething;
>     val e = ie.get();
>     e.setKey(e);
>     return e;
>   }
>
> None are quite what you want :-)
>
> Injecting after instantiation sort of breaks the life-cycle contract
> (injection onto fields or setter methods should occur after construction and
> before any post construct method is invoked).

A colleague hit this again today so I was wondering if we could come
up with a clean canonical way to get Jersey create sub resources for
us doing all the lifecycle/injection goodness without using the
ResourceContext/Injectable API?

e.g. something like...

class Container extends Foo {
 @GET
 @Path("{id}")
 def getElement(subResource: Element) = {
   // possibly modify the object we are given, or return something else...
   subResource
 }
 ...
}

class Element(@PathParam("id") key: String) extends Foo {
 @GET
 def index = {
  ...
 }
...
}

We might want to annotation the getElement's subResource parameter
somehow to indicate to Jersey its meant to inject a sub resource into
the method call?

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

Paul Sandoz
Administrator
Hi James,

So would something like the following work for you:

   def getElement(@<I do not know what to call this!> subResource:  
Element) = { ... }

?

That would be really easy to support because we can write an  
InjectableProvider that defers to ResourceContext. I can even send one  
in the email in addition to adding it to the workspace so that one can  
use it with a stable version.

But as you can tell i am having a naming problem :-) any suggestions?

Paul.

On Jun 30, 2010, at 4:23 PM, James Strachan wrote:

> On 20 April 2010 15:01, Paul Sandoz <[hidden email]> wrote:
>> Hi James,
>>
>> There are currently two ways for the application to instantiate  
>> resource
>> classes:
>>
>> 1) Injected @Context ReosurceContext rc then call
>> rc.getResource(MyClass.class);
>>
>>
>>  https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/core/ResourceContext.html
>>
>>   def getElement(@PathParam("id") key : String, @Context  
>> ReosurceContext rc)
>> {
>>     doSomething;
>>     val e = rc.get(classOf[Element]);
>>     e.setKey(e);
>>     return e;
>>   }
>>
>> 2) Using Jersey's @Inject (i know it is an unfortunate clash with  
>> 330).
>>
>>   def getElement(@PathParam("id") key : String, @Inject  
>> Injectable<Element>
>> ie) {
>>     doSomething;
>>     val e = ie.get();
>>     e.setKey(e);
>>     return e;
>>   }
>>
>> None are quite what you want :-)
>>
>> Injecting after instantiation sort of breaks the life-cycle contract
>> (injection onto fields or setter methods should occur after  
>> construction and
>> before any post construct method is invoked).
>
> A colleague hit this again today so I was wondering if we could come
> up with a clean canonical way to get Jersey create sub resources for
> us doing all the lifecycle/injection goodness without using the
> ResourceContext/Injectable API?
>
> e.g. something like...
>
> class Container extends Foo {
> @GET
> @Path("{id}")
> def getElement(subResource: Element) = {
>   // possibly modify the object we are given, or return something  
> else...
>   subResource
> }
> ...
> }
>
> class Element(@PathParam("id") key: String) extends Foo {
> @GET
> def index = {
>  ...
> }
> ...
> }
>
> We might want to annotation the getElement's subResource parameter
> somehow to indicate to Jersey its meant to inject a sub resource into
> the method call?
>
> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
On 1 July 2010 14:32, Paul Sandoz <[hidden email]> wrote:
> Hi James,
>
> So would something like the following work for you:
>
>  def getElement(@<I do not know what to call this!> subResource: Element) =
> { ... }
>
> ?

Sure!

> That would be really easy to support because we can write an
> InjectableProvider that defers to ResourceContext. I can even send one in
> the email in addition to adding it to the workspace so that one can use it
> with a stable version.
>
> But as you can tell i am having a naming problem :-) any suggestions?

Yeah, I wasn't sure what to call it either :)

How about...

def getElement(@SubResource e: Element) = ...


As an aside - I hit another related thing today. One of the awesome
things about JAXRS is its so modular; drop a bunch of jars together
with jaxrs beans in them and provided your URIs don't clash, you've an
extensible web app & REST API.

However I've found I often want to extend an existing sub resource in
a modular way so that adding a jar to a web app can extend/enhance a
web app/REST API.

e.g. camel-web is a web console for Camel which has a root resource &
then a rather big tree of sub resources. If folks drop in the
activemq-camel-web jar, it would be nice to be able to replace some of
the endpoints with derived sub resource classes which offer more
representations or behaviour with knowledge of activemq etc.

If the application code is explicitly doing "new Element(id)" then you
have to go through the whole resource chain from root to sub resource
and overriding them all.

If jersey is instantiating the sub resource we could let the framework
detect a sub class being on the classpath (if its in the set of
packages scanned by jersey) then a new DerivedElement class could be
injected in the above example.

e.g. in a base module...

def getElement(@SubResource e: Element) = ...


could return an instance of "Element".

Add derived.jar to the classpath and jersey might create a
"DerivedElement" instead.

(There could be issues if there are multiple derivations of the class
on the classpath though :)

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

Paul Sandoz
Administrator

On Jul 1, 2010, at 4:06 PM, James Strachan wrote:

> On 1 July 2010 14:32, Paul Sandoz <[hidden email]> wrote:
>> Hi James,
>>
>> So would something like the following work for you:
>>
>>  def getElement(@<I do not know what to call this!> subResource:  
>> Element) =
>> { ... }
>>
>> ?
>
> Sure!
>
>> That would be really easy to support because we can write an
>> InjectableProvider that defers to ResourceContext. I can even send  
>> one in
>> the email in addition to adding it to the workspace so that one can  
>> use it
>> with a stable version.
>>
>> But as you can tell i am having a naming problem :-) any suggestions?
>
> Yeah, I wasn't sure what to call it either :)
>
> How about...
>
> def getElement(@SubResource e: Element) = ...
>

I thought of that too, but may not be accurate as a sub-resource could  
ask for a reference to the root resource using the same mechanism.

   @ResourceRef?

still don't like it much but...

Would you mind logging an issue, since i will be away i am not sure i  
will get to this today and may forget when i get back!


>
> As an aside - I hit another related thing today. One of the awesome
> things about JAXRS is its so modular; drop a bunch of jars together
> with jaxrs beans in them and provided your URIs don't clash, you've an
> extensible web app & REST API.
>
> However I've found I often want to extend an existing sub resource in
> a modular way so that adding a jar to a web app can extend/enhance a
> web app/REST API.
>
> e.g. camel-web is a web console for Camel which has a root resource &
> then a rather big tree of sub resources. If folks drop in the
> activemq-camel-web jar, it would be nice to be able to replace some of
> the endpoints with derived sub resource classes which offer more
> representations or behaviour with knowledge of activemq etc.
>
> If the application code is explicitly doing "new Element(id)" then you
> have to go through the whole resource chain from root to sub resource
> and overriding them all.
>
> If jersey is instantiating the sub resource we could let the framework
> detect a sub class being on the classpath (if its in the set of
> packages scanned by jersey) then a new DerivedElement class could be
> injected in the above example.
>
> e.g. in a base module...
>
> def getElement(@SubResource e: Element) = ...
>
>
> could return an instance of "Element".
>
> Add derived.jar to the classpath and jersey might create a
> "DerivedElement" instead.
>
> (There could be issues if there are multiple derivations of the class
> on the classpath though :)
>

Do you think it might be better in this case to use Guice? A binding  
could declare that when a reference to Element is requested it will be  
an implementation of DerivedElement. This would avoid issues of  
multiple derivations and also avoid the tricky bit of Jersey having to  
scan for derived classes.

I think that should actually work with @SubResource given the way  
Jersey will ask Guice for a reference.

Paul.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
On 2 July 2010 06:58, Paul Sandoz <[hidden email]> wrote:

> On Jul 1, 2010, at 4:06 PM, James Strachan wrote:
>> On 1 July 2010 14:32, Paul Sandoz <[hidden email]> wrote:
>>>
>>> Hi James,
>>>
>>> So would something like the following work for you:
>>>
>>>  def getElement(@<I do not know what to call this!> subResource: Element)
>>> =
>>> { ... }
>>>
>>> ?
>>
>> Sure!
>>
>>> That would be really easy to support because we can write an
>>> InjectableProvider that defers to ResourceContext. I can even send one in
>>> the email in addition to adding it to the workspace so that one can use
>>> it
>>> with a stable version.
>>>
>>> But as you can tell i am having a naming problem :-) any suggestions?
>>
>> Yeah, I wasn't sure what to call it either :)
>>
>> How about...
>>
>> def getElement(@SubResource e: Element) = ...
>>
>
> I thought of that too, but may not be accurate as a sub-resource could ask
> for a reference to the root resource using the same mechanism.
>
>  @ResourceRef?
>
> still don't like it much but...
>
> Would you mind logging an issue, since i will be away i am not sure i will
> get to this today and may forget when i get back!
>
>
>>
>> As an aside - I hit another related thing today. One of the awesome
>> things about JAXRS is its so modular; drop a bunch of jars together
>> with jaxrs beans in them and provided your URIs don't clash, you've an
>> extensible web app & REST API.
>>
>> However I've found I often want to extend an existing sub resource in
>> a modular way so that adding a jar to a web app can extend/enhance a
>> web app/REST API.
>>
>> e.g. camel-web is a web console for Camel which has a root resource &
>> then a rather big tree of sub resources. If folks drop in the
>> activemq-camel-web jar, it would be nice to be able to replace some of
>> the endpoints with derived sub resource classes which offer more
>> representations or behaviour with knowledge of activemq etc.
>>
>> If the application code is explicitly doing "new Element(id)" then you
>> have to go through the whole resource chain from root to sub resource
>> and overriding them all.
>>
>> If jersey is instantiating the sub resource we could let the framework
>> detect a sub class being on the classpath (if its in the set of
>> packages scanned by jersey) then a new DerivedElement class could be
>> injected in the above example.
>>
>> e.g. in a base module...
>>
>> def getElement(@SubResource e: Element) = ...
>>
>>
>> could return an instance of "Element".
>>
>> Add derived.jar to the classpath and jersey might create a
>> "DerivedElement" instead.
>>
>> (There could be issues if there are multiple derivations of the class
>> on the classpath though :)
>>
>
> Do you think it might be better in this case to use Guice? A binding could
> declare that when a reference to Element is requested it will be an
> implementation of DerivedElement. This would avoid issues of multiple
> derivations and also avoid the tricky bit of Jersey having to scan for
> derived classes.
>
> I think that should actually work with @SubResource given the way Jersey
> will ask Guice for a reference.

Here's another thought on this.

One of the great things about JAXRS is it leads to very modular
web/REST applications. Its easy to split up
features/resources/representations into different jars with different
dependencies so folks can mix and match features.

To give a more concrete example; the Apache Camel project as a Jersey
based web/REST application. We want to allow sub resources to be
customized and new resources added in different modules customers may
use. e.g. if folks are using Apache ActiveMQ with Camel, if they drop
the right jar onto the classpath then hey-presto they get new
resources and representations (typically sub resources of existing
resources) for ActiveMQ specific things which users who use, say,
Camel with just file systems don't need.

Imagine if we wish to add a new resource/representation to an existing
resource or sub resource. Typically we'd have to create our own
derivation of the respective root resource - then delve into each sub
resource @Path method, override it to return a new derived class -
walk the chain of resources until we get to the parent resource we are
going to create a new sub resource from - then add a new method to
return a new resource bean.

This seems rather a lot of work - particularly for deeply nested
resources. What would be a little more DRY and much simpler would be
if we could add a sub resource to a parent resource in a more loosely
coupled way - and let Jersey do the resource path walking and
dependency injection to leave things loosely coupled.

e.g. imagine these 2 loosely coupled resources, a root and
sub-resource where the sub resource is optional defined in a separate
jar...

// style A

// my-foo.jar module

@Path("/whatver")
class FooResource {
}


// my-bar.jar module

@Path("bar/{id}")
@SubResource(FooResource.class)
class BarResource {
   @PathParam("id") String id;
   @Context FooResource parentResource;

  @GET String getBody() {...}
}

Here we are changing the JAXRS model slightly for sub resources;
rather than the parent resource, FooResource knowing at compile time
all the possible sub resources available and having methods defined on
it for each sub resource to return each new instance available, we use
a new annotation (@SubResource) on the sub resource class to create a
new sub resource on the FooResource class. In this case @SubResource
specifically marks a class as being a sub resource - and also links
the sub resource to its parent class. This decouples the parent
resource from having to know at compile time of all the possible sub
resources available.

Then we use dependency injection to inject the path parameter in the
sub resource - along with anything else we need - in this example I've
used @Context to also inject the parent resource too.

So this is functionally equivalent to writing something like...

// style B

@Path("/whatver")
class FooResource {

  @Path("bar/{id}")
  pubilc BarResource getBar(@PathParam("id") String id) {
    return new BarResource(id, this);
  }
}

class BarResource {
   String id;
   FooResource parentResource;

  public BarResource(String id, FooResource parentResource) {
    this.id = id;
    this.parentResource = parentResource;
  }

  @GET String getBody() {...}
}

However the former is better as

* its leaner meaner code that's more declarative & DRY
* annotations tend to stay closer to where they are really required -
e.g. compare the two BarResource implementations; one of them is very
clear what those fields are, one is not - you have to search for users
of its constructor to see what the JAXRS metadata is.
* we get to reuse the same injection model on sub resources as we do
for resources (so we can inject anything we like rather than having to
manually hand-craft constructors and methods-which-call-constructors)
* sub resources are now very modular - anyone can add a sub resource
to any resource easily in a separate jar without lots of redundant
spagetti code to override all the methods invoked to navigate from the
root resource to the newly created leaf resource. Plus it gets very
complex if you want to support 2 kinds of optional sub resource in 2
different jars using the same parent resource using the old way :)
* it feels a bit more natural than my previous suggestion (style C
below) to get injection on sub resources - of having methods on the
parent resource which get injected with the sub resource - that
typically don't do anything at all other than return what they are
given :)

e.g. if we wanted to get injection on the sub resource we could do
something like this from my previous mails...

// style C

@Path("/whatver")
class FooResource {

  @Path("bar/{id}")
  public BarResource getBar(@ResourceRef BarResource bar) {
    return bar;
  }
}


// my-bar.jar module

class BarResource {
   @PathParam("id") String id;
   @Context FooResource parentResource;

  @GET String getBody() {...}
}

Its interesting that the sub resource code in style C is pretty
similar to style A (since we're using injection on it). All we're
doing is removing a fairly pointless getBar() method in the
FooResource - which also adds a tight compile time coupling between
the resources - and move the method's 2 annotations into the sub
resource class (which is more useful anyway when viewing the code for
BarResource).

So it seems simpler to just annotate sub resource classes to link them
to parent resources and get dependency injection - i.e. style A wins.
I guess if a sub resource were to be created from multiple parent
resource classes using different @Path template URIs, then folks could
always use style C - having the factory methods of the sub resources
on the parent resources can be useful if you need many of them and/or
using different @Paths. Style A is useful when you only have one
parent resource class for a sub resource (which is very common), want
slightly more DRY code keeping annotations closer to their relevant
code and when you want more modular code (e.g. so sub resources can be
in different jars).

Thoughts?

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
BTW I've raised an issue to track this
https://jersey.dev.java.net/issues/show_bug.cgi?id=560

On 15 July 2010 10:01, James Strachan <[hidden email]> wrote:

> On 2 July 2010 06:58, Paul Sandoz <[hidden email]> wrote:
>> On Jul 1, 2010, at 4:06 PM, James Strachan wrote:
>>> On 1 July 2010 14:32, Paul Sandoz <[hidden email]> wrote:
>>>>
>>>> Hi James,
>>>>
>>>> So would something like the following work for you:
>>>>
>>>>  def getElement(@<I do not know what to call this!> subResource: Element)
>>>> =
>>>> { ... }
>>>>
>>>> ?
>>>
>>> Sure!
>>>
>>>> That would be really easy to support because we can write an
>>>> InjectableProvider that defers to ResourceContext. I can even send one in
>>>> the email in addition to adding it to the workspace so that one can use
>>>> it
>>>> with a stable version.
>>>>
>>>> But as you can tell i am having a naming problem :-) any suggestions?
>>>
>>> Yeah, I wasn't sure what to call it either :)
>>>
>>> How about...
>>>
>>> def getElement(@SubResource e: Element) = ...
>>>
>>
>> I thought of that too, but may not be accurate as a sub-resource could ask
>> for a reference to the root resource using the same mechanism.
>>
>>  @ResourceRef?
>>
>> still don't like it much but...
>>
>> Would you mind logging an issue, since i will be away i am not sure i will
>> get to this today and may forget when i get back!
>>
>>
>>>
>>> As an aside - I hit another related thing today. One of the awesome
>>> things about JAXRS is its so modular; drop a bunch of jars together
>>> with jaxrs beans in them and provided your URIs don't clash, you've an
>>> extensible web app & REST API.
>>>
>>> However I've found I often want to extend an existing sub resource in
>>> a modular way so that adding a jar to a web app can extend/enhance a
>>> web app/REST API.
>>>
>>> e.g. camel-web is a web console for Camel which has a root resource &
>>> then a rather big tree of sub resources. If folks drop in the
>>> activemq-camel-web jar, it would be nice to be able to replace some of
>>> the endpoints with derived sub resource classes which offer more
>>> representations or behaviour with knowledge of activemq etc.
>>>
>>> If the application code is explicitly doing "new Element(id)" then you
>>> have to go through the whole resource chain from root to sub resource
>>> and overriding them all.
>>>
>>> If jersey is instantiating the sub resource we could let the framework
>>> detect a sub class being on the classpath (if its in the set of
>>> packages scanned by jersey) then a new DerivedElement class could be
>>> injected in the above example.
>>>
>>> e.g. in a base module...
>>>
>>> def getElement(@SubResource e: Element) = ...
>>>
>>>
>>> could return an instance of "Element".
>>>
>>> Add derived.jar to the classpath and jersey might create a
>>> "DerivedElement" instead.
>>>
>>> (There could be issues if there are multiple derivations of the class
>>> on the classpath though :)
>>>
>>
>> Do you think it might be better in this case to use Guice? A binding could
>> declare that when a reference to Element is requested it will be an
>> implementation of DerivedElement. This would avoid issues of multiple
>> derivations and also avoid the tricky bit of Jersey having to scan for
>> derived classes.
>>
>> I think that should actually work with @SubResource given the way Jersey
>> will ask Guice for a reference.
>
> Here's another thought on this.
>
> One of the great things about JAXRS is it leads to very modular
> web/REST applications. Its easy to split up
> features/resources/representations into different jars with different
> dependencies so folks can mix and match features.
>
> To give a more concrete example; the Apache Camel project as a Jersey
> based web/REST application. We want to allow sub resources to be
> customized and new resources added in different modules customers may
> use. e.g. if folks are using Apache ActiveMQ with Camel, if they drop
> the right jar onto the classpath then hey-presto they get new
> resources and representations (typically sub resources of existing
> resources) for ActiveMQ specific things which users who use, say,
> Camel with just file systems don't need.
>
> Imagine if we wish to add a new resource/representation to an existing
> resource or sub resource. Typically we'd have to create our own
> derivation of the respective root resource - then delve into each sub
> resource @Path method, override it to return a new derived class -
> walk the chain of resources until we get to the parent resource we are
> going to create a new sub resource from - then add a new method to
> return a new resource bean.
>
> This seems rather a lot of work - particularly for deeply nested
> resources. What would be a little more DRY and much simpler would be
> if we could add a sub resource to a parent resource in a more loosely
> coupled way - and let Jersey do the resource path walking and
> dependency injection to leave things loosely coupled.
>
> e.g. imagine these 2 loosely coupled resources, a root and
> sub-resource where the sub resource is optional defined in a separate
> jar...
>
> // style A
>
> // my-foo.jar module
>
> @Path("/whatver")
> class FooResource {
> }
>
>
> // my-bar.jar module
>
> @Path("bar/{id}")
> @SubResource(FooResource.class)
> class BarResource {
>   @PathParam("id") String id;
>   @Context FooResource parentResource;
>
>  @GET String getBody() {...}
> }
>
> Here we are changing the JAXRS model slightly for sub resources;
> rather than the parent resource, FooResource knowing at compile time
> all the possible sub resources available and having methods defined on
> it for each sub resource to return each new instance available, we use
> a new annotation (@SubResource) on the sub resource class to create a
> new sub resource on the FooResource class. In this case @SubResource
> specifically marks a class as being a sub resource - and also links
> the sub resource to its parent class. This decouples the parent
> resource from having to know at compile time of all the possible sub
> resources available.
>
> Then we use dependency injection to inject the path parameter in the
> sub resource - along with anything else we need - in this example I've
> used @Context to also inject the parent resource too.
>
> So this is functionally equivalent to writing something like...
>
> // style B
>
> @Path("/whatver")
> class FooResource {
>
>  @Path("bar/{id}")
>  pubilc BarResource getBar(@PathParam("id") String id) {
>    return new BarResource(id, this);
>  }
> }
>
> class BarResource {
>   String id;
>   FooResource parentResource;
>
>  public BarResource(String id, FooResource parentResource) {
>    this.id = id;
>    this.parentResource = parentResource;
>  }
>
>  @GET String getBody() {...}
> }
>
> However the former is better as
>
> * its leaner meaner code that's more declarative & DRY
> * annotations tend to stay closer to where they are really required -
> e.g. compare the two BarResource implementations; one of them is very
> clear what those fields are, one is not - you have to search for users
> of its constructor to see what the JAXRS metadata is.
> * we get to reuse the same injection model on sub resources as we do
> for resources (so we can inject anything we like rather than having to
> manually hand-craft constructors and methods-which-call-constructors)
> * sub resources are now very modular - anyone can add a sub resource
> to any resource easily in a separate jar without lots of redundant
> spagetti code to override all the methods invoked to navigate from the
> root resource to the newly created leaf resource. Plus it gets very
> complex if you want to support 2 kinds of optional sub resource in 2
> different jars using the same parent resource using the old way :)
> * it feels a bit more natural than my previous suggestion (style C
> below) to get injection on sub resources - of having methods on the
> parent resource which get injected with the sub resource - that
> typically don't do anything at all other than return what they are
> given :)
>
> e.g. if we wanted to get injection on the sub resource we could do
> something like this from my previous mails...
>
> // style C
>
> @Path("/whatver")
> class FooResource {
>
>  @Path("bar/{id}")
>  public BarResource getBar(@ResourceRef BarResource bar) {
>    return bar;
>  }
> }
>
>
> // my-bar.jar module
>
> class BarResource {
>   @PathParam("id") String id;
>   @Context FooResource parentResource;
>
>  @GET String getBody() {...}
> }
>
> Its interesting that the sub resource code in style C is pretty
> similar to style A (since we're using injection on it). All we're
> doing is removing a fairly pointless getBar() method in the
> FooResource - which also adds a tight compile time coupling between
> the resources - and move the method's 2 annotations into the sub
> resource class (which is more useful anyway when viewing the code for
> BarResource).
>
> So it seems simpler to just annotate sub resource classes to link them
> to parent resources and get dependency injection - i.e. style A wins.
> I guess if a sub resource were to be created from multiple parent
> resource classes using different @Path template URIs, then folks could
> always use style C - having the factory methods of the sub resources
> on the parent resources can be useful if you need many of them and/or
> using different @Paths. Style A is useful when you only have one
> parent resource class for a sub resource (which is very common), want
> slightly more DRY code keeping annotations closer to their relevant
> code and when you want more modular code (e.g. so sub resources can be
> in different jars).
>
> Thoughts?
>
> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>



--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

Paul Sandoz-2
In reply to this post by jstrachan
Hi James,

AFIAK style A would enable a one-level deep relationship between a  
root resource and a sub-resource. It would enable the developer to add  
sub-resources to a any root resource if that was intended or otherwise  
(although one could devise ways to disallow that).

In such a case it would be almost as easy to make the sub-resource in  
style A a root resource with @Path("whatever/bar/{id}") if there is no  
value in the parent/sub relationship. Some shared behavior could be  
inherited from a common base class. The downside in this case is the  
"whatever" is repeated.

Do you envisage a use-case where a sub-resource is added to a root  
resource without modification to the latter? I guess that is what  
makes me uncomfortable about style A.

I suppose in Guice one could could modify the bindings such that  
BarResource is bound to a specialized implementation, in fact one  
might qualify it in this case so BarResource is reusable in other  
contexts:

@Path("/whatver")
class FooResource {
  @SubOfFoo @Inject Provider<BarResource> bar;

  @Path("bar/{id}")
  public BarResource getBar() { // Should try and add support for 330  
@Inject for parameters
    return bar.get();
  }
}

Thus specialization is possible without loosing the clear definition  
of sub-resources, and specialization is clearly defined according to  
Guice bindings. Although the above bugs me that there is a  
dissociation between the path parameter, "id", and BarResource.

One way to solve this would be to allow the intermixing of injected  
and passed parameters a bit like Guice's assisted inject, but i cannot  
come up with an appropriately typed and easy solution to that problem  
independent of Guice, and Guice still requires the creation of a  
factory interface

@Path("/whatever")
class FooResource {
  @Inject BarResourceFactory bar;

  @Path("bar/{id}")
  public BarResource getBar(@PathParam("id") String id) {
    return bar.create(id);
  }
}

interface BarResourceFactory {
   public BarResource.create(String id);
}

class BarResource {
   @Inject
   BarResource(@Inject FooResource foo, @Assisted String id) { ... }
}

This is frustrating, i feel we are missing a language feature here  
that could really help.

It is certainly easy to implement support for @ResourceRef (and say  
@SuperResourceRef to validate a parent of a certain type) as we  
already that support for that in a slightly different way.

Style A would be a little harder. Having @SubResource("bar/{id}",  
BarResource.class) would be easier because we don't change the  
definition of what a root resource is. I am currently not too sure  
about the consequences of a sub-resource modifying the relationship to  
a super resource when jar is dropped into the classpath. It could make  
for harder debugging if more magic is involved. If the super resource  
is unaware of the sub-resources that could be attached it may make it  
harder to define application-based hypermedia representations on the  
super resource (although at runtime the relationships will be  
recognized by the WADL representation returned by the super resource).


I am wondering in such cases that perhaps it might be better to define  
a routes class that provides a global view of the relationships?

   resource(Foo.class, "blah).
     subResources(resource(Bar.class, "b"), resource(Baz.class, "z"))

kind of hard to wire up graphs nicely using Java though.


What if we could wire up the sub-resource to the super-resource but  
the path is defined on the former? that would at least resolve my  
concerns about the "anything goes" relationship and the path would be  
defined on the sub-resource.

@Path("/whatver")
@SubResource(BarResource.class)
class FooResource { }

@SubPath("bar/{id}") // Different annotation so as not to conflict  
with def of root resource
class BarResource {
   @PathParam("id") String id;
   @ResourceRef FooResource parentResource;

  @GET String getBody() {...}
}

It also means one could define sub-resources on sub-resources.

Paul.

On Jul 15, 2010, at 11:01 AM, James Strachan wrote:

> On 2 July 2010 06:58, Paul Sandoz <[hidden email]> wrote:
>> On Jul 1, 2010, at 4:06 PM, James Strachan wrote:
>>> On 1 July 2010 14:32, Paul Sandoz <[hidden email]> wrote:
>>>>
>>>> Hi James,
>>>>
>>>> So would something like the following work for you:
>>>>
>>>>  def getElement(@<I do not know what to call this!> subResource:  
>>>> Element)
>>>> =
>>>> { ... }
>>>>
>>>> ?
>>>
>>> Sure!
>>>
>>>> That would be really easy to support because we can write an
>>>> InjectableProvider that defers to ResourceContext. I can even  
>>>> send one in
>>>> the email in addition to adding it to the workspace so that one  
>>>> can use
>>>> it
>>>> with a stable version.
>>>>
>>>> But as you can tell i am having a naming problem :-) any  
>>>> suggestions?
>>>
>>> Yeah, I wasn't sure what to call it either :)
>>>
>>> How about...
>>>
>>> def getElement(@SubResource e: Element) = ...
>>>
>>
>> I thought of that too, but may not be accurate as a sub-resource  
>> could ask
>> for a reference to the root resource using the same mechanism.
>>
>>  @ResourceRef?
>>
>> still don't like it much but...
>>
>> Would you mind logging an issue, since i will be away i am not sure  
>> i will
>> get to this today and may forget when i get back!
>>
>>
>>>
>>> As an aside - I hit another related thing today. One of the awesome
>>> things about JAXRS is its so modular; drop a bunch of jars together
>>> with jaxrs beans in them and provided your URIs don't clash,  
>>> you've an
>>> extensible web app & REST API.
>>>
>>> However I've found I often want to extend an existing sub resource  
>>> in
>>> a modular way so that adding a jar to a web app can extend/enhance a
>>> web app/REST API.
>>>
>>> e.g. camel-web is a web console for Camel which has a root  
>>> resource &
>>> then a rather big tree of sub resources. If folks drop in the
>>> activemq-camel-web jar, it would be nice to be able to replace  
>>> some of
>>> the endpoints with derived sub resource classes which offer more
>>> representations or behaviour with knowledge of activemq etc.
>>>
>>> If the application code is explicitly doing "new Element(id)" then  
>>> you
>>> have to go through the whole resource chain from root to sub  
>>> resource
>>> and overriding them all.
>>>
>>> If jersey is instantiating the sub resource we could let the  
>>> framework
>>> detect a sub class being on the classpath (if its in the set of
>>> packages scanned by jersey) then a new DerivedElement class could be
>>> injected in the above example.
>>>
>>> e.g. in a base module...
>>>
>>> def getElement(@SubResource e: Element) = ...
>>>
>>>
>>> could return an instance of "Element".
>>>
>>> Add derived.jar to the classpath and jersey might create a
>>> "DerivedElement" instead.
>>>
>>> (There could be issues if there are multiple derivations of the  
>>> class
>>> on the classpath though :)
>>>
>>
>> Do you think it might be better in this case to use Guice? A  
>> binding could
>> declare that when a reference to Element is requested it will be an
>> implementation of DerivedElement. This would avoid issues of multiple
>> derivations and also avoid the tricky bit of Jersey having to scan  
>> for
>> derived classes.
>>
>> I think that should actually work with @SubResource given the way  
>> Jersey
>> will ask Guice for a reference.
>
> Here's another thought on this.
>
> One of the great things about JAXRS is it leads to very modular
> web/REST applications. Its easy to split up
> features/resources/representations into different jars with different
> dependencies so folks can mix and match features.
>
> To give a more concrete example; the Apache Camel project as a Jersey
> based web/REST application. We want to allow sub resources to be
> customized and new resources added in different modules customers may
> use. e.g. if folks are using Apache ActiveMQ with Camel, if they drop
> the right jar onto the classpath then hey-presto they get new
> resources and representations (typically sub resources of existing
> resources) for ActiveMQ specific things which users who use, say,
> Camel with just file systems don't need.
>
> Imagine if we wish to add a new resource/representation to an existing
> resource or sub resource. Typically we'd have to create our own
> derivation of the respective root resource - then delve into each sub
> resource @Path method, override it to return a new derived class -
> walk the chain of resources until we get to the parent resource we are
> going to create a new sub resource from - then add a new method to
> return a new resource bean.
>
> This seems rather a lot of work - particularly for deeply nested
> resources. What would be a little more DRY and much simpler would be
> if we could add a sub resource to a parent resource in a more loosely
> coupled way - and let Jersey do the resource path walking and
> dependency injection to leave things loosely coupled.
>
> e.g. imagine these 2 loosely coupled resources, a root and
> sub-resource where the sub resource is optional defined in a separate
> jar...
>
> // style A
>
> // my-foo.jar module
>
> @Path("/whatver")
> class FooResource {
> }
>
>
> // my-bar.jar module
>
> @Path("bar/{id}")
> @SubResource(FooResource.class)
> class BarResource {
>   @PathParam("id") String id;
>   @Context FooResource parentResource;
>
>  @GET String getBody() {...}
> }
>
> Here we are changing the JAXRS model slightly for sub resources;
> rather than the parent resource, FooResource knowing at compile time
> all the possible sub resources available and having methods defined on
> it for each sub resource to return each new instance available, we use
> a new annotation (@SubResource) on the sub resource class to create a
> new sub resource on the FooResource class. In this case @SubResource
> specifically marks a class as being a sub resource - and also links
> the sub resource to its parent class. This decouples the parent
> resource from having to know at compile time of all the possible sub
> resources available.
>
> Then we use dependency injection to inject the path parameter in the
> sub resource - along with anything else we need - in this example I've
> used @Context to also inject the parent resource too.
>
> So this is functionally equivalent to writing something like...
>
> // style B
>
> @Path("/whatver")
> class FooResource {
>
>  @Path("bar/{id}")
>  pubilc BarResource getBar(@PathParam("id") String id) {
>    return new BarResource(id, this);
>  }
> }
>
> class BarResource {
>   String id;
>   FooResource parentResource;
>
>  public BarResource(String id, FooResource parentResource) {
>    this.id = id;
>    this.parentResource = parentResource;
>  }
>
>  @GET String getBody() {...}
> }
>
> However the former is better as
>
> * its leaner meaner code that's more declarative & DRY
> * annotations tend to stay closer to where they are really required -
> e.g. compare the two BarResource implementations; one of them is very
> clear what those fields are, one is not - you have to search for users
> of its constructor to see what the JAXRS metadata is.
> * we get to reuse the same injection model on sub resources as we do
> for resources (so we can inject anything we like rather than having to
> manually hand-craft constructors and methods-which-call-constructors)
> * sub resources are now very modular - anyone can add a sub resource
> to any resource easily in a separate jar without lots of redundant
> spagetti code to override all the methods invoked to navigate from the
> root resource to the newly created leaf resource. Plus it gets very
> complex if you want to support 2 kinds of optional sub resource in 2
> different jars using the same parent resource using the old way :)
> * it feels a bit more natural than my previous suggestion (style C
> below) to get injection on sub resources - of having methods on the
> parent resource which get injected with the sub resource - that
> typically don't do anything at all other than return what they are
> given :)
>
> e.g. if we wanted to get injection on the sub resource we could do
> something like this from my previous mails...
>
> // style C
>
> @Path("/whatver")
> class FooResource {
>
>  @Path("bar/{id}")
>  public BarResource getBar(@ResourceRef BarResource bar) {
>    return bar;
>  }
> }
>
>
> // my-bar.jar module
>
> class BarResource {
>   @PathParam("id") String id;
>   @Context FooResource parentResource;
>
>  @GET String getBody() {...}
> }
>
> Its interesting that the sub resource code in style C is pretty
> similar to style A (since we're using injection on it). All we're
> doing is removing a fairly pointless getBar() method in the
> FooResource - which also adds a tight compile time coupling between
> the resources - and move the method's 2 annotations into the sub
> resource class (which is more useful anyway when viewing the code for
> BarResource).
>
> So it seems simpler to just annotate sub resource classes to link them
> to parent resources and get dependency injection - i.e. style A wins.
> I guess if a sub resource were to be created from multiple parent
> resource classes using different @Path template URIs, then folks could
> always use style C - having the factory methods of the sub resources
> on the parent resources can be useful if you need many of them and/or
> using different @Paths. Style A is useful when you only have one
> parent resource class for a sub resource (which is very common), want
> slightly more DRY code keeping annotations closer to their relevant
> code and when you want more modular code (e.g. so sub resources can be
> in different jars).
>
> Thoughts?
>
> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
On 2 August 2010 16:11, Paul Sandoz <[hidden email]> wrote:
> Hi James,
>
> AFIAK style A would enable a one-level deep relationship between a root
> resource and a sub-resource.

Sorry I wasn't very clear. For style A I was assuming we can add a sub
resource to any resource; whether its a root or sub resource.


> It would enable the developer to add
> sub-resources to a any root resource if that was intended or otherwise
> (although one could devise ways to disallow that).
>
> In such a case it would be almost as easy to make the sub-resource in style
> A a root resource with @Path("whatever/bar/{id}") if there is no value in
> the parent/sub relationship. Some shared behavior could be inherited from a
> common base class. The downside in this case is the "whatever" is repeated.

But imagine a deeply nested tree...

/customers/123/orders/abc/detail

where you've navigated through 4 resources. Then imagine the "detail"
resource having to basically copy-paste all of those URI templates and
handle all the path params then probably replicate much of the
functionality of those resource beans too.

But for a single sub resource when the parent root resource uses a
simple static uri template when there's not much injection going on
then you're right, style A only really helps for the injection of sub
resources.


> Do you envisage a use-case where a sub-resource is added to a root resource
> without modification to the latter? I guess that is what makes me
> uncomfortable about style A.

Yes. The idea is to add a sub resource to an existing resource (root
or sub or subsub etc), without having to change the entire tree of
resource beans or refactoring them all to shove in some injection
magic or provide a derived class for each resource etc.

If you own the source code and can add a compile time dependency on
the new sub resource then style C is an alternative too. Though I
prefer style A as its more DRY and lets JAXRS web applications be more
easily extensible. Each web application has an explicit set of
packages searched; but I can put the same base web app into different
builds which include new additional sub-resources with style C.


> I suppose in Guice one could could modify the bindings such that BarResource
> is bound to a specialized implementation, in fact one might qualify it in
> this case so BarResource is reusable in other contexts:
>
> @Path("/whatver")
> class FooResource {
>  @SubOfFoo @Inject Provider<BarResource> bar;
>
>  @Path("bar/{id}")
>  public BarResource getBar() { // Should try and add support for 330 @Inject
> for parameters
>   return bar.get();
>  }
> }
>
> Thus specialization is possible without loosing the clear definition of
> sub-resources, and specialization is clearly defined according to Guice
> bindings. Although the above bugs me that there is a dissociation between
> the path parameter, "id", and BarResource.

Yeah.

It also requires that all parent resources are written with
extensibility in mind. You can't just add a new sub-resource anywhere
in the tree of resources. Look how much noise we've just added for one
level of resource depth; imagine 4 or 5 resources deep & how much pain
there is :)


> One way to solve this would be to allow the intermixing of injected and
> passed parameters a bit like Guice's assisted inject, but i cannot come up
> with an appropriately typed and easy solution to that problem independent of
> Guice, and Guice still requires the creation of a factory interface
>
> @Path("/whatever")
> class FooResource {
>  @Inject BarResourceFactory bar;
>
>  @Path("bar/{id}")
>  public BarResource getBar(@PathParam("id") String id) {
>   return bar.create(id);
>  }
> }
>
> interface BarResourceFactory {
>  public BarResource.create(String id);
> }
>
> class BarResource {
>  @Inject
>  BarResource(@Inject FooResource foo, @Assisted String id) { ... }
> }
>
> This is frustrating, i feel we are missing a language feature here that
> could really help.

Yeah - its kinda verbose though having to shove factories everywhere
which only really help the framework implementation; they are just
noise to the application programmer :)


> It is certainly easy to implement support for @ResourceRef (and say
> @SuperResourceRef to validate a parent of a certain type) as we already that
> support for that in a slightly different way.
>
> Style A would be a little harder. Having @SubResource("bar/{id}",
> BarResource.class) would be easier because we don't change the definition of
> what a root resource is.

Fine with me! BTW I'm really not trying to change the definition of
what a root resource is at all - just providing a way to add new sub
resources on to an existing resource.


> I am currently not too sure about the consequences
> of a sub-resource modifying the relationship to a super resource when jar is
> dropped into the classpath. It could make for harder debugging if more magic
> is involved.

Jersey already detects all the root resources on the classpath in the
packages listed; the only real change would be things annotated with
@Path + @SubResource (or whatever) would not be added as roots, but
added as sub resources of their parent's resource type. Which only
have an effect when folks navigate into the parent resource with a new
previously unsupported additional uri template. i.e. it shouldn't
affect root resources per se - or any existing resource, it will only
affect new URIs folks try to navigate to which match the new sub
resource URI templates


> If the super resource is unaware of the sub-resources that
> could be attached it may make it harder to define application-based
> hypermedia representations on the super resource

Note that this new sub-resource mechanism I'm proposing for style A
would only apply to new child resources with an additional URI
template. So it would not affect in any way the available hypermedia
representations on the parent resource.

If I've not been clear my aim is to make it easier to add new sub
resource (i.e. a totally different resource with a different URI) by
appending a URI template to an existing resource (somewhere in the URI
tree) - such that the new sub resource can reuse any existing resource
bean in the tree (i.e. reuse code that does URI template decomposing
and reuse methods on parent resources and so forth) without having to
start from scratch and write a big new root resource that ends up
copy/pasting lots of the logic and URI template code that already
exists in the available resource bean tree.

As you build trees of resource beans; they tend to do more than just
decompose a URI string; they tend to look up a Customer object, then
an Order; the aim is to be able to create a new resource for an Order
for example in a simple extensible way.

A nice side benefit is that it offers a more DRY and IoC consistent
programming model for root and sub resources (much cleaner than style
B and C).


> (although at runtime the
> relationships will be recognized by the WADL representation returned by the
> super resource).

Folks have to define URIs nicely so this kind of extension is
possible. If the URIs are bad such that they are not extensible this
way, its a bug in the users code not in JAXRS/Jersey :)

Maybe the Camel use case is a bit too wacky for you :)

How about just viewing this as an easier way of providing a consistent
programming model for writing resources and sub resources - using the
same injection mechanism without having to write lots of boiler plate
code to place class C within class B within class A; they can just be
linked by an annotation - no noisy factory methods required or noisy
get methods in parent resources which just return the resource they
are given by the framework etc.

I"m not saying we should disallow style B or C; but style A is the
most DRY and modular.


> I am wondering in such cases that perhaps it might be better to define a
> routes class that provides a global view of the relationships?
>
>  resource(Foo.class, "blah).
>    subResources(resource(Bar.class, "b"), resource(Baz.class, "z"))
>
> kind of hard to wire up graphs nicely using Java though.

Whether there's a little routing DSL or whether we use annotations I
don't mind much; but given JAXRS is all annotation based right now I
figured just adding a new annotation to link new sub resources to a
parent resource was nice and simple.

As an aside many web frameworks in the Scala/Ruby/Groovy worlds have
routing DSLs in them. I actually prefer the annotation approach as its
more modular & simpler.


> What if we could wire up the sub-resource to the super-resource but the path
> is defined on the former? that would at least resolve my concerns about the
> "anything goes" relationship and the path would be defined on the
> sub-resource.
>
> @Path("/whatver")
> @SubResource(BarResource.class)
> class FooResource { }
>
> @SubPath("bar/{id}") // Different annotation so as not to conflict with def
> of root resource
> class BarResource {
>  @PathParam("id") String id;
>  @ResourceRef FooResource parentResource;
>
>  @GET String getBody() {...}
> }
>
> It also means one could define sub-resources on sub-resources.

Sorry thats what I meant; a new sub resource would have the uri
template on its own class. (Using a different annotation @SubPath
instead of @Path is fine by me). Then we can add new sub resources to
any resource at any point in the tree (and add new resources to it etc
etc)

The only difference is where the link between the parent and child
classes goes; on the child or on the parent.
Defining all the available types of sub resources on a parent resource
is less loosely coupled (e.g. you'd need to allow now a collection
rather than 1 class. So I can't copy-paste a sub resource and just
change the Uri template and a few methods; I've got to remember to add
a new sub-resources class to a parent's annotation. Plus it makes
extensibility harder as all of the sub resources now must be in the
same classloader; I can't easily for example add an optional GraphViz
or Excel set of resources to an application using an optional library
folks can use (without deriving from every resource class in each
module just to override one annotation - which only works with 1
optional module, not 2).


Let me turn the question around - why are you worried about being able
to add new sub resources to existing root or sub resources by scanning
the classpath; when its fine to add root resources that way?

After all like you said at the start of your reply, there's nothing to
stop someone adding a pseudo sub resource by just copy and pasting the
correct URI template and just adding a bit more stuff on the end?

One of the great things about JAXRS right now is you can decompose
your resource beans into libraries and then create different web
applications using different combinations of libraries and JAXRS
figures out which resource beans are active by scanning the classpath.
Is extending this behavior to allow new sub resources anywhere in the
tree (with new URis) so bad? Afterall adding them doesn't affect any
of the previous URIs; it just makes some previously 404 responses do
something interesting if you add new libraries to the classpath.

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

Paul Sandoz-2
Hi James,

OK, i have a clearer understanding now. You want to introduce is a new  
type of component that is registered with Application/ResourceConfig  
(how it is registered via scanning or explicitly is not important).  
That component will declare that it is a sub resource of a super  
resource.

The concern i have around hypermedia is the super-resource may not  
know about all the sub-resources such that it can create a  
representation with links/types to those sub-resources. I think this  
concern can be mitigated by a resource being able to inspect the  
model, which would any be better than using Java reflection on  
explicit sub-resource locators.

I believe this feature is certainly possible to implement in addition  
to ensuring the abstract model is correctly up to date without too  
many modifications to existing code. It should also be possible to  
make it work for conventional sub-resources that have those new  
components attached as further sub-resources.

For Aug/Sept i will be mostly tied up sorting out a new client API  
(moving the one in the experimental area to the stable area) and  
JavaOne so i don't have much time to work on this at the moment. The  
@ResourceRef stuff is easy, 1 to 2 hour job at most.


Of late i have become more uncomfortable with the idea of plonking  
jars in place without some form of developer agreement or contract in  
place that describes relationships, because the former can lead to  
very confusing results and class path hell. This is where i was  
suggesting some sort of routes file. But what i really meant was a  
module concept much like that of Guice. Imagine if your Camel app  
defined a JerseyModule and another app can use that module as a parent  
from which it can refer to the components of the parent module. I  
think you may be able to do all the same things you can today with  
annotations but things might be appropriately scoped e.g. for the case  
of a sub-resource declaring the parent resource if there is no  
concrete class of that name in the module or parent then it is a  
binding error. I think this type of thing can also help with the  
inclusion of message body readers/writers e.g. a JAXBModule.  
JerseyModule is kind of like Application/ResourceConfig but with  
inheritance and builder like registration of stuff (that could include  
scanning for registration).

Paul.


On Aug 2, 2010, at 6:26 PM, James Strachan wrote:

> On 2 August 2010 16:11, Paul Sandoz <[hidden email]> wrote:
>> Hi James,
>>
>> AFIAK style A would enable a one-level deep relationship between a  
>> root
>> resource and a sub-resource.
>
> Sorry I wasn't very clear. For style A I was assuming we can add a sub
> resource to any resource; whether its a root or sub resource.
>
>
>> It would enable the developer to add
>> sub-resources to a any root resource if that was intended or  
>> otherwise
>> (although one could devise ways to disallow that).
>>
>> In such a case it would be almost as easy to make the sub-resource  
>> in style
>> A a root resource with @Path("whatever/bar/{id}") if there is no  
>> value in
>> the parent/sub relationship. Some shared behavior could be  
>> inherited from a
>> common base class. The downside in this case is the "whatever" is  
>> repeated.
>
> But imagine a deeply nested tree...
>
> /customers/123/orders/abc/detail
>
> where you've navigated through 4 resources. Then imagine the "detail"
> resource having to basically copy-paste all of those URI templates and
> handle all the path params then probably replicate much of the
> functionality of those resource beans too.
>
> But for a single sub resource when the parent root resource uses a
> simple static uri template when there's not much injection going on
> then you're right, style A only really helps for the injection of sub
> resources.
>
>
>> Do you envisage a use-case where a sub-resource is added to a root  
>> resource
>> without modification to the latter? I guess that is what makes me
>> uncomfortable about style A.
>
> Yes. The idea is to add a sub resource to an existing resource (root
> or sub or subsub etc), without having to change the entire tree of
> resource beans or refactoring them all to shove in some injection
> magic or provide a derived class for each resource etc.
>
> If you own the source code and can add a compile time dependency on
> the new sub resource then style C is an alternative too. Though I
> prefer style A as its more DRY and lets JAXRS web applications be more
> easily extensible. Each web application has an explicit set of
> packages searched; but I can put the same base web app into different
> builds which include new additional sub-resources with style C.
>
>
>> I suppose in Guice one could could modify the bindings such that  
>> BarResource
>> is bound to a specialized implementation, in fact one might qualify  
>> it in
>> this case so BarResource is reusable in other contexts:
>>
>> @Path("/whatver")
>> class FooResource {
>>  @SubOfFoo @Inject Provider<BarResource> bar;
>>
>>  @Path("bar/{id}")
>>  public BarResource getBar() { // Should try and add support for  
>> 330 @Inject
>> for parameters
>>   return bar.get();
>>  }
>> }
>>
>> Thus specialization is possible without loosing the clear  
>> definition of
>> sub-resources, and specialization is clearly defined according to  
>> Guice
>> bindings. Although the above bugs me that there is a dissociation  
>> between
>> the path parameter, "id", and BarResource.
>
> Yeah.
>
> It also requires that all parent resources are written with
> extensibility in mind. You can't just add a new sub-resource anywhere
> in the tree of resources. Look how much noise we've just added for one
> level of resource depth; imagine 4 or 5 resources deep & how much pain
> there is :)
>
>
>> One way to solve this would be to allow the intermixing of injected  
>> and
>> passed parameters a bit like Guice's assisted inject, but i cannot  
>> come up
>> with an appropriately typed and easy solution to that problem  
>> independent of
>> Guice, and Guice still requires the creation of a factory interface
>>
>> @Path("/whatever")
>> class FooResource {
>>  @Inject BarResourceFactory bar;
>>
>>  @Path("bar/{id}")
>>  public BarResource getBar(@PathParam("id") String id) {
>>   return bar.create(id);
>>  }
>> }
>>
>> interface BarResourceFactory {
>>  public BarResource.create(String id);
>> }
>>
>> class BarResource {
>>  @Inject
>>  BarResource(@Inject FooResource foo, @Assisted String id) { ... }
>> }
>>
>> This is frustrating, i feel we are missing a language feature here  
>> that
>> could really help.
>
> Yeah - its kinda verbose though having to shove factories everywhere
> which only really help the framework implementation; they are just
> noise to the application programmer :)
>
>
>> It is certainly easy to implement support for @ResourceRef (and say
>> @SuperResourceRef to validate a parent of a certain type) as we  
>> already that
>> support for that in a slightly different way.
>>
>> Style A would be a little harder. Having @SubResource("bar/{id}",
>> BarResource.class) would be easier because we don't change the  
>> definition of
>> what a root resource is.
>
> Fine with me! BTW I'm really not trying to change the definition of
> what a root resource is at all - just providing a way to add new sub
> resources on to an existing resource.
>
>
>> I am currently not too sure about the consequences
>> of a sub-resource modifying the relationship to a super resource  
>> when jar is
>> dropped into the classpath. It could make for harder debugging if  
>> more magic
>> is involved.
>
> Jersey already detects all the root resources on the classpath in the
> packages listed; the only real change would be things annotated with
> @Path + @SubResource (or whatever) would not be added as roots, but
> added as sub resources of their parent's resource type. Which only
> have an effect when folks navigate into the parent resource with a new
> previously unsupported additional uri template. i.e. it shouldn't
> affect root resources per se - or any existing resource, it will only
> affect new URIs folks try to navigate to which match the new sub
> resource URI templates
>
>
>> If the super resource is unaware of the sub-resources that
>> could be attached it may make it harder to define application-based
>> hypermedia representations on the super resource
>
> Note that this new sub-resource mechanism I'm proposing for style A
> would only apply to new child resources with an additional URI
> template. So it would not affect in any way the available hypermedia
> representations on the parent resource.
>
> If I've not been clear my aim is to make it easier to add new sub
> resource (i.e. a totally different resource with a different URI) by
> appending a URI template to an existing resource (somewhere in the URI
> tree) - such that the new sub resource can reuse any existing resource
> bean in the tree (i.e. reuse code that does URI template decomposing
> and reuse methods on parent resources and so forth) without having to
> start from scratch and write a big new root resource that ends up
> copy/pasting lots of the logic and URI template code that already
> exists in the available resource bean tree.
>
> As you build trees of resource beans; they tend to do more than just
> decompose a URI string; they tend to look up a Customer object, then
> an Order; the aim is to be able to create a new resource for an Order
> for example in a simple extensible way.
>
> A nice side benefit is that it offers a more DRY and IoC consistent
> programming model for root and sub resources (much cleaner than style
> B and C).
>
>
>> (although at runtime the
>> relationships will be recognized by the WADL representation  
>> returned by the
>> super resource).
>
> Folks have to define URIs nicely so this kind of extension is
> possible. If the URIs are bad such that they are not extensible this
> way, its a bug in the users code not in JAXRS/Jersey :)
>
> Maybe the Camel use case is a bit too wacky for you :)
>
> How about just viewing this as an easier way of providing a consistent
> programming model for writing resources and sub resources - using the
> same injection mechanism without having to write lots of boiler plate
> code to place class C within class B within class A; they can just be
> linked by an annotation - no noisy factory methods required or noisy
> get methods in parent resources which just return the resource they
> are given by the framework etc.
>
> I"m not saying we should disallow style B or C; but style A is the
> most DRY and modular.
>
>
>> I am wondering in such cases that perhaps it might be better to  
>> define a
>> routes class that provides a global view of the relationships?
>>
>>  resource(Foo.class, "blah).
>>    subResources(resource(Bar.class, "b"), resource(Baz.class, "z"))
>>
>> kind of hard to wire up graphs nicely using Java though.
>
> Whether there's a little routing DSL or whether we use annotations I
> don't mind much; but given JAXRS is all annotation based right now I
> figured just adding a new annotation to link new sub resources to a
> parent resource was nice and simple.
>
> As an aside many web frameworks in the Scala/Ruby/Groovy worlds have
> routing DSLs in them. I actually prefer the annotation approach as its
> more modular & simpler.
>
>
>> What if we could wire up the sub-resource to the super-resource but  
>> the path
>> is defined on the former? that would at least resolve my concerns  
>> about the
>> "anything goes" relationship and the path would be defined on the
>> sub-resource.
>>
>> @Path("/whatver")
>> @SubResource(BarResource.class)
>> class FooResource { }
>>
>> @SubPath("bar/{id}") // Different annotation so as not to conflict  
>> with def
>> of root resource
>> class BarResource {
>>  @PathParam("id") String id;
>>  @ResourceRef FooResource parentResource;
>>
>>  @GET String getBody() {...}
>> }
>>
>> It also means one could define sub-resources on sub-resources.
>
> Sorry thats what I meant; a new sub resource would have the uri
> template on its own class. (Using a different annotation @SubPath
> instead of @Path is fine by me). Then we can add new sub resources to
> any resource at any point in the tree (and add new resources to it etc
> etc)
>
> The only difference is where the link between the parent and child
> classes goes; on the child or on the parent.
> Defining all the available types of sub resources on a parent resource
> is less loosely coupled (e.g. you'd need to allow now a collection
> rather than 1 class. So I can't copy-paste a sub resource and just
> change the Uri template and a few methods; I've got to remember to add
> a new sub-resources class to a parent's annotation. Plus it makes
> extensibility harder as all of the sub resources now must be in the
> same classloader; I can't easily for example add an optional GraphViz
> or Excel set of resources to an application using an optional library
> folks can use (without deriving from every resource class in each
> module just to override one annotation - which only works with 1
> optional module, not 2).
>
>
> Let me turn the question around - why are you worried about being able
> to add new sub resources to existing root or sub resources by scanning
> the classpath; when its fine to add root resources that way?
>
> After all like you said at the start of your reply, there's nothing to
> stop someone adding a pseudo sub resource by just copy and pasting the
> correct URI template and just adding a bit more stuff on the end?
>
> One of the great things about JAXRS right now is you can decompose
> your resource beans into libraries and then create different web
> applications using different combinations of libraries and JAXRS
> figures out which resource beans are active by scanning the classpath.
> Is extending this behavior to allow new sub resources anywhere in the
> tree (with new URis) so bad? Afterall adding them doesn't affect any
> of the previous URIs; it just makes some previously 404 responses do
> something interesting if you add new libraries to the classpath.
>
> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
On 3 August 2010 09:07, Paul Sandoz <[hidden email]> wrote:

> Hi James,
>
> OK, i have a clearer understanding now. You want to introduce is a new type
> of component that is registered with Application/ResourceConfig (how it is
> registered via scanning or explicitly is not important). That component will
> declare that it is a sub resource of a super resource.
>
> The concern i have around hypermedia is the super-resource may not know
> about all the sub-resources such that it can create a representation with
> links/types to those sub-resources. I think this concern can be mitigated by
> a resource being able to inspect the model, which would any be better than
> using Java reflection on explicit sub-resource locators.

Great!


> I believe this feature is certainly possible to implement in addition to
> ensuring the abstract model is correctly up to date without too many
> modifications to existing code. It should also be possible to make it work
> for conventional sub-resources that have those new components attached as
> further sub-resources.

Great!


> For Aug/Sept i will be mostly tied up sorting out a new client API (moving
> the one in the experimental area to the stable area) and JavaOne so i don't
> have much time to work on this at the moment. The @ResourceRef stuff is
> easy, 1 to 2 hour job at most.

Any chance of sneaking in the @ResourceRef in the mean time then? :)


> Of late i have become more uncomfortable with the idea of plonking jars in
> place without some form of developer agreement or contract in place that
> describes relationships, because the former can lead to very confusing
> results and class path hell.

Maybe more introspection tools might help; e.g. a little tool to
display a nice diagram or tree of the resources. I guess this is just
transforming the WADL into visual representations so folks can see
what resources are at what URI template and which jar they come from
etc..

I've worked on a number of web apps using various JAXRS resources from
different packages and to be fair Jersey already does a pretty good
job of listing what resources its using from what packages etc.


> This is where i was suggesting some sort of
> routes file. But what i really meant was a module concept much like that of
> Guice. Imagine if your Camel app defined a JerseyModule and another app can
> use that module as a parent from which it can refer to the components of the
> parent module. I think you may be able to do all the same things you can
> today with annotations but things might be appropriately scoped e.g. for the
> case of a sub-resource declaring the parent resource if there is no concrete
> class of that name in the module or parent then it is a binding error.

Though the sub resources would be linked using the class loader to the
parent resource's class (or a ClassNotFoundException would occur). So
even though we're using annotations to do the linking, its a form of
typesafe module that works across class loader boundaries.


> I
> think this type of thing can also help with the inclusion of message body
> readers/writers e.g. a JAXBModule. JerseyModule is kind of like
> Application/ResourceConfig but with inheritance and builder like
> registration of stuff (that could include scanning for registration).

Agreed. We have a kinda module thing in the
META-INF/services/jersey-server-components file - in that you can
inspect the jars to see the packages which are jersey 'modules' of
sorts. But maybe a module system a-la Guice is simpler.

e.g. I always find those zillions of init-param with long
com.sun.jersey.whatnot names feel a bit smelly in a web.xml. It just
feels like those properties should be closer to the JAXRS stuff. For
example you need intimate knowledge of how each 'module' of jaxrs
resources work before you know how you can configure your global
web.xml with the ton of Jersey properties.

So maybe a little Jersey module class with simple bean properties
would be simpler. As an aside when using Scalate and Guice I tend to
use this helper Guice module to initialize Jersey (and the Scalate
templates) using guice-servlet - so Jersey itself is configured in the
IoC container (and I can hide all those long property strings)...

http://github.com/scalate/scalate/blob/master/scalate-guice/src/main/scala/org/fusesource/scalate/guice/ScalateModule.scala


So maybe we could introduce a simple JerseyModule class which
describes the properties & packages (or classes) of resources and
components; then allow it to be specified in a
META-INF/services/jersey-module file. Then its much easier to
introspect which modules are visible on the classloader and introspect
them in a more meaningful way - than just raw package scanning? It
could maybe open the door for different jersey configurations for
different modules. (e.g. tracing and implicit views on for some
modules but off for others or something like that). Maybe a module
could then explicitly depend on another module (to allow the new
sub-resources of other resources type feature?).

It would be nice if you just registered the Jersey filter in web.xml;
then Jersey found the available modules (or you list them explicitly
maybe) and those modules figured out what configurations to use for
Jersey - rather than a global configuration of Jersey in the web.xml -
when the modules probably know more about how Jersey needs to be
configured than the web.xml editor.

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

Paul Sandoz-2

On Aug 3, 2010, at 10:33 AM, James Strachan wrote:

> On 3 August 2010 09:07, Paul Sandoz <[hidden email]> wrote:
>> Hi James,
>>
>> OK, i have a clearer understanding now. You want to introduce is a  
>> new type
>> of component that is registered with Application/ResourceConfig  
>> (how it is
>> registered via scanning or explicitly is not important). That  
>> component will
>> declare that it is a sub resource of a super resource.
>>
>> The concern i have around hypermedia is the super-resource may not  
>> know
>> about all the sub-resources such that it can create a  
>> representation with
>> links/types to those sub-resources. I think this concern can be  
>> mitigated by
>> a resource being able to inspect the model, which would any be  
>> better than
>> using Java reflection on explicit sub-resource locators.
>
> Great!
>
>
>> I believe this feature is certainly possible to implement in  
>> addition to
>> ensuring the abstract model is correctly up to date without too many
>> modifications to existing code. It should also be possible to make  
>> it work
>> for conventional sub-resources that have those new components  
>> attached as
>> further sub-resources.
>
> Great!
>
>
>> For Aug/Sept i will be mostly tied up sorting out a new client API  
>> (moving
>> the one in the experimental area to the stable area) and JavaOne so  
>> i don't
>> have much time to work on this at the moment. The @ResourceRef  
>> stuff is
>> easy, 1 to 2 hour job at most.
>
> Any chance of sneaking in the @ResourceRef in the mean time then? :)
>

I will try and get in done this week, about to travel to Prague for 3  
days to meet up with other Jersey team members so lots of  
distractions :-) plus a deadline by the 6th of Aug for JavaOne presos  
was imposed on us :-(


>
>> Of late i have become more uncomfortable with the idea of plonking  
>> jars in
>> place without some form of developer agreement or contract in place  
>> that
>> describes relationships, because the former can lead to very  
>> confusing
>> results and class path hell.
>
> Maybe more introspection tools might help; e.g. a little tool to
> display a nice diagram or tree of the resources. I guess this is just
> transforming the WADL into visual representations so folks can see
> what resources are at what URI template and which jar they come from
> etc..
>
> I've worked on a number of web apps using various JAXRS resources from
> different packages and to be fair Jersey already does a pretty good
> job of listing what resources its using from what packages etc.
>

OK.


>
>> This is where i was suggesting some sort of
>> routes file. But what i really meant was a module concept much like  
>> that of
>> Guice. Imagine if your Camel app defined a JerseyModule and another  
>> app can
>> use that module as a parent from which it can refer to the  
>> components of the
>> parent module. I think you may be able to do all the same things  
>> you can
>> today with annotations but things might be appropriately scoped  
>> e.g. for the
>> case of a sub-resource declaring the parent resource if there is no  
>> concrete
>> class of that name in the module or parent then it is a binding  
>> error.
>
> Though the sub resources would be linked using the class loader to the
> parent resource's class (or a ClassNotFoundException would occur). So
> even though we're using annotations to do the linking, its a form of
> typesafe module that works across class loader boundaries.
>

But there is really only one class loader for a Web app. I suppose it  
is different if using OSGi or Camel?


>
>> I
>> think this type of thing can also help with the inclusion of  
>> message body
>> readers/writers e.g. a JAXBModule. JerseyModule is kind of like
>> Application/ResourceConfig but with inheritance and builder like
>> registration of stuff (that could include scanning for registration).
>
> Agreed. We have a kinda module thing in the
> META-INF/services/jersey-server-components file - in that you can
> inspect the jars to see the packages which are jersey 'modules' of
> sorts. But maybe a module system a-la Guice is simpler.
>
> e.g. I always find those zillions of init-param with long
> com.sun.jersey.whatnot names feel a bit smelly in a web.xml. It just
> feels like those properties should be closer to the JAXRS stuff. For
> example you need intimate knowledge of how each 'module' of jaxrs
> resources work before you know how you can configure your global
> web.xml with the ton of Jersey properties.
>
> So maybe a little Jersey module class with simple bean properties
> would be simpler. As an aside when using Scalate and Guice I tend to
> use this helper Guice module to initialize Jersey (and the Scalate
> templates) using guice-servlet - so Jersey itself is configured in the
> IoC container (and I can hide all those long property strings)...
>
> http://github.com/scalate/scalate/blob/master/scalate-guice/src/main/scala/org/fusesource/scalate/guice/ScalateModule.scala
>
>
> So maybe we could introduce a simple JerseyModule class which
> describes the properties & packages (or classes) of resources and
> components; then allow it to be specified in a
> META-INF/services/jersey-module file. Then its much easier to
> introspect which modules are visible on the classloader and introspect
> them in a more meaningful way - than just raw package scanning? It
> could maybe open the door for different jersey configurations for
> different modules. (e.g. tracing and implicit views on for some
> modules but off for others or something like that). Maybe a module
> could then explicitly depend on another module (to allow the new
> sub-resources of other resources type feature?).
>
> It would be nice if you just registered the Jersey filter in web.xml;
> then Jersey found the available modules (or you list them explicitly
> maybe) and those modules figured out what configurations to use for
> Jersey - rather than a global configuration of Jersey in the web.xml -
> when the modules probably know more about how Jersey needs to be
> configured than the web.xml editor.
>

Yes, the idea would be to replace all the specific META-INF/services  
files in a jar with at most just one that defines the module. I dunno  
how we can remove it all together. I suppose a manifest header might  
also work but that is harder for developers to register.

Jersey could supply a default module for all the message body readers/
writers, composed into meaningful sets, but a developer could define  
their own and compose from in the sets in addition to their own stuff,  
say if they want to use Jackson and not get interference with JAXB (we  
added a specific feature to a JSON support to avoid this conflict).

I like the idea of having providers scoped to a module.

This is definitely something i want to do for a Jersey 2.0 effort.

Paul.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: injecting @Context fields on sub resources...

jstrachan
On 3 August 2010 10:21, Paul Sandoz <[hidden email]> wrote:

>
> On Aug 3, 2010, at 10:33 AM, James Strachan wrote:
>
>> On 3 August 2010 09:07, Paul Sandoz <[hidden email]> wrote:
>>>
>>> Hi James,
>>>
>>> OK, i have a clearer understanding now. You want to introduce is a new
>>> type
>>> of component that is registered with Application/ResourceConfig (how it
>>> is
>>> registered via scanning or explicitly is not important). That component
>>> will
>>> declare that it is a sub resource of a super resource.
>>>
>>> The concern i have around hypermedia is the super-resource may not know
>>> about all the sub-resources such that it can create a representation with
>>> links/types to those sub-resources. I think this concern can be mitigated
>>> by
>>> a resource being able to inspect the model, which would any be better
>>> than
>>> using Java reflection on explicit sub-resource locators.
>>
>> Great!
>>
>>
>>> I believe this feature is certainly possible to implement in addition to
>>> ensuring the abstract model is correctly up to date without too many
>>> modifications to existing code. It should also be possible to make it
>>> work
>>> for conventional sub-resources that have those new components attached as
>>> further sub-resources.
>>
>> Great!
>>
>>
>>> For Aug/Sept i will be mostly tied up sorting out a new client API
>>> (moving
>>> the one in the experimental area to the stable area) and JavaOne so i
>>> don't
>>> have much time to work on this at the moment. The @ResourceRef stuff is
>>> easy, 1 to 2 hour job at most.
>>
>> Any chance of sneaking in the @ResourceRef in the mean time then? :)
>>
>
> I will try and get in done this week, about to travel to Prague for 3 days
> to meet up with other Jersey team members so lots of distractions :-) plus a
> deadline by the 6th of Aug for JavaOne presos was imposed on us :-(

No worries :). But a style C would be a good workaround for now; so we
can at least use the same injection model with root and sub resources.


>>> This is where i was suggesting some sort of
>>> routes file. But what i really meant was a module concept much like that
>>> of
>>> Guice. Imagine if your Camel app defined a JerseyModule and another app
>>> can
>>> use that module as a parent from which it can refer to the components of
>>> the
>>> parent module. I think you may be able to do all the same things you can
>>> today with annotations but things might be appropriately scoped e.g. for
>>> the
>>> case of a sub-resource declaring the parent resource if there is no
>>> concrete
>>> class of that name in the module or parent then it is a binding error.
>>
>> Though the sub resources would be linked using the class loader to the
>> parent resource's class (or a ClassNotFoundException would occur). So
>> even though we're using annotations to do the linking, its a form of
>> typesafe module that works across class loader boundaries.
>>
>
> But there is really only one class loader for a Web app. I suppose it is
> different if using OSGi or Camel?

Sorry; not enough coffee yet (and am about to delve into the horrid
OSGi world shortly). I meant across jar boundaries in a web-app
(though it would be class loader boundaries in OSGi).


>>> I
>>> think this type of thing can also help with the inclusion of message body
>>> readers/writers e.g. a JAXBModule. JerseyModule is kind of like
>>> Application/ResourceConfig but with inheritance and builder like
>>> registration of stuff (that could include scanning for registration).
>>
>> Agreed. We have a kinda module thing in the
>> META-INF/services/jersey-server-components file - in that you can
>> inspect the jars to see the packages which are jersey 'modules' of
>> sorts. But maybe a module system a-la Guice is simpler.
>>
>> e.g. I always find those zillions of init-param with long
>> com.sun.jersey.whatnot names feel a bit smelly in a web.xml. It just
>> feels like those properties should be closer to the JAXRS stuff. For
>> example you need intimate knowledge of how each 'module' of jaxrs
>> resources work before you know how you can configure your global
>> web.xml with the ton of Jersey properties.
>>
>> So maybe a little Jersey module class with simple bean properties
>> would be simpler. As an aside when using Scalate and Guice I tend to
>> use this helper Guice module to initialize Jersey (and the Scalate
>> templates) using guice-servlet - so Jersey itself is configured in the
>> IoC container (and I can hide all those long property strings)...
>>
>>
>> http://github.com/scalate/scalate/blob/master/scalate-guice/src/main/scala/org/fusesource/scalate/guice/ScalateModule.scala
>>
>>
>> So maybe we could introduce a simple JerseyModule class which
>> describes the properties & packages (or classes) of resources and
>> components; then allow it to be specified in a
>> META-INF/services/jersey-module file. Then its much easier to
>> introspect which modules are visible on the classloader and introspect
>> them in a more meaningful way - than just raw package scanning? It
>> could maybe open the door for different jersey configurations for
>> different modules. (e.g. tracing and implicit views on for some
>> modules but off for others or something like that). Maybe a module
>> could then explicitly depend on another module (to allow the new
>> sub-resources of other resources type feature?).
>>
>> It would be nice if you just registered the Jersey filter in web.xml;
>> then Jersey found the available modules (or you list them explicitly
>> maybe) and those modules figured out what configurations to use for
>> Jersey - rather than a global configuration of Jersey in the web.xml -
>> when the modules probably know more about how Jersey needs to be
>> configured than the web.xml editor.
>>
>
> Yes, the idea would be to replace all the specific META-INF/services files
> in a jar with at most just one that defines the module. I dunno how we can
> remove it all together. I suppose a manifest header might also work but that
> is harder for developers to register.
>
> Jersey could supply a default module for all the message body
> readers/writers, composed into meaningful sets, but a developer could define
> their own and compose from in the sets in addition to their own stuff, say
> if they want to use Jackson and not get interference with JAXB (we added a
> specific feature to a JSON support to avoid this conflict).
>
> I like the idea of having providers scoped to a module.
>
> This is definitely something i want to do for a Jersey 2.0 effort.

Cool.

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]