Search code examples
javadependency-injectionjerseyjettyhk2

Jersey HK2 Dependency Error


I'm creating RESTful web services using Jersey. I'm also using Jetty embedded web server which runs through Java main method. With Jersey comes HK2 DI by default. I am getting issue with dependency injection for the service:

Aug 09, 2017 4:16:30 PM org.glassfish.jersey.internal.Errors logErrors
WARNING: The following warnings have been detected: WARNING: Unknown HK2 failure detected:
MultiException stack 1 of 3
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=HelloService,parent=HelloResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,18651401)

I have seen several tutorials and already answered questions here in Stackoverflow but it seems that my work still has issue on dependency injection.

I have the following codes:

package hello.config;
...    
public class ApplicationResourceConfig extends ResourceConfig {
    public ApplicationResourceConfig() {
            packages("hello.resource");
            register(ApplicationBinder.class);
            register(JacksonFeature.class);
        }
}

package hello.config;
...
public class ApplicationBinder extends AbstractBinder {
    @Override
        protected void configure() {
        bind(HelloServiceImpl.class).to(HelloService.class).in(RequestScoped.class);
            bind(HelloDaoImpl.class).to(HelloDao.class).in(RequestScoped.class);
    }
}

package hello.resource;
...
@Path("/hello")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class HelloResource {
        @Inject
        private HelloService helloService;

        @GET
        @Path("world")
        public String world() {
            return helloService.hello();
    }
}

package hello.service;
...
@Contract
public interface HelloService {
    void hello();
}

package hello.service;
...
@Service
@Named
public class HelloServiceImpl implements HelloService {
    @Inject
    private HelloDao helloDao;

    @Override
    public String hello(hello) {
        helloDao.hello();
    }
}

package hello.dao;
...
@Contract
public interface HelloDao {
    String hello();
}

package hello.dao;
...
@Named
public interface HelloDaoImpl {
    public String hello() {
        return "Hello, world!";
    }
}

package hello;
...
public class Server {
    private static final int DEFAULT_PORT = 8080;
    private static final String DEFAULT_CONTEXT_PATH = "/myapp";
    private static final String DEFAULT_MAPPING_URL = "/*";

    public static void main(String[] args) {
        Server server = new Server(port(args));
        ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        servletContextHandler.setContextPath(DEFAULT_CONTEXT_PATH);
        servletContextHandler.addServlet(new ServletContainer(new ApplicationResourceConfig()), DEFAULT_MAPPING_URL);
        server.setHandler(servletContextHandler);
        server.start();
        LOGGER.info("Server started at port {}", port);
        server.join();
    }

    public static int port(String[] args) {
        if (args.length > 0) {
        String port = args[0];
        try {
            return Integer.valueOf(port);
        } catch (NumberFormatException exception) {
            LOGGER.error("Invalid port number {}", port);
        }

        return DEFAULT_PORT;
    }
}

Thank you.


Solution

  • You can't register the ApplicationBinder as a class. It needs to be registered as an instance.

    register(new ApplicationBinder());