Reputation: 417
Could you possibly explain how I can get the ServletContext
instance in my Application
's sub-class? Is it possible? I have tried to do it like in the following snippet but it does not seem to work - the ctx
is not set:
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
//...
@ApplicationPath("/")
public class MainApplication extends Application {
@Context ServletContext ctx;
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
//...
return classes;
}
}
web.xml:
<web-app ...>
<context-param>
<param-name>environment</param-name>
<param-value>development</param-value>
</context-param>
<filter>
<filter-name>jersey-filter</filter-name>
<filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>my.MainApplication</param-value>
</init-param>
</filter>
...
</web-app>
The problem is that I need to get context parameters from it. If there is another way, I would be grateful if somebody gave a hint.
I understand that Context
annotation might not be purposed for this. Actually, I do not need ServletContext
itself. If only I could get context params from web.xml, I would be absolutely happy.
Here is an example of what I really need:
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class MainApplication extends Application {
@Context ServletContext ctx;
@Override
public Set<Object> getSingletons() {
Set<Object> set = new HashSet<Object>();
final String environment = ctx.getInitParameter("environment");
//final String environment = ... get context parameter from web xml
set.add(new AbstractBinder() {
@Override
protected void configure() {
bind(new BaseDataAccess(environment)).to(DataAccess.class);
}
});
//...
return set;
}
}
Thanks.
Upvotes: 18
Views: 26303
Reputation: 105
@Context
can be made available on ResoureConfig
by injecting it as a constructor parameter using @Context
. Another way to access it is through an event handler.
Try the below code.
@ApplicationPath("...")
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(StartupHandler.class);
}
private static class StartupHandler extends AbstractContainerLifecycleListener {
@Context
ServletContext ctx;
@Override
public void onStartup(Container container) {
// You can put code here for initialization.
}
}
// ...
Upvotes: 2
Reputation: 3546
Since Jersey 2.5, ServletContext can be injected directly in constructor: https://java.net/jira/browse/JERSEY-2184
public class MyApplication extends ResourceConfig {
public MyApplication(@Context ServletContext servletContext) {
// TODO
}
}
Upvotes: 17
Reputation: 1579
You can use the ApplicationEventListener
interface to get the ServletContext
. After initialization has finished, you can 'catch' an ApplicationEvent
and use the injected ServletContext
to work with.
Works fine with: org.glassfish.jersey : 2.12
For additional versions, pls use comments - i dont know, sry.
Jersey Docs - 20.1.2. Event Listeners
Your MainApplication
:
@ApplicationPath("/")
public class MainApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> set = new HashSet<Class<?>>();
set.add(MainApplicationListener.class);
return classes;
}
}
... or alternative MainResourceConfig
(I prefer to use this one):
public class MainResourceConfig extends ResourceConfig {
public MainResourceConfig() {
register(MainApplicationListener.class);
}
}
And the ApplicationEventListener
:
public class MainApplicationListener implements ApplicationEventListener {
@Context
private ServletContext ctx; //not null anymore :)
@Override
public void onEvent(ApplicationEvent event) {
switch (event.getType()) {
case INITIALIZATION_FINISHED:
// do whatever you want with your ServletContext ctx
break;
}
@Override
public RequestEventListener onRequest(RequestEvent requestEvent) {
return null;
}
}
Upvotes: 1
Reputation: 261
There is interesting statement in documentation for Jersey version 1.18 for class com.sun.jersey.spi.container.servlet.ServletContainer
The servlet or filter may be configured to have an initialization parameter "com.sun.jersey.config.property.resourceConfigClass" or "javax.ws.rs.Application" and whose value is a fully qualified name of a class that implements ResourceConfig or Application. If the concrete class has a constructor that takes a single parameter of the type Map then the class is instantiated with that constructor and an instance of Map that contains all the initialization parameters is passed as the parameter.
If my understanding is correct the following constructor must be invoced with "an instance of Map that contains all the initialization parameters"
public class ExampleApplication extends Application {
public ExampleApplication(Map initParams) {
}
...
}
Here is appropriate part of web.xml:
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>experiment.service.ExampleApplication</param-value>
</init-param>
</servlet>
But somehow it failed for me with the following message:
SEVERE: Missing dependency for constructor public experiment.service.ExampleApplication(java.util.Map) at parameter index 0
And for current version of Jersey (2.5.1) there are no such statement in documentstion: https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/servlet/ServletContainer.html
Upvotes: 1
Reputation:
Don't use @Context
in your Application
but in a Resource class.
@Path("/foos")
public class FooResource {
@Context
ServletContext ctx;
@GET
public Response getFoos() {
return Response.ok().build();
}
}
Upvotes: 0
Reputation: 10727
Injection happens when you enter service method. Check if this is a problem.
Upvotes: 1