Reputation: 4466
Using Jersey 3.0.1, I am struggling to get binding working.
I have this binding module with the factories below:
public static class MyBinder extends AbstractBinder {
@Override
protected void configure() {
LOG.info("Attempting to configure binder");
bindFactory(DataSourceFactory.class).to(HikariDataSource.class).in(Singleton.class);
bindFactory(JooqConfigFactory.class).to(Configuration.class).in(Singleton.class);
bindFactory(DSLContextFactory.class).to(DSLContext.class).in(Singleton.class);
LOG.info("Configured binder");
}
}
public static class DataSourceFactory implements Supplier<HikariDataSource> {
@Override
public HikariDataSource get() {
...
return new HikariDataSource(config);
}
}
public static class JooqConfigFactory implements Supplier<Configuration> {
@Inject
HikariDataSource dataSource;
@Override
public Configuration get() {
...
return conf;
}
}
public static class DSLContextFactory implements Supplier<DSLContext> {
@Inject
Configuration config;
@Override
public DSLContext get() {
return DSL.using(config);
}
}
Then I have the setup for my Servlet using embedded Jetty:
public void start() throws Exception {
int port = appConfig.getProperty("http.port", 9998);
Server server = new Server(port);
ServletContextHandler ctx =
new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
ctx.setContextPath("/");
server.setHandler(ctx);
ResourceConfig config = new JerseyConfig();
ServletHolder servlet = new ServletHolder(new ServletContainer(config));
servlet.setInitOrder(1);
ctx.addServlet(servlet, "/*");
server.start();
server.join();
}
public static class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("com.sodonnell.jersey", "jersey.config.server.provider.packages");
register(new MyBinder());
}
}
And in my Rest service I simply try to inject a private instance variable:
public MyClass {
@Inject // javax.inject.Inject
private DSLContext dslContext;
}
However this dslContext is always null. I can see from the logs, that it prints the LOG.info("Configured binder");
message. However putting similar logs in my factory classes show they never get called.
Has anyone got any idea what I am missing?
To make things simpler, I created this class:
public class SimpleClass {
private static Logger LOG = LoggerFactory.getLogger(SimpleClass.class);
public SimpleClass() {
LOG.info("Call the simple class constructor");
}
Changed my binder module:
import com.google.inject.Injector;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.jooq.Configuration;
import org.jooq.DSLContext;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
import org.jooq.impl.DefaultConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.util.Properties;
import java.util.function.Supplier;
...
// This is a nested class
public static class MyBinder extends AbstractBinder {
@Override
protected void configure() {
LOG.info("Attempting to configure binder");
bind(new SimpleClass()).to(SimpleClass.class);
}
}
Then attempted to inject just SimpleClass:
package com.sodonnell.hdfs3.rest;
import com.sodonnell.hdfs3.SimpleClass;
import com.zaxxer.hikari.HikariDataSource;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.HEAD;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.Response;
import org.jooq.DSLContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
@Inject
private SimpleClass simpleClass;
...
But its still null, although I see both the log messages. There must be some fundamental setup I am missing.
Full cut down code with the SimpleClass example at:
github.com/sodonnel/jerseyBind
Upvotes: 3
Views: 1023
Reputation: 209004
The answer is quite simple. You are using Jersey 3.0 which has switched to the new Jakarta naming. javax
is thrown out the window - this includes javax.inject
. All the javax
package names have now been changed to jakarta
. So to get the inject to work, the @Inject
import should be
import jakarta.inject.Inject;
This change is part of the change of Java EE to Jakarta EE Starting from Jakarta EE 8 to Jakarta EE 9, all the namespacing has changed from javax
to jakarta
. So things like javax.servlet
will now be jakarta.servlet
. Weird, yes a huge breaking change with no backward compatibility.
In your case you have all the correct components to work with Jakarta (i.e. Jersey 3.0 and Jett 11), but you just need to make use of the new namespacing. Notice all the JAX-RS imports are now jakarta
also.
Upvotes: 5