我已经创建了一个服务器过滤器,它扩展了泽西的 ContainerRequestFilter ,在这个自定义过滤器中,我想注入一个(EntityManager)对象。为了实现这一目标,我创建了一个工厂来实现泽西的 hk2.api.Factory 和配置。此设置成功将对象注入资源,但是,它无法将对象注入过滤器。
有谁知道如何配置球衣以将对象注入过滤器?
原始错误:
MultiException有3个例外。他们是:
- java.lang.IllegalStateException:不在请求范围内。
- java.lang.IllegalArgumentException:尝试解决co.example.filters.Filter的依赖关系时发现错误
- java.lang.IllegalStateException:无法执行操作:解析co.example.filters.Filter
醇>
错误消息:
警告:检测到以下警告:警告:未知 检测到HK2失败:MultiException堆栈1的2 javax.persistence.PersistenceException:[PersistenceUnit:egunit] 无法构建Hibernate SessionFactory org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl。 在 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access $ 600(EntityManagerFactoryBuilderImpl.java:120) 在 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl $ 4.perform(EntityManagerFactoryBuilderImpl.java:860) 在 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl $ 4.perform(EntityManagerFactoryBuilderImpl.java:850) 在 org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425) 在 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849) 在 org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75) 在 org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54) 在 javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55) 在 javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39) 在 co.example.factories.ExampleEntityManagerFactory。(ExampleEntityManagerFactory.java:21)
...
...
...
MultiException stack 2 of 2
java.lang.IllegalStateException:无法执行操作:create on co.example.factories.ExampleEntityManagerFactory at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:395)
在 org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471) 在 org.jvnet.hk2.internal.PerLookupContext.findOrCreate(PerLookupContext.java:69) at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2064) 在 org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:105) 在 org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:87) 在 org.jvnet.hk2.internal.FactoryCreator.create(FactoryCreator.java:117) 在 org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471) 在 org.glassfish.jersey.process.internal.Reque.findOrCreate(RequestScope.java:162) at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2064) 在 org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:711) 在 org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:661) 在 org.jvnet.hk2.internal.IterableProviderImpl.get(IterableProviderImpl.java:108) 在co.example.filters.Filter.filter(Filter.java:35)
自定义过滤器:
@Provider
public class Filter implements ContainerRequestFilter {
@Inject private javax.inject.Provider<EntityManager> entityManagerProvider;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
EntityManager entityManager = entityManagerProvider.get();
EntityDao ed = new EntityDao(entityManager);
...
}
工厂:
public class ExampleEntityManagerFactory implements Factory<EntityManager> {
private final CloseableService closeableService;
private final EntityManagerFactory entityManagerFactory;
@Inject
public ExampleEntityManagerFactory(CloseableService closeableService) {
this.closeableService = closeableService;
this.entityManagerFactory = Persistence.createEntityManagerFactory("egunit");
}
@Override
public EntityManager provide() {
final EntityManager instance = entityManagerFactory.createEntityManager();
//closeableService.add(new Closeable() {
// @Override
// public void close() throws IOException {
// if (instance.isOpen()) instance.close();
// }
//});
return instance;
}
@Override
public void dispose(EntityManager instance) {
if (instance.isOpen()) instance.close();
}
}
绑定:
public class Configuration extends ResourceConfig {
public Configuration() {
...
register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(ExampleEntityManagerFactory.class).to(EntityManager.class).in(RequestScoped.class);
}
});
}
}
答案 0 :(得分:1)
很难在没有看到某些代码(和验证)的情况下确定确定,但我只是做出有根据的猜测并说它是一个范围问题。 EntityManager
应该本身就在请求范围内,所以我猜测你是如何设置它的。所以它在你的资源类中运行良好,我猜测它也是请求作用域(默认行为)。
另一方面,您的ContainerRequestFilter
处于单身范围内。因此,尝试将范围EntityManager
的请求注入单例范围的过滤器是不可能的,并且您可能在启动时收到消息&#34;不在请求范围内&#34; 。
一个简单的解决方法是简单地注入javax.inject.Provider<EntityManager>
。关于javadoc中Provider
的说明之一:
与直接注入
T
相比,注入Provider<T>
:
- 抽象范围,以便您可以在包含范围内的实例中查找较小范围内的实例。
所以就这样做
@Provider
public static class Filter implements ContainerRequestFilter {
@Inject
private javax.inject.Provider<EntityManager> emProvider;
@Override
public void filter(ContainerRequestContext request) throws IOException {
EntityManager em = emProvider.get();
}
}
鉴于其他所有功能,这应该工作(如测试)。如果这不是问题/解决方案,请发布一些代码和完整的堆栈跟踪。
对于任何感兴趣的人,这是完整的测试,使用Jersey Test Framework。
只需要Maven依赖
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.17</version>
<scope>test</scope>
</dependency>
测试(如果您想看到它失败,请删除过滤器中的javax.inject.Provider
,并简单地注入EntityManager
)
import java.io.IOException;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import junit.framework.Assert;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
public class FilterScopeTest extends JerseyTest {
public static class EntityManager {
public String getEntity() {
return "Some Entity";
}
public void close() {
}
}
public static class EntityManagerFactory implements Factory<EntityManager> {
EntityManager em = new EntityManager();
public EntityManagerFactory() {
System.out.println("+++++ EntityManagerFactory Created +++++");
}
@Override
public EntityManager provide() {
return em;
}
@Override
public void dispose(EntityManager t) {
em.close();
}
}
public static class Binder extends AbstractBinder {
@Override
protected void configure() {
bindFactory(EntityManagerFactory.class).to(EntityManager.class).in(RequestScoped.class);
}
}
@Provider
public static class Filter implements ContainerRequestFilter {
@Inject
private javax.inject.Provider<EntityManager> em;
public Filter() {
System.out.println("+++++ Filter Created +++++");
}
@Override
public void filter(ContainerRequestContext request) throws IOException {
System.out.println("+++++ In filter EM is null: " + (em.get() == null) + " +++++");
System.out.println("+++++ EM entity value: " + (em.get().getEntity()) + " +++++");
}
}
@Path("em")
public static class EmResource {
@Inject
EntityManager em;
@GET
public String getStuff() {
return em.getEntity();
}
}
@Override
public Application configure() {
return new ResourceConfig(EmResource.class, Filter.class).register(new Binder());
}
@Test
public void doIt() {
Response response = target("em").request().get();
Assert.assertEquals(200, response.getStatus());
System.out.println(response.readEntity(String.class));
response.close();
}
@Test
public void doIt2() {
Response response = target("em").request().get();
Assert.assertEquals(200, response.getStatus());
System.out.println(response.readEntity(String.class));
response.close();
}
}