I need to test my RESTful service and I thought the most appropriate way to do it would be using the Jersey Test Framework since I am already using Jersey for my service.
However, when running a simple test I am getting a UnsatisfiedDependencyException
because the implementation of the DAO I am using in the service is not found (it's being set via DI). This error used to happen to me everytime I modified my pom.xml
Maven configuration file, mostly when adding or removing dependencies. Supposedly, the IDE I'm using, IntelliJ IDEA is supposed to regenerate the artifacts automatically, but for me to avoid this dependency failure I needed to remove the old artifact from the Tomcat server deployment options as well as from the project structure, and add it again.
The problem here is that the test framework is using a separate server, as the documentation said. I am using the following one:
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.23.1</version>
</dependency>
I don't know how to solve the dependency issue if I am using a different server.
The top error message in the exception stack says:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl
Any ideas?
Edit. I managed to patch it with a dirty solution.
First, let me show you how I was injecting the DAO:
// Binder.java
public class Binder extends AbstractBinder {
@Override
protected void configure() {
bind(TournamentDao.class).to(ITournamentDao.class).in(Singleton.class);
}
}
// DependencyInjectionFeature.java
@Provider
public class DependencyInjectionFeature implements Feature {
@Override
public boolean configure(FeatureContext context) {
context.register(new Binder());
return true;
}
}
// EventSchedulerService.java
@Path("eventscheduler")
public class EventSchedulerService {
private ITournamentDao dao;
@Inject
public EventSchedulerService(ITournamentDao tournamentDao) {
dao = tournamentDao;
}
}
The web configuration file web.xml
scans the package where these classes are placed (the package has the same name than the one where the test exists) and perform the dependency injection since it finds the @Provider
annotation.
To patch my issue I did the exact same thing in the test class:
public class EventSchedulerServiceTest extends JerseyTest {
protected Application configure() {
ResourceConfig config = new ResourceConfig(EventSchedulerService.class);
config.register(new AbstractBinder() {
@Override
protected void configure() {
bind(TournamentDao.class).to(ITournamentDao.class).in(Singleton.class);
}
});
return config;
}
}
Obviously this is a bad idea because now I have duplicate code; but it did the trick. I'd like to know how to make the test server to use the service configuration correctly.
I remember from a previous discussion in the comments here , you had the problem of not using a ResourceConfig
to configure your main application. You we instead using web.xml.
The reason you are using a Feature
annotated with @Provider
is that you we're using package scanning in your web.xml
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>your.packages.to.scan</param-value>
</init-param>
The package scan picked up the @Provider
on the Feature
, and automatically registers it. This provider is what is used to register the Binder
, which is what configured the dependency injection.
As mentioned, a Jersey application can be configured in a ResourceConfig
or in a web.xml. Anything jersey configuration you can do in the web.xml, you can also do in the ResourceConfig
. There are a bunch of different ways you can register components with the ResourceConfig
You can just call register
config.register(new DependencyInjectionFeature());
You can also package scan, the same way you are doing in the web.xml, by calling packages
config.packages("your.packages.to.scan");
You should also look at your implementation of the Binder
class. It extends AbstractBinder
. The look at how you are currently configuring the DI in the test
config.register(new AbstractBinder() { @Override protected void configure() { ... } });
You are registering an AbstractBinder
instance. So you know that calling you can register the DI configuration calling register
on the ResourceConfig
, so you could instead of registering a different binder, just register an instance of the Binder
class
config.register(new Binder());
So you have some options.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.