0

I'm trying to write a REST application with Jersey and Jetty. Stack: Java 11, Gradle 6.1.1, Jersey 2.30, Hibernate 5.4.X, Jetty server and servlet in 9.4.26.v20200117 version. The problem appears when HK2 is injecting the dependencies. Here is a error log:

Feb 11, 2020 10:49:41 PM org.glassfish.jersey.internal.Errors logErrors
WARNING: The following warnings have been detected: WARNING: Unknown HK2 failure detected:
MultiException stack 1 of 2
java.lang.ExceptionInInitializerError
...

Here is Jetty main class:

package com.familybank;

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.servlet.ServletContainer;

public class Application {
    public static void main(String[] args) {
        // Jersey
        final var servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
        final var jerseyServletContainer = new ServletContainer(new ApplicationResourceConfiguration());
        final var jerseyServletHolder = new ServletHolder(jerseyServletContainer);
        servletContextHandler.setContextPath("/");
        servletContextHandler.addServlet(jerseyServletHolder, "/api/*");

        // Wire up Jetty
        final var handlerList = new HandlerCollection();
        handlerList.setHandlers(new Handler[]{ servletContextHandler });
        final var server = new Server(8080);
        server.setHandler(handlerList);

        /*
        final var uri = UriBuilder.fromUri("http://localhost/").port(8080).build();
        final var server = JettyHttpContainerFactory.createServer(uri, new ApplicationResourceConfiguration());
        */

        try {
            server.start();
            server.join();
        } catch (Exception ex) {
            // logger.error("Error occurred while starting Jetty", ex);
            System.exit(1);
        } finally {
            server.destroy();
        }
    }
}

Also ApplicationBinder:

public class ApplicationBinder extends AbstractBinder {
    @Override
    protected void configure() {
        // DAO dependency injection
        bind(UserDAO.class).to(UserDAO.class);
        bind(PasswordDAO.class).to(PasswordDAO.class);
        bind(RoleDAO.class).to(RoleDAO.class);

        // Service dependency injection
        bind(UserServiceImpl.class).to(UserService.class);
    }
}

And the ApplicationResourceConfiguration:

public class ApplicationResourceConfiguration extends ResourceConfig {
    public ApplicationResourceConfiguration() {
        // register(UserController.class); // With or without the result is the same
        register(new ApplicationBinder());
        packages(true, "com.example");
        // register(UserController.class);
    }
}

Additionally UserController looks like:

@Path("/user")
public class UserController {
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    private final UserService userService;

    @Inject
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GET
    @Path("/get-all")
    @Produces(MediaType.APPLICATION_JSON)
    public User getAll() {
        logger.debug("GET /user/get-all");

        return userService.getByLogin("some.user@example.com").orElseGet(User::new);
    }
}

UserServiceImpl using a RoleDAO, PasswordDAO and UserDAO. DAO classes use EntityManagerFactory to get into database.

EntityManagerFactoryProvider class:

public class EntityManagerFactoryProvider {
    private static EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("family-bank");

    public static EntityManagerFactory getEntityManagerFactory() {
        return entityManagerFactory;
    }
}

Project also contains persistance.xml configuration - it works in other project so should be fine.

The most strange thing is that when I run project from IntelliJ it works well. Jar building and run with no actions also looks good, but the stairs appear when I'm calling url from web-browser: http://localhost:8080/api/user/get-all

Then HK2 failed with dependency injection. I have no idea what is wrong. If someone need I can send whole stack trace of exceptions (didn't put it there, cause of its length...).

How to configure Jersey 2 and Jetty stuff to work in described case?

okarmusk
  • 55
  • 2
  • 10
  • You might want to include both stacktraces on that HK failure. – Joakim Erdfelt Feb 11 '20 at 21:52
  • Stack trace is really long (2156 lines). Link to traces: paste.ofcode.org/34xBccxdkNZaana69FNUuhv – okarmusk Feb 11 '20 at 22:07
  • `java.lang.NoClassDefFoundError: Could not initialize class com.example.configuration.EntityManagerFactoryProvider`. Do you have a static initializer in that class? Can you show it? Something seems to be going wrong during this initialization. – Paul Samsotha Feb 12 '20 at 03:15
  • @PaulSamsotha - I edited a question adding the EntityManagerFactoryProvider. There is static field initialized by Persistence.createEntityManagerFactory(...) method. How does it affect HK2? – okarmusk Feb 12 '20 at 09:03
  • https://stackoverflow.com/q/7325579/2587435... HK2 is not able to create the EntityManagerFactoryProvider, hence it won't be able to create anything else up the chain. There may be a problem creating the EntityManagerFactory – Paul Samsotha Feb 12 '20 at 09:32
  • I removed a static and initialize it via @Inject from constructor. Of course I added the ``` bind(EntityManagerFactoryProvider.class).to(EntityManagerFactoryProvider.class); ``` into ```ApplicationBinder```. Behavior of app doesn't changed. Still works when run from IntelliJ, but after build via gradle and run as a single jar throws: ``` MultiException stack 2 of 2 java.lang.IllegalStateException: Unable to perform operation: create on com.familybank.configuration.EntityManagerFactoryProvider ``` – okarmusk Feb 12 '20 at 11:36
  • That's a different message. Im sure there's more information in the stack trace. – Paul Samsotha Feb 12 '20 at 20:00
  • Here is a next trace package: paste.ofcode.org/M8ag8q2rTtHZdQ8i6qHDzQ Additionally I removed all of the jetty stuff to check if Jersey works on standard Tomcat9 server. It works, what makes situation completely wired, cause HK2 should be also used in Tomcat in similar way comparing to Jetty. – okarmusk Feb 12 '20 at 21:33
  • I can't find "create on com.familybank" anywhere in the trace you linked to. This is what you said the message was. – Paul Samsotha Feb 13 '20 at 03:34

1 Answers1

1

Solution was to just migrate to Tomcat.

okarmusk
  • 55
  • 2
  • 10