users@jersey.java.net

Re: Returning a class from a sub-locator

From: Martin Grotzke <martin.grotzke_at_javakaffee.de>
Date: Tue, 19 Feb 2008 19:10:52 +0100

Ok, thanx a lot for this example!

Cheers,
Martin


On Tue, 2008-02-19 at 15:32 +0100, Paul Sandoz wrote:
> Hi Martin,
>
> Martin Grotzke wrote:
> > being able to return a class sounds really great!
> >
> > Though, in our case we have something like a resource (Items) with path
> > "/items" and another resource (Item) with path "{itemId}". In the Item
> > resource we need access to the path parameter "itemId".
> >
>
> See end of email for an example taken from the unit tests, you can use
> @PathParam, but it does require that the class returned is implicitly
> aware of the template name "itemId" used by the parent.
>
> This is why i think it would also be nice to use the ComponentProvider
> iface to pass in the constructor parameters for per-request life-cycle
> resources. For example:
>
> @Context ComponentProvider cp;
>
> @Path("{itemId}")
> public Class<?> getItem(@PathParam("itemId") String id) {
> Object[] params = new Object[1];
> params[0] = id;
> return cp.getInstance(ItemResource.class, params);
> // Hmmm should change Object[] params to Object... params
> // then it could be:
> // return cp.getInstance(ItemResource.class, id);
> }
>
> or:
>
> @Context ComponentProvider cp;
>
> @Path("{itemId}")
> public Class<?> getItem(@PathParam("itemId") String id) {
> Object r = new ItemResource(id);
> cp.inject(r);
> return r;
> }
>
>
> > Is there any way to retrieve the value of "itemId" within Item if it is
> > instantiated by an ioc-container like spring?
> >
>
> Yes, as shown below.
>
>
> > Btw: I'm just starting with jsr311/jersey and like it very much -
> > congrats and thx a lot!
> >
>
> Thanks for the kind words,
> Paul.
>
> @Path("/{p}")
> static public class ParentWithTemplatesLifecycle {
> @GET
> public String getMe(@PathParam("p") String p) {
> return p;
> }
>
> @Path("child/{c}")
> public Class<ChildWithTemplatesPerRequest>
> getChildWithTemplates() {
> return ChildWithTemplatesPerRequest.class;
> }
>
> @Path("child/singleton/{c}")
> public Class<ChildWithTemplatesSingleton>
> getChildWithTemplatesSingleton() {
> return ChildWithTemplatesSingleton.class;
> }
> }
>
> static public class ChildWithTemplatesPerRequest {
> private int i = 0;
> private String c;
>
> public ChildWithTemplatesPerRequest(@PathParam("c") String c) {
> this.c = c;
> }
>
> @GET
> public String getMe() {
> i++;
> return c + i;
> }
> }
>
> @Singleton
> static public class ChildWithTemplatesSingleton {
> private int i = 0;
>
> @GET
> public String getMe(@PathParam("c") String c) {
> i++;
> return c + i;
> }
> }
>
>
> >
> > On Tue, 2008-02-19 at 12:24 +0100, Paul Sandoz wrote:
> >> Hi,
> >>
> >> One of the major pain points i have observed from developers is that
> >> sub-locators return objects and it is necessary to manually pass
> >> contextual information injected on the root resource classes to
> >> resources instantiated and returned by sub-locators.
> >>
> >> I have modified things in the trunk so that it is possible for a
> >> sub-locator to return a Class. For example:
> >>
> >> @Path("/parent")
> >> static public class Parent {
> >> @GET
> >> public String getMe() {
> >> return "parent";
> >> }
> >>
> >> @Path("child")
> >> public Class<Child> getChild() {
> >> return Child.class;
> >> }
> >> }
> >>
> >> static public class Child {
> >> @GET
> >> public String getMe() {
> >> return "child";
> >> }
> >> }
> >>
> >> The standard life-cycle mechanisms (singleton or per-request) should all
> >> work as before and Jersey will defer to a component provider for
> >> instantiating the returned class. So it should be much easier to work
> >> with Spring.
> >>
> >>
> >> Another fix i am considering is allowing injection of ComponentProvider:
> >>
> >> @Path("/parent")
> >> static public class Parent {
> >> @Context ComponentProvider cp;
> >>
> >> @GET
> >> public String getMe() {
> >> return "parent";
> >> }
> >>
> >> @Path("child")
> >> public Child getChild() {
> >> Child c = new Child();
> >> // Spring does not support this :-(
> >> cp.inject(c);
> >> return c;
> >> }
> >> }
> >>
> >> @Path("/parent")
> >> static public class Parent {
> >> @Context ComponentProvider cp;
> >>
> >> @GET
> >> public String getMe() {
> >> return "parent";
> >> }
> >>
> >> @Path("child")
> >> public Child getChild() {
> >> return cp.getInstance(c);
> >> }
> >> }
> >>
> >> which allows the application to have some extra control over the
> >> instance before it is returned. Is this something people would find useful?
> >>
> >> Thanks,
> >> Paul.
> >>
>