3

I have an entity which attempts to call a facade (which I'm calling steps) which is talking to a DAO. The Entity Manager in only this case is null (offending line >> http://goo.gl/rqyRg) when I watch/set a breakpoint. Still a bit green with Java, hoping to glean something from one of you that will get the ball rolling in the right debugging direction. Right now, I'm suspicious that the issue is my own skull thickness.

Here is the offending Facade. << StepsFacade.java >>

package com.mdjdreview.session;

import com.mdjdreview.dao.Steps;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;


@Stateless
public class StepsFacade extends AbstractFacade<Steps> {
    @PersistenceContext(unitName = "MdJdReviewPU2")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public StepsFacade() {
        super(Steps.class);
    }

    public Object findAllRange(int low, int high) {
        try {
            Query q = this.em.createNamedQuery("Steps.findAllRange");
            q.setMaxResults(high);
            q.setFirstResult(low);
            return q.getResultList();
        }
        catch(NoResultException ex) {
            return null;
        }
    }

    public Object findByPatternRange(String title, int low, int high) {
        try {
            Query q = this.em.createNamedQuery("Steps.findByPatternRange");
            q.setParameter("title", title.toUpperCase() + "%");
            q.setMaxResults(high);
            q.setFirstResult(low);
            return q.getResultList();
        }
        catch(NoResultException ex) {
            return null;
        }
    }

    public int findByPatternRangeCount(String title) {
        Query q = this.em.createNamedQuery("Steps.findByPatternRangeCount");
        q.setParameter("title", title.toUpperCase() + "%");
        return ((Long) q.getSingleResult()).intValue();
    }

    public Object findByTitle(String title) {
        try {
            return this.em.createNamedQuery("Steps.findByTitle").setParameter("title", title).getSingleResult();
        }
        catch(NoResultException ex) {
            return null;
        }
    }

    public Object findByProductId(Object productId) {

        try {
            return this.em.createNamedQuery("Steps.findByProductId").setParameter("productId", productId).getResultList();
        } catch (Exception e) {
            System.out.println("----------- findByProductId err "+e.getLocalizedMessage());
            System.out.println("----------- findByProductId err "+e.getMessage());
            System.out.println("----------- findByProductId err "+e.getStackTrace());
            System.out.println(productId);
            return e.getMessage();
        }
    }

    public int findByProductQuestionCount(Object productId) {
        Query q = this.em.createNamedQuery("Steps.findByProductQuestionCount");
        q.setParameter("productId", productId);

        if(q.getSingleResult() == null) {
            return 0;
        }
        else {
            return ((Long) q.getSingleResult()).intValue();
        }
    }

    public int findBySlideStepCount(Object slidesId) {
        Query q = this.em.createNamedQuery("Steps.findBySlideStepCount");
        q.setParameter("slidesId", slidesId);

        if(q.getSingleResult() == null) {
            return 0;
        }
        else {
            return ((Long) q.getSingleResult()).intValue();
        }
    }

    public int findByCategoryStepCount(Object categoriesId) {
        Query q = this.em.createNamedQuery("Steps.findByCategoryStepCount");
        q.setParameter("categoriesId", categoriesId);

        if(q.getSingleResult() == null) {
            return 0;
        }
        else {
            return ((Long) q.getSingleResult()).intValue();
        }
    }

    public int findByModuleStepCount(Object modulesId) {
        Query q = this.em.createNamedQuery("Steps.findByModuleStepCount");
        q.setParameter("modulesId", modulesId);

        if(q.getSingleResult() == null) {
            return 0;
        }
        else {
            return ((Long) q.getSingleResult()).intValue();
        }
    }

    public Object findByExamStep(Object step, Object generatedExamsId) {
        try {
            Query q = this.em.createNamedQuery("Steps.findByExamStep");
            q.setParameter("step", step);
            q.setParameter("generatedExamsId", generatedExamsId);
            q.setMaxResults(1);
            q.setFirstResult(0);
            return q.getSingleResult();
        }
        catch(NoResultException ex) {
            return null;
        }
    }

    /**
     * @param em the em to set
     */
    public void setEntityManager(EntityManager em) {
        this.em = em;
    }
}

And, what's so puzzling, is here is a Facade with nearly identical code which works well. << AnswersFacade.java >>

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.mdjdreview.session;

import com.mdjdreview.dao.Answers;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author nick
 */
@Stateless
public class AnswersFacade extends AbstractFacade<Answers> {
    @PersistenceContext(unitName = "MdJdReviewPU2")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public AnswersFacade() {
        super(Answers.class);
    }

    public Object findByQuestionId(Object questionId) {
        try {
            return this.em.createNamedQuery("Answers.findByQuestionId").setParameter("questionId", questionId).getResultList();
        }
        catch(NoResultException ex) {
            return null;
        }
    }

    public Object findAllRange(int low, int high) {
        try {
            Query q = this.em.createNamedQuery("Answers.findAllRange");
            q.setMaxResults(high);
            q.setFirstResult(low);
            return q.getResultList();
        }
        catch(NoResultException ex) {
            return null;
        }
    }

    public Object findByPatternRange(String title, int low, int high) {
        try {
            Query q = this.em.createNamedQuery("Answers.findByPatternRange");
            q.setParameter("title", title.toUpperCase() + "%");
            q.setMaxResults(high);
            q.setFirstResult(low);
            return q.getResultList();
        }
        catch(NoResultException ex) {
            return null;
        }
    }

    public int findByPatternRangeCount(String title) {
        Query q = this.em.createNamedQuery("Answers.findByPatternRangeCount");
        q.setParameter("title", title.toUpperCase() + "%");
        return ((Long) q.getSingleResult()).intValue();
    }
}

Here's the entity that's calling the Facade, << ExamResults.java >>

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mdjdreview.entities;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.primefaces.model.chart.CartesianChartModel;
import org.primefaces.model.chart.ChartSeries;
import org.primefaces.model.chart.PieChartModel;

// I need to import this package to allow for access to the category object
import com.mdjdreview.dao.Steps;
import com.mdjdreview.dao.Categories;
import com.mdjdreview.session.StepsFacade;
import com.mdjdreview.session.CategoriesFacade;
import com.mdjdreview.session.ProductToCategoriesFacade;
import com.mdjdreview.session.ProductToStepsFacade;

import java.util.List;
import java.util.Map;

import javax.ejb.EJB;

/**
 *
 * @author joshua
 * this is where we layout the graph
 * 
 */
@ManagedBean
@ViewScoped
public class ExamResults implements Serializable {

    private CartesianChartModel categoryModel;
    private PieChartModel pieModel;

    @EJB
    private StepsFacade stepsFacade = new StepsFacade();

    @EJB
    private CategoriesFacade categoryFacade = new CategoriesFacade();

    public ExamResults() {
        createCategoryModel();
    }

    public CartesianChartModel getCategoryModel() {
        return categoryModel;
    }

    public PieChartModel getPieModel() {
        return pieModel;
    }
     // this one draws out the graph

    private void createCategoryModel() {
        categoryModel = new CartesianChartModel();

        Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        // TODO: this is not called eamxId, this is a productId don't forget to change this
        String productId = (String) requestMap.get("productId");

        System.out.println("--------------------------- prouctID = "+productId);


        List<Categories> cats;

        List<Steps> steps;

        try {
            steps = (List<Steps>)this.stepsFacade.findByProductId((Object)productId);
            int itemCount = steps.size();
            System.out.println("setps in list = "+itemCount);
        } catch (Exception e) {
            System.out.println("no steps for you");
            System.out.println(e.getMessage());
        }

        try {

            cats = this.categoryFacade.findByTypeParentId((Object)productId, "question");
            int itemCount = cats.size();
            System.out.println("cats in list = "+itemCount);

        } catch (Exception e) {
            System.out.println("no, dice on the categories");
        }

        //


        System.out.println("just tried to pull steps what's above this line?");


        ChartSeries correct = new ChartSeries();
        correct.setLabel("Correct");
        // what they got right
        // setp 1: 
            // <LIST> Step pull back by the steps facade
            // <LIST> Keywords
            // <LIST> Catnames 

        // step 2: loop through steps, query category ID

        // that 90 there for heart is a magic number, that needs to be pulled in dynamically
        // it looks lie in the AnswersToCategories dao, we can pull the 

        correct.set("Heart", 90);
        correct.set("Bacteria", 100);
        correct.set("Mitral Valve", 44);
        correct.set("Pediatrics", 80);
        correct.set("OBGYN", 25);

        ChartSeries missed = new ChartSeries();
        missed.setLabel("Missed");
        // what they got wrong
        missed.set("Heart", 10);
        missed.set("Bacteria", 0);
        missed.set("Mitral Valve", 56);
        missed.set("Pediatrics", 20);
        missed.set("OBGYN", 75);
// auto create x & y
        categoryModel.addSeries(correct);
        categoryModel.addSeries(missed);
    }   
}

Here's what I've tried so far to fix:

  1. I've poured over the application server's (GlassFish) startup output and not seeing anything there, everyone is happy, no warns, errors or anything higher, just a bunch of INFOs.
  2. I've looked all over Stack Overflow and much code looks identical to this and haven't been able to scare up any clues.
  3. I figured, from my entity, hoped that the Facades (http://goo.gl/MSl8F) should just be getting injected and tried not instantiating new facade objects (the following), but that just created more problems (facades were null when breakpointed).
@EJB
private StepsFacade stepsFacade;

@EJB
private CategoriesFacade categoryFacade;

Any ideas? Thanks for looking.

fusion27
  • 2,396
  • 1
  • 25
  • 25
  • Your point 3 is correct, you should remove the assignment because the EJBs should be injected by the container. If you get the NPA I suspect that ExamResult bean is not being created by the container. How do you call it? – perissf May 23 '13 at 15:17
  • @perissf `exam-complete.xhtml` calls it: http://goo.gl/DYa0F – fusion27 May 23 '13 at 15:27

1 Answers1

6

This is not right:

@EJB
private StepsFacade stepsFacade = new StepsFacade();

@EJB
private CategoriesFacade categoryFacade = new CategoriesFacade();

public ExamResults() {
    createCategoryModel();
}

Here are 2 major mistakes:

  1. You should not instantiate EJBs yourself. The container is responsible for it. You should just have them injected by the container via @EJB. The container will also take care that each EJB has in turn the right entity manager injected via @PersistenceContext.
  2. You should not try to use EJBs in the constructor. They are not injected at that point. It's in Java impossible to set an instance variable before the instance is constructed. You should instead be using @PostConstruct. The container will invoke it directly after construction and dependency injection.

This is right:

@EJB
private StepsFacade stepsFacade;

@EJB
private CategoriesFacade categoryFacade;

@PostConstruct
public void init() { // Note: method name is fully to your choice.
    createCategoryModel();
}

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • thank you so much!! I was stuck like a stick in the mud there! – fusion27 May 23 '13 at 16:13
  • I have used `@PostConstruct` annotation after injecting my beans, but still getting null pointer exception. – JIT Develop Jan 21 '16 at 05:15
  • @JIT: You're then having a different problem than asked. For example, you're using Spring instead of JSF to manage beans. Obviously, different rules apply. You should read Spring documentation/instructions and not Java EE's. – BalusC Jan 21 '16 at 09:40