当前位置: 首页 > 知识库问答 >
问题:

jersey+grizzly+HK2:依赖注入,但不注入资源

毕衡
2023-03-14

将EntityManager注入资源可以工作,但不能注入Callable。在这里,EntityManager保持为null

请告知代码保存在这里是否比保存在GitHub上更好。

共有1个答案

汪阳飇
2023-03-14

因此,要真正理解HK2的工作原理,您应该熟悉它的ServiceLocator。它类似于SpringApplicationContext,后者是DI框架的主容器。

在一个独立的应用程序中,您可以通过以下操作来引导DI容器

ServiceLocatorFactory locatorFactory = ServiceLocatorFactory.getInstance();
ServiceLocator serviceLocator = locatorFactory.create("TestLocator");
ServiceLocatorUtilities.bind(serviceLocator, new EntityManagerProvider());

现在,您的EntityManagerProvider已注册到容器中。您可以通过以下操作来查找EntityManager

EntityManager em = serviceLocator.getService(EntityManager.class);
public class BackgroundTask implements Callable<String> {

    @Inject
    EntityManager em;

    @Override
    public String call() throws Exception {
        ...
}
BackgroundTask task = new BackgroundTask();
BackgroundTask task = new BackgroundTask(); 
serviceLocator.inject(task);

因此,下一个问题是,如果任务正在Jersey应用程序的范围之外运行,如何注入任务?在很大程度上,以上所说的都是它的要旨。Jersey有自己的ServiceLocator,尝试获取对它的引用并不容易。我们可以为Jersey提供ServiceLocator,但Jersey最终仍然创建自己的定位器,并使用我们的定位器填充它。所以最终还是会有两个定位器。您可以在下面的重构代码中看到我的意思的一个示例,其中它检查ServiceLocatorFeator中的引用。

但是如果您确实希望向Jersey提供ServiceLocator,则可以将其传递给Grizzly服务器工厂方法

server = GrizzlyHttpServerFactory.createHttpServer(
        URI.create(BASE_URI),
        config, 
        serviceLocator
);

现在你还可以在泽西以外使用定位器。老实说,在这种情况下,您完全不能涉及Jersey并且只保留您自己的定位器,只需将EntityManagerProvider注册到Jersey和您的ServiceLocator中。我看不出它真的有多大区别,除了多了一行代码。功能上,我看不出有什么变化。

public class DependencyInjectionTest {

    private final ServiceLocatorFactory locatorFactory
            = ServiceLocatorFactory.getInstance();
    private ServiceLocator serviceLocator;

    private final static String BASE_URI = "http://localhost:8888/";
    private final static String OK = "OK";
    private HttpServer server;
    private ExecutorService backgroundService;

    public class EntityManagerProvider extends AbstractBinder
            implements Factory<EntityManager> {

        private final EntityManagerFactory emf;

        public EntityManagerProvider() {
            emf = Persistence.createEntityManagerFactory("derbypu");
        }

        @Override
        protected void configure() {
            bindFactory(this).to(EntityManager.class);
            System.out.println("EntityManager binding done");
        }

        @Override
        public EntityManager provide() {
            EntityManager em = emf.createEntityManager();
            System.out.println("New EntityManager created");
            return em;
        }

        @Override
        public void dispose(EntityManager em) {
            em.close();
        }
    }

    public class BackgroundTask implements Callable<String> {

        @Inject
        EntityManager em;

        @Override
        public String call() throws Exception {
            System.out.println("Background task started");
            Assert.assertNotNull(em);   // will throw exception

            System.out.println("EntityManager is not null");
            return OK;
        }
    }

    public class ServiceLocatorFeature implements Feature {

        @Override
        public boolean configure(FeatureContext context) {
            ServiceLocator jerseyLocator
                    = org.glassfish.jersey.ServiceLocatorProvider
                            .getServiceLocator(context);

            System.out.println("ServiceLocators are the same: "
                    + (jerseyLocator == serviceLocator));

            return true;
        }
    }

    @Path("/test")
    public static class JerseyResource {

        @Inject
        EntityManager em;

        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public Response doGet() {
            System.out.println("GET request received");
            Assert.assertNotNull(em);

            System.out.println("EntityManager is not null");
            return Response.ok()
                    .entity(OK)
                    .build();
        }
    }

    @Before
    public void setUp() {
        serviceLocator = locatorFactory.create("TestLocator");
        ServiceLocatorUtilities.bind(serviceLocator, new EntityManagerProvider());

        System.out.println("Setting up");
        ResourceConfig config = new ResourceConfig();
        config.register(new ServiceLocatorFeature());
        //config.register(new EntityManagerProvider());
        config.register(JerseyResource.class);
        // can't find a better way to register the resource
        //config.registerInstances(JerseyResource.class);   

        server = GrizzlyHttpServerFactory.createHttpServer(
                URI.create(BASE_URI),
                config, serviceLocator
        );

        backgroundService = Executors.newSingleThreadScheduledExecutor();
    }

    @After
    public void tearDown() {
        System.out.println("Shutting down");
        server.shutdownNow();
        backgroundService.shutdownNow();
    }

    @Test
    public void testScheduledBackgroundTask() throws Exception {
        Assert.assertTrue(server.isStarted());

        BackgroundTask task = new BackgroundTask();
        serviceLocator.inject(task);
        Future<String> f = backgroundService.submit(task);
        System.out.println("Background task submitted");

        try {
            Assert.assertEquals(OK, f.get());   // forces Exception
        } catch (ExecutionException | InterruptedException ex) {
            System.out.println("Caught exception " + ex.getMessage());
            ex.printStackTrace();

            Assert.fail();
        }
    }

    @Test
    public void testBackgroundTask() throws Exception {
        Assert.assertTrue(server.isStarted());

        BackgroundTask task = new BackgroundTask();
        serviceLocator.inject(task);
        System.out.println("Background task instantiated");

        Assert.assertEquals(OK, task.call());
    }

    @Test
    public void testResource() {
        Assert.assertTrue(server.isStarted());

        Client client = ClientBuilder.newClient();
        WebTarget target = client.target(BASE_URI);

        Response r = target.path("test")
                .request()
                .get();
        Assert.assertEquals(200, r.getStatus());
        Assert.assertEquals(OK, r.readEntity(String.class));
    }
}
 类似资料:
  • 试图创建一个自定义的,我可以通过Jersey注入到我的资源中。 这在本问题的Java中有涉及。我已经阅读了有关这方面的文档,这些文档也是用Java编写的。最后,GitHub中的一些代码涵盖了相同的主题(通过Dropwizard完成)。 这将全部编译,但在运行时失败,出现以下异常 我不知道是我在向Scala的转换中犯了错误,还是我在注册绑定器时做了错误的事情。

  • 我正在尝试使用Jersey测试框架为我的REST API编写功能测试。然而,当我在功能测试中使用依赖注入时,我似乎遇到了一个障碍。我的主应用程序看起来是这样的: 是否有一种方法可以将HK2服务定位器与Jersey测试框架一起使用,或者我是否需要将我的应用程序视为外部容器并使用外部容器提供程序,如这里所述:外部容器? 此外,由于这些是功能测试,因此在这里不允许对注入的服务进行嘲弄。

  • 我正在编写一个公开 REST API 的简单微服务。所以我开始使用泽西岛,当然我需要将我的对象注入球衣资源中。基本上,我有2个类来定义一组资源,其中一些需要使用另一个服务。 所以基本上我有: } 该接口的2种实现(MyServiceBean和My备选ServiceBean) 而且,就我对阅读新泽西文件的理解,我定义了一个hk2活页夹: 我将此活页夹注册到ApplicationConfig类 } 并

  • 问题内容: 从头开始,在没有任何Jersey 1.x知识的情况下,我很难理解如何在Jersey 2.0项目中设置依赖项注入。 我也知道HK2在Jersey 2.0中可用,但是我似乎找不到帮助Jersey 2.0集成的文档。 pom.xml 我可以让容器启动并使用我的资源,但是一旦我将@Inject添加到MyService,框架就会引发异常: 问题答案: 你需要定义一个并将其注册到你的JAX-RS应

  • 例如,Foos的资源可能如下所示: 对于酒吧:

  • 在React中,想做依赖注入(Dependency Injection)其实相当简单。请看下面这个例子: // Title.jsx export default function Title(props) { return <h1>{ props.title }</h1>; } // Header.jsx import Title from './Title.jsx'; export defa