2

我正在寻找基于 JAX-RS / Jersey 2 和 EJB 3.1 Lite 注入(或以其他方式最好的初始化)JDOPersistenceManager和/或PersistenceManagerFactoryRESTful Web 应用程序资源的最干净的方法,最好不要添加太多额外的依赖项。该项目使用 DataNucleus 并使用 Maven 3 构建。

这是我发现的一些指针。也许您已经尝试过其中的一些并发现哪种方法最有效:

当前的解决方案基于 JPA,并且注入照常工作。以下代码已被简化,不幸的是我无法发布原始代码。

main/java/project/ws/rs/TestResource.java

@Path("/test")
@Stateless
public class TestResource {

    @PersistenceContext(unitName = "project-webapi")
    private EntityManager em;

    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response test(@PathParam("id") UUID id) {
        return Response.status(
                Response.Status.OK).entity(em.find(type, id)).build();
    }
}

正如您在上面看到的,持久的 JAX-RS 资源被注释为@StatelessEJB。

所有 Java EE 和 Jersey 依赖项都由作为我的目标平台的 GlassFish 4.0 提供。DataNucleus 库包含在WEB-INF/lib.

该项目具有main/resources/META-INF/persistence.xml文件描述的标准持久性单元。

<persistence>
  <persistence-unit name="project-webapi"/>
</persistence>

(为简单起见,省略了 XML 命名空间和模式引用。)

部署描述符位于main/webapp/WEB-INF/web.xml

<web-app version="3.0" metadata-complete="false" />

目标

我想从 JPA 切换到 JDO,而不会像上面那样丢失干净的依赖注入。一个理想的解决方案当然类似于EntityManagerPersistenceManager上面的替换,但是如何实现或者可能有更好的方法?如果其他方式对此目的更有效,则不必注入。

我切换的原因是能够在 DataNucleus 的帮助下使用非 SQL 持久性,并为我的 Java EE Web 应用程序提供完整的 ORM 实现。

我相信还有很多其他人会对此感兴趣。有任何想法吗?

编辑:为像上面这样的网络应用程序找到最有效的方法来获取对 a 的引用PersistenceManager是这个问题的重点。

使用 JPA,它是通过注入完成的。显然,我们知道 Java EE 规范和应用服务器不直接通过 JDO 支持这一点。否则我们不会问这个。因此,我们追求最干净和“最可部署”的方式来为 Web 应用程序做这件事。

4

1 回答 1

0

我使用 CDI 拦截器在我们的 Web 应用程序中创建和拆除 JDO PM。

您可以在帮助类中定义依赖于 ThreadLocal 的拦截器方法。我在这里简化了我的代码(阅读:未经测试:)),因为您可能必须处理多个数据源、重新输入等,但如图所示:

public class MyJDO_Helper {

    private static ThreadLocal<PersistenceManager> localPM = new ThreadLocal<>();

    @AroundInvoke
    public Object allocatePersistenceManager(InvocationContext ctx) throws Exception {
        PersistenceManager pm = localPM.get();
        if (pm == null) {
            pm = getNewPersistenceManager();
            localPM.set(pm);
        }
        try {
            return ctx.proceed();
        }
        catch(Error err) { // to log them before Jersey blows casting them to Ex
            log.log(Level.SEVERE, "Caught " + err, err);
            throw err;
        }
        finally {
            try {
                if (pm.currentTransaction().isActive()) {
                    pm.currentTransaction().rollback();
                }
                pm.close();   
            }
            catch(Exception ex) {
                log.log(Level.SEVERE, "Error closing JDO PM: " + ex, ex);
            }
        }
    }

    public static PersistenceManager getPersistenceManager() {
        return localPM.get();
    }

然后你可以在需要 JDO 访问的 Jersey 资源方法上 decalre 这个拦截器:

@ManagedBean // for interceptors
@Path("/my")
public class MyResource {

    @GET
    @Interceptors({MyJDO_Helper.class})
    public String get() {
        PersistenceManager pm = MyJDO_Helper.getPersistenceManager();

此时,您可以随时从代码中的任何位置(甚至不是 Jersey 类)调用 MyJDO_Helper.getPersistenceManager(),并且您将始终获得正确的 PM,而无需传递它。:)

于 2013-08-19T17:51:38.290 回答