JDO的Guice持久性 - 奇怪的NPE

时间:2012-01-17 23:04:42

标签: java persistence guice jdo datanucleus

我在桌面应用程序中使用Guice和JDO以及Datanucleus。我正面对一个我无法解决的NPE,所以我希望有人可以帮助我:)。

我正在使用正确配置的H2 db,创建了架构并且我的所有类都得到了很好的增强,所以不是这样。无论如何,我在这里获得NPE,在JDORepository类:

public abstract class JdoRepository<T> implements Repository<T>
{
private final Class<T> clazz;
private final Provider<PersistenceManager> pmProvider;

protected JdoRepository(Class<T> clazz, Provider<PersistenceManager> pmProvider)
{
    this.clazz = clazz;
    this.pmProvider = pmProvider;
}
public void persist(T entity)
{
    pmProvider.get().makePersistent(entity);   <---- NPE!
}

My PersistenceManagerFilter看起来像这样:

    @Singleton
    public class PersistenceManagerFilter implements Filter
    {
    private static final Logger logger =  Logger.getLogger(PersistenceManagerFilter.class.getName());

    private static final ThreadLocal<PersistenceManager> pm = new  ThreadLocal<PersistenceManager>();

    private PersistenceManagerFactory pmf;

    public void init(FilterConfig filterConfig) throws ServletException
    {
        logger.info("Creating PersistenceManagerFactory");
        pmf = JDOHelper.getPersistenceManagerFactory();
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain  chain)
            throws IOException, ServletException
    {
        try
        {
            pm.set(pmf.getPersistenceManager());
            chain.doFilter(request, response);
        }
        finally
        {
            pm.get().close();
        }
    }

    public void destroy()
    {
        logger.info("Closing PersistenceManagerFactory");
        pmf.close();
    }

    /**
     * This module binds the JDO {@link javax.jdo.PersistenceManager} interface to the  provider that allows the
     * implementation to be injected as Provider&lt;PersistenceManager&gt;.
     */
    public static class GuiceModule extends AbstractModule
    {
        @Override
        protected void configure()
        {
            bind(PersistenceManager.class).toProvider(new Provider<PersistenceManager>()
            {
                public PersistenceManager get()
                {
                    return PersistenceManagerFilter.pm.get();
                }
            });
        }
    }
}

负责模块:

    public class GuiceModule extends AbstractModule
   {
   @Override
   protected void configure()
   {
       // Enable per-request-thread PersistenceManager injection.
       install(new PersistenceManagerFilter.GuiceModule());
       bind(new TypeLiteral<Repository<Project>>() { }).to(JdoProjectRepository.class);

我是这样开始的:

Injector injector = Guice.createInjector(new GuiceModule());
    Main main = injector.getInstance(Main.class);
    main.run();

因此,主类中的存储库绑定工作正常,因为它们被重定向到JDORepository。这是低级别的东西,PMF没有得到正确约束?有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您的main.run() - 方法有何功能?它会调用PersistenceManagerFilter#doFilter吗?如果没有,则ThreadLocal<PersistenceManager>中的值将为空...

您可以覆盖initialValue()并执行以下操作:

ThreadLocal<PersistenceManager> pm = new  ThreadLocal<PersistenceManager>(){
    @Override
    protected PersistenceManager initialValue() {
        return JDOHelper.getPersistenceManagerFactory().getPersistenceManager();
    }
};

您还应该记得在finally块中调用ThreadLocal#remove()方法。

您可以直接在guice-module中绑定ThreadLocal,而不是自己处理PersistenceManager

class GuiceModule extends AbstractModule {

    @Provides @RequestScoped
    PersistenceManager providePersistenceManager(){
        return JDOHelper.getPersistenceManagerFactory().getPersistenceManager();
    }

    @Override
    protected void configure() {}
}