我如何在 Jersey 中使用 supportsNullCreation()?
How do I utilize supportsNullCreation() in Jersey?
我有一个可注射供应商,可能 return 无效。当它为空时出现异常。我将提供程序注册为 Singleton,是否可以将其注册为我为 supportsNullCreation() 自定义为 return true 的 SingletonContext 类型?我想如果我能做到这一点,那么即使 findOrCreate() return 为 null,我的代码仍然 运行 这就是我想要的。
@ApplicationPath("rest")
public class MyApplication extends ResourceConfig
{
public MyApplication()
{
...
// Provider of DB
this.register( new AbstractBinder()
{
@Override
public void configure()
{
bindFactory(DbManager.class).to(EntityManagerFactory.class).in(Singleton.class);
}
});
}
然后就是这样使用:
@Singleton
@Path("myservice")
public class WebServiceClass
{
// NOTE: Right now I have to comment this to run without a DB
@Inject
private EntityManagerFactory entityManagerFactory = null;
...
我得到的例外是...
java.lang.IllegalStateException: Context
org.jvnet.hk2.internal.SingletonContext@6cae5847 findOrCreate returned a null for
descriptor SystemDescriptor(
implementation=com.db.DbManager
contracts={javax.persistence.EntityManagerFactory}
scope=javax.inject.Singleton
qualifiers={}
descriptorType=PROVIDE_METHOD
descriptorVisibility=NORMAL
metadata=
rank=0
loader=org.glassfish.hk2.utilities.binding.AbstractBinder@7050f2b1
proxiable=null
proxyForSameScope=null
analysisName=null
id=145
locatorId=0
identityHashCode=863132354
reified=true)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2075)
...
我建议稍微更改一下设计。在资源 class 中使用 EntityManagerFactory
并不是很好的设计。你留下了像
这样的代码
public class Resource {
private EntityManagerFctory emf;
@POST
public Response get(Entity e) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(e);
em.getTransaction().commit();
em.close();
}
}
这张照片有很多错误。一方面,您违反了[单一职责原则][1]。其次,这不允许您优雅地处理 null
EMF,即使这是可能的。你到处都有这个
if (emf != null) {
// do code above
} else {
// do something else.
}
而且它不适合测试。常见的模式是使用 DAO 层。就我个人而言,我什至在 DAO 和 REST 层之间添加了一个服务层,但您可以只使用一个 DAO 层。
例如,我要做的是为数据访问调用创建一个通用抽象接口。
public interface DataService {
Data getData();
}
然后为数据库访问创建一个实现
public class WithDbService implements DataService {
private EntityManagerFactory emf;
public WithDbService(EntityManagerFactory emf) {
this.emf = emf;
}
@Override
public Data getData() {
...
}
}
然后创建另一个没有数据库访问权限的实现。
public class WithoutDbService implements DataService {
@Override
public Data getData() {}
}
然后你可以使用Factory
创建DataService
。您要做的是使用 ServiceLocator
尝试找到 EMF。如果不为空,return WithDbService
else return WithoutDbService
public class DataServiceFatory implements Factory<DataService> {
private DataService dataService;
@Inject
public DataServiceFactory(ServiceLocator locator) {
// abbreviated for brevity
EMF emf = locator.getService(EMF.class);
if (emf != null) {
dataService = new WithDbService(emf);
} else {
dataService = new WithoutDbService();
}
}
@Override
public DataService provider() { return dataService; }
}
[...]
bindFactory(DataServiceFactory.class).to(DataService.class).in(..);
然后你可以在每个地方注入DataService
。只要这两个实现遵循约定,就应该可以正常工作。
可能会有一些设计改进,但与直接在资源中使用 EMF 相比,这是一个很大的进步 class。
我有一个可注射供应商,可能 return 无效。当它为空时出现异常。我将提供程序注册为 Singleton,是否可以将其注册为我为 supportsNullCreation() 自定义为 return true 的 SingletonContext 类型?我想如果我能做到这一点,那么即使 findOrCreate() return 为 null,我的代码仍然 运行 这就是我想要的。
@ApplicationPath("rest")
public class MyApplication extends ResourceConfig
{
public MyApplication()
{
...
// Provider of DB
this.register( new AbstractBinder()
{
@Override
public void configure()
{
bindFactory(DbManager.class).to(EntityManagerFactory.class).in(Singleton.class);
}
});
}
然后就是这样使用:
@Singleton
@Path("myservice")
public class WebServiceClass
{
// NOTE: Right now I have to comment this to run without a DB
@Inject
private EntityManagerFactory entityManagerFactory = null;
...
我得到的例外是...
java.lang.IllegalStateException: Context
org.jvnet.hk2.internal.SingletonContext@6cae5847 findOrCreate returned a null for
descriptor SystemDescriptor(
implementation=com.db.DbManager
contracts={javax.persistence.EntityManagerFactory}
scope=javax.inject.Singleton
qualifiers={}
descriptorType=PROVIDE_METHOD
descriptorVisibility=NORMAL
metadata=
rank=0
loader=org.glassfish.hk2.utilities.binding.AbstractBinder@7050f2b1
proxiable=null
proxyForSameScope=null
analysisName=null
id=145
locatorId=0
identityHashCode=863132354
reified=true)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2075)
...
我建议稍微更改一下设计。在资源 class 中使用 EntityManagerFactory
并不是很好的设计。你留下了像
public class Resource {
private EntityManagerFctory emf;
@POST
public Response get(Entity e) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(e);
em.getTransaction().commit();
em.close();
}
}
这张照片有很多错误。一方面,您违反了[单一职责原则][1]。其次,这不允许您优雅地处理 null
EMF,即使这是可能的。你到处都有这个
if (emf != null) {
// do code above
} else {
// do something else.
}
而且它不适合测试。常见的模式是使用 DAO 层。就我个人而言,我什至在 DAO 和 REST 层之间添加了一个服务层,但您可以只使用一个 DAO 层。
例如,我要做的是为数据访问调用创建一个通用抽象接口。
public interface DataService {
Data getData();
}
然后为数据库访问创建一个实现
public class WithDbService implements DataService {
private EntityManagerFactory emf;
public WithDbService(EntityManagerFactory emf) {
this.emf = emf;
}
@Override
public Data getData() {
...
}
}
然后创建另一个没有数据库访问权限的实现。
public class WithoutDbService implements DataService {
@Override
public Data getData() {}
}
然后你可以使用Factory
创建DataService
。您要做的是使用 ServiceLocator
尝试找到 EMF。如果不为空,return WithDbService
else return WithoutDbService
public class DataServiceFatory implements Factory<DataService> {
private DataService dataService;
@Inject
public DataServiceFactory(ServiceLocator locator) {
// abbreviated for brevity
EMF emf = locator.getService(EMF.class);
if (emf != null) {
dataService = new WithDbService(emf);
} else {
dataService = new WithoutDbService();
}
}
@Override
public DataService provider() { return dataService; }
}
[...]
bindFactory(DataServiceFactory.class).to(DataService.class).in(..);
然后你可以在每个地方注入DataService
。只要这两个实现遵循约定,就应该可以正常工作。
可能会有一些设计改进,但与直接在资源中使用 EMF 相比,这是一个很大的进步 class。