Hi Paul,
Thanks for revisiting this post.
As per my understanding, @Singleton enforces that there can be only one
instance of this resource in the web application context. So, I added
this annotation to my resource so multiple instances do not get created
for each client request.
Let me explain my use case briefly so that you can correct me if I am
doing something fundamentally wrong.
We have defined a set of backend REST APIs which works on our model
(list/create/delete/update). The web application front end is the
primary consumer of this REST API. The web application and RESTful
resources are deployed into Jersey as a WAR.
In addition to performing CRUD operations, the web application also
operates on each model (for ex: if the model is secure, it can perform
login/logout on the model). The users can select the model they wish to
operate and the model will be set in session for that user until they
decide to choose a different model to work with. At application startup,
we need to select a default model and set it in session so that the user
can use this default model at first access. This is where my requirement
comes into picture. When I start my resources, I need to somehow set the
default model in session if there is one so that the user is presented
with this default model.
So, I try to set this in the constructor by injecting a HTTP servlet
request and fetch the session from the request as shown below which
seems to be an illegal scenario.
@Singleton
public static class ModelResource {
@Context
HttpServletRequest r;
public ModelResource(@Context HttpServletRequest req) {
req.getSession().setAttribute("currentmodel", "defaultmodel");
}
@Produces("text/plain")
@GET
public String get() {
return (String) r.getAttribute("currentmodel");
}
}
I appreciate your inputs.
-Arul
Paul Sandoz wrote:
> Hi Arul,
>
> I realized there is something wrong with the way you are doing things
> in that you assume a singleton instance is associated with a session.
> This will not be the case for multiple clients, thus your service is
> likely to fail in that case.
>
> So... i have given up resisting providing life-cycle support for HTTP
> servlet sessions, and have implemented such support with a new
> annotation:
>
> com.sun.jersey.spi.container.servlet.PerSession
>
> And you can use it like this:
>
> @Path("resource")
> @PerSession
> public class Resource {
> int i = 0;
>
> @GET
> public String get() {
> i++;
> return "" + i;
> }
> }
>
> Instances are stored as attributes on the session using the class name
> as the key. It requires that you are using a servlet as the HTTP
> container.
>
> Use it wisely with the knowledge that you are breaking an important
> RESTful constraint [1].
>
> Paul.
>
> [1] http://www.crummy.com/2008/08/19/2
>
> Arul Dhesiaseelan wrote:
>> Hi Paul,
>>
>> I am still having issue with constructor injection in singleton
>> resources in Jersey 0.9. If I comment SingletonConstructorResource in
>> the below code, I can run other 3 scenarios just fine which was
>> working fine in 0.8 too. If I uncomment SingletonConstructorResource,
>> then none of the scenarios work in 0.9. Am I missing something? I
>> remember you had fixed this issue earlier.
>>
>> I am getting the following exception when trying to invoke any of the
>> resources:
>>
>> com.sun.jersey.api.container.ContainerException: Unable to create
>> resource
>> at
>> com.sun.jersey.impl.resource.SingletonProvider.init(SingletonProvider.java:88)
>>
>> at
>> com.sun.jersey.spi.resource.ResourceProviderFactory.createProvider(ResourceProviderFactory.java:132)
>>
>> at
>> com.sun.jersey.impl.model.ResourceClass.init(ResourceClass.java:180)
>> at
>> com.sun.jersey.impl.application.WebApplicationImpl.getResourceClass(WebApplicationImpl.java:267)
>>
>> at
>> com.sun.jersey.impl.application.WebApplicationImpl.processRootResources(WebApplicationImpl.java:796)
>>
>> at
>> com.sun.jersey.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:668)
>>
>> at
>> com.sun.jersey.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:485)
>>
>> at
>> com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:559)
>>
>> at
>> com.sun.jersey.spi.container.servlet.ServletContainer.load(ServletContainer.java:483)
>>
>> at
>> com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:165)
>>
>> at
>> org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:433)
>>
>> at
>> org.mortbay.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:342)
>>
>> at
>> org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:463)
>> at
>> org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
>> at
>> org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
>> at
>> org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
>> at
>> org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
>> at org.mortbay.jetty.Server.handle(Server.java:324)
>> at
>> org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
>> at
>> org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
>>
>> at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
>> at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
>> at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
>> at
>> org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
>>
>> at
>> org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
>>
>> Caused by: java.lang.reflect.InvocationTargetException
>> at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
>> Method)
>> at
>> sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
>>
>> at
>> sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
>>
>> at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
>> at
>> com.sun.jersey.impl.application.WebApplicationImpl$DefaultResourceComponentProvider.getInstance(WebApplicationImpl.java:465)
>>
>> at
>> com.sun.jersey.impl.resource.SingletonProvider.init(SingletonProvider.java:84)
>>
>> ... 24 more
>> Caused by: java.lang.NullPointerException
>> at jersey.Inject$SingletonConstructorResource.(Inject.java:42)
>> ... 30 more
>>
>>
>>
>>
>> public class Inject {
>> @Path("singleton")
>> @Singleton
>> public static class SingletonResource {
>> @Context
>> HttpServletRequest r;
>>
>> @Produces("text/plain")
>> @GET
>> public String get() {
>> return r.getPathInfo();
>> }
>> }
>>
>> // @Path("singleton/constructor")
>> // @Singleton
>> // public static class SingletonConstructorResource {
>> // @Context HttpServletRequest r;
>> //
>> // public SingletonConstructorResource(@Context
>> HttpServletRequest r) {
>> // this.r = r;
>> // r.getSession().setAttribute("test", "true");
>> // }
>> //
>> // @Produces("text/plain")
>> // @GET public String get() {
>> // return (String)r.getAttribute("test");
>> // }
>> // }
>>
>> @Path("perrequest")
>> public static class PerRequestResource {
>> @Context
>> HttpServletRequest r;
>>
>> @Produces("text/plain")
>> @GET
>> public String get() {
>> return r.getPathInfo();
>> }
>> }
>>
>> @Path("perrequest/constructor")
>> public static class PerRequestConstructorResource {
>> String path;
>>
>> public PerRequestConstructorResource(@Context HttpServletRequest r) {
>> path = r.getPathInfo();
>> }
>>
>> @Produces("text/plain")
>> @GET
>> public String get() {
>> return path;
>> }
>> }
>>
>> public static void main(String[] args) throws Exception {
>> ServletHolder sh = new ServletHolder(ServletContainer.class);
>> sh.setInitParameter("com.sun.jersey.config.property.packages",
>> "jersey");
>> Server server = new Server(9999);
>> org.mortbay.jetty.servlet.Context context = new
>> org.mortbay.jetty.servlet.Context(server, "/",
>> org.mortbay.jetty.servlet.Context.SESSIONS);
>> context.addServlet(sh, "/*");
>> server.start();
>> }
>>
>> }
>>
>> Thanks!
>> Arul
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>