使用Jersey 2.0,如何根据请求注册一个可绑定的实例? [英] Using Jersey 2.0, how do you register a bindable instance per request?

查看:273
本文介绍了使用Jersey 2.0,如何根据请求注册一个可绑定的实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

...如果实例需要手动构建,也许是由第三方工厂类?以前,(Jersey 1.x),你会做这样的事情:

...if the instance needs to be constructed manually, perhaps by a 3rd party factory class? Previously, (Jersey 1.x), you would do something like this:

public class MyInjectableProvider extends PerRequestTypeInjectableProvider<Context, MyInjectable> {
    public MyInjectableProvider() {
        super(MyInjectable.class);
    }

    @Override
    public Injectable<MyInjectable> getInjectable(ComponentContext ic, Context context) {
        MyInjectable myInjectableInstance = //...

        return new Injectable<MyInjectable>() {
            @Override
            public MyInjectable getValue() {
                return myInjectableInstance;
            }
        };
    }
}

匿名本地类可以访问一个实例返回一些范围。当您不使用具有默认构造函数的类时,这是非常有用的,但需要根据每个请求构造。

The anonymous local class is able to access an instance to return within some scope. This is useful when you're not working with classes that have default constructors, but they need to be constructed on a per-request basis.

泽西2.0切换到HK2作为依赖注入框架,但是,迁移页面( https://jersey.java.net/documentation/latest /migration.html )不提供此类绑定的示例,HK2文档不提供使用AbstractBinder的示例。

Jersey 2.0 switched over to HK2 as a dependency injection framework, but alas, the migration page (https://jersey.java.net/documentation/latest/migration.html) doesn't provide an example of this kind of binding, and the HK2 documentation doesn't provide examples using an AbstractBinder.

详细说明了一点,我试图向我的资源提供资源本地的,与容器无关的JPA EntityManager实例。这些必须从单身工厂班获得,只能坚持一个单一的工作单位,这是我的情况下的一个要求。我知道有解决方法(只是注入工厂,或绑定到一个threadlocal),但是我发现以前的解决方案是优雅的,如果可能,我们想重新创建它。

To elaborate just a bit more, I'm trying to provide resource-local, container-agnostic JPA EntityManager instances to my resources. These have to be fetched from a singleton factory class, and should only stick around for a single "unit of work," which is a request in my case. I'm aware there are workarounds (Just inject the factory, or bind to a threadlocal), but I found the previous solution elegant and would like to recreate it if possible.

编辑:

通过HK2 javadocs挖掘一下,我发现类似的东西可以实现如下:


After digging through the HK2 javadocs for a bit, I've discovered that something similar can be achieved as follows:

public class MyInjectableProvider extends AbstractBinder 
        implements Factory<MyInjectable> {
    @Override
    protected void configure() {
        bindFactory(this).to(MyInjectable.class);
    }

    @Override
    public MyInjectable provide() {
        return getMyInjectable();
    }

    @Override
    public void dispose(MyInjectable instance) {}
}

并注册...

public class MyResourceConfig extends ResourceConfig {
    public MyResourceConfig() {
        register(new MyInjectableProvider());
    }
}

这个似乎有效,但也似乎有点不清楚例如,dispose()不会被调用。此外,此绑定似乎隐含地表现为RequestScoped。将配置修改为 bindFactory(this).to(MyInjectable.class).in(RequestScoped.class); 似乎没有实际更改行为。我错过了一些东西,还是这个想要的解决方案?

This "seems to work," but it also seems a bit unclear. dispose() is never called, for example. Also, this binding seems to implicitly behave as RequestScoped. Modifying the configuration to bindFactory(this).to(MyInjectable.class).in(RequestScoped.class); doesn't appear to actually change the behavior. Am I missing something, or is this the intended solution?

推荐答案

代替 Factory< T>注意注入 CloseableService 可能会做大部分你想要的。将需要一个 CloseableFactory 适配器。 CloseableService closing()退出请求范围后的所有注册资源。

In place of Factory<T>.dispose(T), registering with the injectable CloseableService may do most of what you want. A CloseableFactory adapter will be required. CloseableService closes() all registered resources upon exiting the request scope.

有关具体示例,请参阅下面的 ConnectionFactory

For a specific example, see the ConnectionFactory below.

import org.glassfish.hk2.api.Factory;
import org.glassfish.jersey.server.CloseableService;

import javax.inject.Inject;
import javax.ws.rs.InternalServerErrorException;
import java.sql.Connection;
import java.sql.SQLException;

import static com.google.common.base.Preconditions.checkNotNull;

public class ConnectionFactory implements Factory<Connection> {
    private final CloseableService closeableService;

    @Inject
    public ConnectionFactory(CloseableService closeableService) {
        this.closeableService = checkNotNull(closeableService);
    }

    public Connection provide() {
        final Connection connection;
        try {
            connection = acquireConnection();
        } catch (SQLException e) {
            throw new InternalServerErrorException(e);
        }
        try {
            closeableService.add(new CloseableConnection(connection));
        } catch (Throwable t) {
            closeQuietly(connection);
            throw runtime(t);
        }
        return connection;
    }

    public void dispose(Connection connection) {
        closeQuietly(connection);
    }

    private static RuntimeException runtime(Throwable t) {
        throw ConnectionFactory.<RuntimeException>unchecked(t);
    }

    private static <T extends Throwable> T unchecked(Throwable t) throws T {
        throw (T) t;
    }

    private static void closeQuietly(Connection connection) {
        try {
            connection.close();
        } catch (SQLException ignore) {}
    }
}

以下是 CloseableFactory - a CloseableConnection

Below is a less general version of a CloseableFactory - a CloseableConnection.

import java.io.Closeable;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import static com.google.common.base.Preconditions.checkNotNull;

public final class CloseableConnection implements Closeable {
    private final Connection connection;

    public CloseableConnection(Connection connection) {
        this.connection = checkNotNull(connection);
    }

    public void close() throws IOException {
        try {
            connection.close();
        } catch (SQLException e) {
            throw new IOException(e);
        }
    }
}

这篇关于使用Jersey 2.0,如何根据请求注册一个可绑定的实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆