2

I've the below managed bean

@ManagedBean
@RequestScoped
public class customerBean {

    private Customer customer;
    private CustomerJpaController customerJpa;

    @PostConstruct
    public void init() {
        customer = new Customer();
    }

    public String addCustomer() throws Exception {
        customerJpa.create(customer);
        return "customer";
    }

    // getter and setter
}

The CustomerJpaController looks like below:

public class CustomerJpaController implements Serializable {

    @PersistenceContext(unitName = "JFSCustomerPU")
    private EntityManagerFactory emf = null;
    private UserTransaction utx = null;

    public CustomerJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }

    // ...
}

When addCustomer() is invoked from the view, it throws java.lang.NullPointerException at line customerJpa.create(customer);. How is this caused and how can I solve it?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Anh Tran
  • 59
  • 4
  • 1
    You have to `@Inject` this JPA or create somehow instance of it because variable `customerJpa` is null, you don't initialize it. – Geinmachi Sep 26 '15 at 09:53

2 Answers2

1

In your code sample, your CustomerJpaController is never instantiated. So, you get a null pointer exception.

I advise you to switch to CDI and rely on its injection method to have your entity manager (factory?) properly instantiated and injected in your controller when this last is instantiated. And, so, to use @Named instead of @ManagedBean.

So, you would have :

@Named
@RequestScoped
public class CustomerJpaController implements Serializable {
    ...
}

(or whichever scope better fits your need)

It seems to me that you should use an EntityManager (EM) rather than an EntityManagerFactory (EMF) in your controller.

If your EMF is container managed and you have only one persistence unit, you can use the standard JPA @PersistenceContext annotation :

@PersistenceContext
private EntityManager entityManager;

If your EMF is not managed, you can leverage the power of deltaspike JPA module (remember : deltaspike is good for you :-) ) and inject an EntityManager in your controller :

@Named
@RequestScoped
public class CustomerJpaController implements Serializable {
    @Inject
    private EntityManager em;
}

This requires the implementation of an EntityManagerProducer class, which can have any name but must have one method annotated @Produces @RequestScoped returning an EntityManager and another one taking an EntityManager parameter annotated with @Disposes. Ex :

public class MyEntityManagerProducer {

    @Inject
    @PersistenceUnitName("myPU")
    private EntityManagerFactory emf;

    @Produces
    @RequestScoped
    public EntityManager createEntityManager() {
        return emf.createEntityManager();
    }

    public void disposeEntityManager(@Disposes em) {
        if (em.isOpen()) {
            em.close();
        }
    }

Note the usage of @PersistenceUnitName("myPU"), the deltaspike annotation that will handle the instanciation of the EMF.

If you have multiple persistence units, as it is often the case in the real world, you can set them apart with qualifiers. To declare a qualifier, declare an @interface with the following annotations :

@Target({ FIELD, METHOD, PARAMETER, TYPE }) 
@Retention(RUNTIME) 
@Documented 
@Qualifier 
public @interface MyQualifier {
}

Then, add this qualifier to all @Produces, @Disposes and @Inject, to allow CDI to decide which persistence unit / entity manager you are willing to use :

public class MyEntityManagerProducer {

    @Inject
    @PersistenceUnitName("myPU")
    private EntityManagerFactory emf;

    @Produces
    @MyQualifier
    @RequestScoped
    public EntityManager createEntityManager() {
        return emf.createEntityManager();
    }

    public void disposeEntityManager(@Disposes @MyQualifier em) {
        if (em.isOpen()) {
            em.close();
        }
    }

and in your controller :

@Named
@RequestScoped
public class CustomerJpaController implements Serializable {
    @Inject
    @MyQualifier
    private EntityManager em;
}

All this requires CDI. Configuring CDI is way beyond a short answer to your question. I use OpenWebBeans in all my projects. Weld is also very popular.

Ludovic Pénet
  • 1,136
  • 1
  • 16
  • 32
0

This is my understanding of things (it might not be 100% correct but it will give you a general idea) :

Where in your bean is your Service instantiated ? Nowhere. In other words customerJpa is null. Starting a connection to a db weights a lot on resources. So instead of you instantiating different services by yourself and opening-closing connections, the container has a pool of services and give the free ones to whoever needs it (in your case your bean needs one). How do you ask the container to give you a service :

Annotate @EJB above your service:

@EJB
private CustomerJpaController customerJpa;

and I think you are missing @Stateless as well

@Stateless
public class CustomerJpaController...

It's advised to switch to @Named and @RequestScoped (the other package) instead of @ManagedBean. Then you can use @Inject to inject your service instead of @EJB.here you can read further on the subject.

Community
  • 1
  • 1
Ced
  • 15,847
  • 14
  • 87
  • 146