I tried implementing custom context injection just like in this answer:
@Provider
public class DaoContextProvider extends SingletonTypeInjectableProvider<Context,Bar> {
public DaoContextProvider() {
super(Bar.class, new Bar("haha"));
}
}
And here's my controller class, to witch I want to inject my context:
@Path("foo")
public class Foo {
@Context
private Bar message;
@GET
public String index() {
return String.format("%s", message );
}
}
But in response message is null.
I tried adding my context provider to singletons, as recomended:
@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
public ApplicationConfig() {
getSingletons().add(new DaoContextProvider());
}
//...
But then my artifact does not even deploy, and provides me with this error:
Artifact server:war exploded: java.io.IOException: com.sun.enterprise.admin.remote.RemoteFailureException: Error occurred during deployment: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: java.lang.UnsupportedOperationException. Please see server.log for more details.
I would provide server.log, as described in exception, but I dont know where to find this log.
The set returned from getSingletons()
is unmodifiable. Instead we need to override the method
@Override
public Set<Object> getSingletons() {
Set<Object> singletons = new HashSet<>();
singletons.add(new new DaoContextProvider());
return singletons;
}
Note though that a direct Application
subclass is limited in functionality compared to the Jersey specific way. In Jersey, the preferred approach is to use a ResourceConfig
subclass (which is actually a subclass of Application
). For example (you can use PackagesResourceConfig
to scan packages).
@ApplicationPath("/webresources")
public class AppConfig extends PackagesResourceConfig {
public AppConfig() {
// scans the package and sub-packages.
super("package.where.all.your.resource.and.providers.are");
getProperties().put("some properites", "to set");
getContainerRequestFilters().add(new SomeFiltersToRegister());
getProviderSingletons().add(new SomeProvidersToAdd());
// see the ResourceConfig API for more methods.
}
}
This will scan for @Path
and @Provider
annotated classes, so we don't need to explicitly register everything. Though some providers will need to be explicitly registered. Your particular provider doesn't need to be registered though. It i picked up in the package scan.
Ok since you say you are using Glassfish 4.1, the first thing you should understand is that Glassfish 4 uses Jersey 2.x. So any Jersey 1.x dependencies/jars you have, you should get rid of them. Use only Jersey 2.x dependencies, and make sure that they are only compile-time dependencies, as you do not want conflicting versions making it's way to Glassfish, that already has a version of them.
What this means is that your current implementation of the DaoContextProvider
will not work. The SingletonTypeInjectableProvider
is Jersey 1.x class, and the Jersey 2.x runtime will just ignore it.
In Jersey 2.x there are a few ways to configure injectable objects. One way is to create a Factory
for the object. For example.
public class DaoContextProvider implements Factory<Bar> {
@Override
public Bar provide() {
return new Bar("boo hoo!");
}
@Override
public void dispose(Bar bar) {}
}
In Jersey 2.x, the API for ResourceConfig
has change, and we can extend it directly. For example
@ApplicationPath("/webresources")
public class AppConfig extends ResourceConfig {
public AppConfig() {
packages("com.stackoverflow.jersey");
register(new AbstractBinder(){
@Override
protected void configure() {
bindFactory(DaoContextProvider.class)
.to(Bar.class)
.in(RequestScoped.class);
}
});
}
}
You can see the AbstractBinder
. That is how we register the DaoContextProvider
with the Bar
class. So now Bar
can be injected to your resource classes.
The only Maven dependency you need to pull everything else in, is
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.19</version>
<scope>provided</scope>
</dependency>
Notice the provided scope, so that it does not get built to the war. If you are not using Maven, then grab all the jars in the Jersey JAX-RS 2.0 RI bundle. Remember that you should make them only compile time dependencies. They should no get built into the war.
See Also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With