Reputation: 109
I'm currently developing a JAX-RS Servlet which I then want to deploy in a Glassfish 4.1 Server (consequently the JAX-RS runtime is Jersey 2.x).
Instead of going with Spring for the configuration and DI stuff, I wanted to try out the Java EE way of doing this. However, neither CDI nor the injection of the datasource I configured in the Glassfish Server is working. But first of all here are the relevant things about the servlet.
Dependencies (are declared with version and scope in the parent pom - which is not the one you see here):
<dependencies>
<!-- Java EE API -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
</dependency>
<!-- Jersey CDI support -->
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x-ban-custom-hk2-binding</artifactId>
</dependency>
<!-- Logging dependencies -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
web.xml:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>Backend</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Disable Moxy JSON -->
<init-param>
<param-name>jersey.config.disableMoxyJson</param-name>
<param-value>true</param-value>
</init-param>
<!-- Register resource classes -->
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.test.Service</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Backend</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
beans.xml:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>
Service.java:
@Path("/")
@RequestScoped
public class Service {
@Inject
private DataProvider dataProvider;
@Path("test")
@GET
@Produces({MediaType.APPLICATION_JSON})
public Response test(){
return Response.ok(dataProvider.getArticles()).build();
}
}
SQLDataProvider.java:
@Default
@ApplicationScoped
@Singleton
@Path("singleton-bean")
public class SQLDataProvider implements DataProvider {
@Resource(name = "jdbc/db_1")
private DataSource dataSource;
private SQLQueryFactory factory;
@Override
public List<Article> getArticles() {
if(factory == null){
factory = new SQLQueryFactory(new Configuration(new MySQLTemplates()), dataSource);
}
QArtikel artikel = QArtikel.artikel;
List<String> names = factory.select(artikel.artikeltyp).from(artikel).fetch();
return names.stream().map(Article::new).collect(Collectors.toList());
}
}
If I deploy this servlet in the Glassfish Server and do a Request, the following exception is thrown:
javax.servlet.ServletException: A MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=DataProvider,parent=SkiBazaarService,qualifiers={},position=-1,optional=false,self=false,unqualified=null,158365417)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of org.skiclub.service.SkiBazaarService errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on org.skiclub.service.SkiBazaarService
As you can see I already tried the solution of user G. Demecki from this post by including the two Jersey dependencies in my servlet - but with no success. I also tried the solution from Oracle, which was posted somewhere in this post. But this did not work for me as well.
I also saw a solution in which you specify the bindings from Types to Instances for the HK2 runtime in this post. I admit that I haven't tried it because I think that having to programmaticlly register the instances to be injected makes absolute nonsense of the idea behind DI.
But there also is another problem. If I modify the declaration of the DataProvider in the Service class to the following
private DataProvider dataProvider = new SQLDataProvider();
the problem with CDI vanishes but a NPE is thrown, since the DataSource I'm trying to get from JNDI is not injected into the instance of the SQLDataProvider. So it seems that the Resource Injection of Java EE also does not work in the JAX-RS Container. For this problem I did not find any possible solutions during my research.
I hope that someone can show me what I need to change in my configuration in order to make CDI and Resource Injection work with JAX-RS because at the moment, this seems impossible for me.
Kind Regards Pascal
Upvotes: 3
Views: 3844
Reputation: 291
See this question:
Recource injection doesn't work with glassfish 4 while lookup works
Try looking up your Resource
a different property, like mappedName
as the above questions suggests.
@Resource(mappedName = "jdbc/db_1")
private DataSource dataSource;
Upvotes: 0