Reputation: 384
I want to initialize a Jersey Rest service and introduce a global application-wide variable which should be calculated at application start up-time and should be available in each rest resource and each method (here indicated by the integer globalAppValue=17, but will be a complex object later).
In order to initialize the service and calculate the value once at start up I found two practices: The general ServletContextListener and the Jersey ResourceConfig method. But I have not understood what is the difference between both of them? Both methods fire at start up (both System.out-messages are printed).
Here is the implementation of my ServletContextListener which works fine:
public class LoadConfigurationListener implements ServletContextListener
{
private int globalAppValue = 17;
@Override
public void contextDestroyed (ServletContextEvent event)
{
}
@Override
public void contextInitialized (ServletContextEvent event)
{
System.out.println ("ServletContext init.");
ServletContext context = event.getServletContext ();
context.setAttribute ("globalAppValue", globalAppValue);
}
}
And this is the implementation of the Jersey Rest ResourceConfig-method in which the ServletContext is not available. Neither is this Application-object later availabe by injection with the resource-methods:
@ApplicationPath("Resources")
public class MyApplication extends ResourceConfig
{
@Context
ServletContext context;
private int globalAppValue = 17;
public MyApplication () throws NamingException
{
System.out.println ("Application init.");
// returns NullPointerException since ServletContext is not injected
context.setAttribute ("globalAppValue", 17);
}
public int getAppValue ()
{
return globalAppValue;
}
}
This is the way I would like to gain access in the resource methods to the global value:
@Path("/")
public class TestResource
{
@Context
ServletContext context;
@Context
MyApplication application;
@Path("/test")
@GET
public String sayHello () throws SQLException
{
String result = "Hello World: ";
// returns NullPointerException since application is not injected
result += "globalAppValue=" + application.getAppValue ();
// works!
result += "contextValue=" + context.getAttribute ("globalAppValue");
return result;
}
}
So while the classic ServletContextListener works fine I got several problems to use the ResourceConfig/Application, but would prefer this way because it seems to integrate more natively into Jersey. So my question is which way would be the best practice to use. Thanks!
Upvotes: 5
Views: 5075
Reputation: 384
no sory, this produces "value=null" as an output if GET /test/ is called.
package rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
@Path("/test")
public class TestResource
{
@Context
Application application;
@GET
public String sayHello ()
{
String result = "value=" + application.getProperties ().get ("value");
return result;
}
}
ApplicationPath set here to "resources" ?
package rest;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
@ApplicationPath("resources")
public class MyApplication extends ResourceConfig
{
public MyApplication ()
{
property ("value", 17);
System.out.println (getProperties ());
}
}
EDIT: For those who followed our discussion, the solution/problem is as follows. With the servlet deployment part of my web.xml, first I wrote wrongly
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
After having deleted the * and changed the url-pattern to <url-pattern>/</url-pattern>
(without *) and respectively changing
@ApplicationPath("/")
public class MyApplication extends ResourceConfig
it finally worked out. So the ApplicationPath must be the same as in the Servlet-Url in the web.xml in order to have the injection in the method class correctly done.
Upvotes: 0
Reputation: 209052
You could just set a property in the ResourceConfig
by just calling property( key, value )
.
public MyApplication() {
property("MyProp", "MyValue");
}
In your resource class, your are only allowed to inject the super abstract class javax.ws.rs.core.Application
, which ResourceConfig
extends from.
Then what you can do is call one of standard the Application
API methods to get set properties. That method of course is named getProperties()
, which returns a map of properties.
@Path("/")
public class TestResource
{
@Context
Application application;
@GET
public String get() {
String value = (String)application.getProperties().get("MyProp");
}
}
Also by using the property
method on the ResourceConfig
, that property is put into a global javax.ws.rs.core.Configuration
object, which is also injectable. So instead of Application
, you could inject Configuration
@Path("/")
public class TestResource
{
@Context
Configuration config;
@GET
public String get() {
String value = (String)config.getProperty("MyProp");
}
}
See Also:
Application
or Configuration
Upvotes: 5