Jersey 3 - 使用 bindFactory 配置绑定
Jersey 3 - Configuring binding with bindFactory
使用 Jersey 3.0.1,我很难使绑定正常工作。
我有以下工厂的绑定模块:
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);
}
}
然后我使用嵌入式 Jetty 为我的 Servlet 设置:
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());
}
}
在我的 Rest 服务中,我只是尝试注入一个私有实例变量:
public MyClass {
@Inject // javax.inject.Inject
private DSLContext dslContext;
}
但是这个 dslContext 总是空的。我可以从日志中看到,它打印了 LOG.info("Configured binder");
消息。然而,将类似的日志放入我的工厂 classes 表明它们从未被调用。
有人知道我错过了什么吗?
编辑
为了让事情更简单,我创建了这个 class:
public class SimpleClass {
private static Logger LOG = LoggerFactory.getLogger(SimpleClass.class);
public SimpleClass() {
LOG.info("Call the simple class constructor");
}
更改了我的活页夹模块:
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);
}
}
然后尝试注入 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;
...
但它仍然是空的,尽管我看到了两条日志消息。我一定缺少一些基本设置。
使用 SimpleClass 示例的完整精简代码位于:
github.com/sodonnel/jerseyBind
答案很简单。您正在使用已切换到新的 Jakarta 命名的 Jersey 3.0。 javax
被抛出 window - 这包括 javax.inject
。所有 javax
包名称现已更改为 jakarta
。所以为了让注入工作,@Inject
导入应该是
import jakarta.inject.Inject;
此更改是 Java EE 到 Jakarta EE 更改的一部分,从 Jakarta EE 8 到 Jakarta EE 9,所有命名空间已从 javax
更改为 jakarta
.所以像 javax.servlet
这样的东西现在将变成 jakarta.servlet
。很奇怪,是的,这是一个巨大的突破性变化,没有向后兼容性。
在你的情况下,你拥有与 Jakarta 一起工作的所有正确组件(即 Jersey 3.0 和 Jett 11),但你只需要使用新的命名空间。请注意,所有 JAX-RS 导入现在也是 jakarta
。
使用 Jersey 3.0.1,我很难使绑定正常工作。
我有以下工厂的绑定模块:
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);
}
}
然后我使用嵌入式 Jetty 为我的 Servlet 设置:
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());
}
}
在我的 Rest 服务中,我只是尝试注入一个私有实例变量:
public MyClass {
@Inject // javax.inject.Inject
private DSLContext dslContext;
}
但是这个 dslContext 总是空的。我可以从日志中看到,它打印了 LOG.info("Configured binder");
消息。然而,将类似的日志放入我的工厂 classes 表明它们从未被调用。
有人知道我错过了什么吗?
编辑
为了让事情更简单,我创建了这个 class:
public class SimpleClass {
private static Logger LOG = LoggerFactory.getLogger(SimpleClass.class);
public SimpleClass() {
LOG.info("Call the simple class constructor");
}
更改了我的活页夹模块:
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);
}
}
然后尝试注入 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;
...
但它仍然是空的,尽管我看到了两条日志消息。我一定缺少一些基本设置。
使用 SimpleClass 示例的完整精简代码位于:
github.com/sodonnel/jerseyBind
答案很简单。您正在使用已切换到新的 Jakarta 命名的 Jersey 3.0。 javax
被抛出 window - 这包括 javax.inject
。所有 javax
包名称现已更改为 jakarta
。所以为了让注入工作,@Inject
导入应该是
import jakarta.inject.Inject;
此更改是 Java EE 到 Jakarta EE 更改的一部分,从 Jakarta EE 8 到 Jakarta EE 9,所有命名空间已从 javax
更改为 jakarta
.所以像 javax.servlet
这样的东西现在将变成 jakarta.servlet
。很奇怪,是的,这是一个巨大的突破性变化,没有向后兼容性。
在你的情况下,你拥有与 Jakarta 一起工作的所有正确组件(即 Jersey 3.0 和 Jett 11),但你只需要使用新的命名空间。请注意,所有 JAX-RS 导入现在也是 jakarta
。