Search code examples
javaeclipselink

Java EntityManager nullpointer


I'm trying to retrieve a simple JSON list, convert this JSON array to Eclipselink objects and put them in postgres. Although i keep getting nullpointers from the EntityManager and i've lost track.

Im calling my controller from a test webservice:

@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();
        }
    }

In the controller im trying to persist these converted objects:

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);
        }
    }
}

Im calling this method from a webservice, only to test it out. Im planning to use seperate threads for pulling it in, in the background.

But what am i doing wrong? This persistance setup is very confusing?!?


Solution

  • The main issue is that the AppController is not a managed object and so no dependency injection will be performed in it. You either need to inject the AppController into the servlet as a managed bean or manually initialise the EntityManagerFactory using the javax.persistence.Persistence utility class. If the AppController is fully stateless you could inject it as a CDI managed bean using the @Inject annotation.

    Another problem if you do inject the AppController is that the EntityManagerFactory is only injected after the AppController object has been constructed, but fields are initialised during object construction. When a new AppController object is created, the emf field is initialised to null and so the attempt to initialise the em field will lead to a null pointer exception.

    EntityManagers are also not thread-safe, so if you do go the route of injecting it through CDI, you will need to create the EntityManager from the factory in the updateAppList() method. This has the drawback that transaction management and closing the entity manager will be your own responsibility.

    An alternative is to convert the AppController to an EJB stateless session bean and then injecting this in the servlet. In this case you don't need to inject the EntityManagerFactory, but can directly inject the EntityManager using the @PersistenceContext annotation.