将对象注入过滤器

时间:2015-07-14 17:23:59

标签: java jersey jax-rs jersey-2.0

我已经创建了一个服务器过滤器,它扩展了泽西的 ContainerRequestFilter ,在这个自定义过滤器中,我想注入一个(EntityManager)对象。为了实现这一目标,我创建了一个工厂来实现泽西的 hk2.api.Factory 和配置。此设置成功将对象注入资源,但是,它无法将对象注入过滤器。

有谁知道如何配置球衣以将对象注入过滤器?

原始错误:

  

MultiException有3个例外。他们是:

     
      
  1. java.lang.IllegalStateException:不在请求范围内。
  2.   
  3. java.lang.IllegalArgumentException:尝试解决co.example.filters.Filter的依赖关系时发现错误
  4.   
  5. java.lang.IllegalStateException:无法执行操作:解析co.example.filters.Filter
  6.   

错误消息:

  

警告:检测到以下警告:警告:未知   检测到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);
            }
        });     

}
}

1 个答案:

答案 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();
    }
}