我有一个使用Hibernate做一些持久性的Jersey Web服务。我已经使用hk2提供程序逻辑实现了EntityManagerFactory的创建/处理我发现了堆栈溢出,这极大地帮助保持了较低的DB连接数。我不想强迫用户拥有数据库,所以我希望代码能够优雅地处理这种情况。但是,除了必须注释掉我的@Inject注释之外,我似乎无法弄明白。任何人都知道如何使用自定义@Inject并对其进行编码以允许它为空?
当Persistence.create失败时,我尝试在DBManager中捕获该异常,并在我的WebServiceClass中检查null。但它在@Inject行崩溃,并且没有捕获异常。我环顾了那个findOrCreate null异常,看到有一个名为supportsNullCreation()的方法,但是没有找到如何使用它的例子。
这就是我的代码:
使用HK2的可注入数据库提供程序:
public class DbManager
implements Factory<EntityManagerFactory>
{
private static EntityManagerFactory factory = null;
@Inject
public DbManager()
{
try
{
factory = Persistence.createEntityManagerFactory("myapp");
}
catch ( Exception eee )
{
// just means DB is not connected which I want to allow
System.out.println("No DB, that should be okay");
}
}
@Override
public EntityManagerFactory provide() {
return factory;
}
@Override
public void dispose(EntityManagerFactory emf) {
if ( emf != null && emf.isOpen() )
{
emf.close();
}
}
public EntityManagerFactory getEntityMgrFactory()
{
return factory;
}
}
然后,这里是如何在Jersey应用程序中创建提供程序:
@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$2@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)
...
答案 0 :(得分:2)
您想要的是动态注入EMF依赖项。通常,所有注入都是静态的,这意味着当创建依赖于它们的对象时,所有依赖关系都会被连接。
使用任何依赖注入机制(不仅仅是HK2)的简单解决方案是创建一个包装器对象,它将保持对真实依赖项的引用,如果依赖项不可用,则为null。通过将EntityManagerFactory包装到一个或零个元素的集合中可以实现相同的目的。它看起来像这样:
// factory wrapper
public class EMFHolder {
private EntityManagerFactory emf;
public EMFHolder(EntityManagerFactory emf) { this.emf = emf;}
public EntityManagerFactory getEmf() { return this.emf;
}
// provider
public class DbManager implements Factory<EntityManagerFactory> {
// ...
@Override
public EMFHolder provide() {
return new EMFHolder(factory);
}
// ...
}
// using factory if not null
public class WebServiceClass
{
@Inject
private EMFHolder emfHolder;
public void doComethingWithEMF() {
if (emfHolder.getEmf() != null) {
// do something with the factory...
}
}
}
另请查看HK2 Iterable Provider,但我认为它不允许您从provide
方法返回空值。
答案 1 :(得分:0)
您可以查看Null Object pattern。
使用该模式,如果不存在数据库,您可以在配置中注册Null Object
Factory<EntityManagerFactory>
实施而不是DbManager
。