Java EntityManager nullpointer

时间:2012-12-30 22:01:52

标签: java eclipselink

我正在尝试检索一个简单的JSON列表,将此JSON数组转换为Eclipselink对象并将它们放在postgres中。虽然我不断从EntityManager获取nullpointers,但我已经失去了轨道。

我从测试网络服务调用我的控制器:

@WebServlet(name = "Test", urlPatterns = {"/Test"})
public class Test extends HttpServlet {


    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            // HERE I CALL CUSTOM METHODS
            AppController appConn = new AppController();
            appConn.updateAppList();
        } finally {            
            out.close();
        }
    }

在控制器中我试图保留这些转换后的对象:

public class AppController {
    @PersistenceUnit(unitName="UserPU")
    EntityManagerFactory emf;
    EntityManager em = emf.createEntityManager();


    public AppController() {

    }

    public void updateAppList() {
        try {
            URLController urlConn = new URLController(Config.allAppsURL);
            JsonElement jelement = new JsonParser().parse(urlConn.toString());
            JsonObject  jobject = jelement.getAsJsonObject();
            jobject = jobject.getAsJsonObject("applist");
            JsonArray jarray = jobject.getAsJsonArray("apps");

            ArrayList<SteamApp> apps = new ArrayList<App>(){};
            for(int i = 0; i < jarray.size(); i++) {
                JsonObject jsteamObject = jarray.get(i).getAsJsonObject();
                App app = new SteamApp(jsteamObject.get("appid").getAsLong(), jsteamObject.get("name").toString());
                apps.add(app);
                //System.out.println("App[" + app.getAppid() + ", " + app.getName() + "] \n\r");
            }

            em.persist(apps);
            em.flush();

        } catch (Exception ex) {
            Logger.getLogger(AppController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

我从Web服务调用此方法,只是为了测试它。我计划在后台使用单独的线程将其拉入。

但是我做错了什么?这种持久性设置非常混乱?!?

1 个答案:

答案 0 :(得分:2)

主要问题是AppController不是托管对象,因此不会在其中执行依赖注入。您需要将AppController作为托管bean注入servlet,或者使用EntityManagerFactory实用程序类手动初始化javax.persistence.Persistence。如果AppController完全无状态,您可以使用@Inject注释将其作为CDI托管bean注入。

如果您注入AppController,另一个问题是EntityManagerFactory仅在构造AppController对象后注入,但在对象构造期间初始化字段。创建新的AppController对象时,emf字段初始化为null,因此初始化em字段的尝试将导致空指针异常。

EntityManagers也不是线程安全的,所以如果你确实通过CDI注入它,你需要在EntityManager方法中从工厂创建updateAppList()。这样做的缺点是事务管理和关闭实体管理器将是您自己的责任。

另一种方法是将AppController转换为EJB无状态会话bean,然后将其注入servlet中。在这种情况下,您不需要注入EntityManagerFactory,但可以使用EntityManager注释直接注入@PersistenceContext