Nullpointerexception Java JPA CDI Tomcat

Asked

Viewed 720 times

6

Good afternoon guys. I am developing a Java test application with JPA, CDI and Tomcat. I created a basic test class and am getting the following error.

Erro: Exception in thread "main" java.lang.NullPointerException
    at br.com.hcancerbarretos.espec.dao.EspecialidadesDAO.getEspecialidades(EspecialidadesDAO.java:16)
    at br.com.hcancerbarretos.espec.testes.Teste.main(Teste.java:13)

To EspecialidadeDAO is null, is not being injected correctly with the @Inject. The strange thing is that if I create a JSF page and display the values in a datatable, all that has @Inject is injected normally. I also created a Webservice class called Specialties, where the Specialty Dependency injection does not work.

Can anyone tell me how to fix it? Why? Any output? Below are the files and classes.

Model class:

import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;

@Entity
@NamedQuery(name="Especialidade.findAll", query="SELECT e FROM Especialidade e")
public class Especialidade implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="ESPECEALIDADE_ID")
    private long especialidadeId;

    private String descricao;

    @Temporal(TemporalType.DATE)
    @Column(name="DT_ALT")
    private Date dtAlt;

    @Temporal(TemporalType.DATE)
    @Column(name="DT_INCL")
    private Date dtIncl;

    private String sigla;

    @Column(name="USU_ALT")
    private String usuAlt;

    @Column(name="USU_INCL")
    private String usuIncl;

    public Especialidade() {
    }

    //getters and setters ...
}

Class code Speciality.

import java.util.List;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import br.com.hcancerbarretos.espec.model.Especialidade;

public class EspecialidadesDAO {

    @Inject
    private EntityManager em;

    public List<Especialidade> getEspecialidades() {
        return em.createNamedQuery("Especialidade.findAll", Especialidade.class).getResultList();
    }

    public String getEspecialidadePorCodigo(long codigo) {
        return em.createQuery("select e.descricao From Especialidade e Where e.especialidadeId = :codigo", String.class)
                .setParameter("codigo", codigo).getSingleResult();
    }
}

Class EntityManagerProducer:

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

@ApplicationScoped
public class EntityManagerProducer {

    private EntityManagerFactory factory;

    public EntityManagerProducer() {
        this.factory = Persistence.createEntityManagerFactory("Especialidade");
    }

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

    public void closeEntityManager(@Disposes EntityManager manager) {
        manager.close();
    }

}

Test class:

import java.util.List;
import br.com.hcancerbarretos.espec.dao.EspecialidadesDAO;
import br.com.hcancerbarretos.espec.model.Especialidade;

public class Teste {

    public static void main(String[] args) {        
        EspecialidadesDAO dao = new EspecialidadesDAO();
        List<Especialidade> especialidades = dao.getEspecialidades();        
    }
}

Class Especialidadews.

import javax.inject.Inject;
import br.com.hcancerbarretos.espec.dao.EspecialidadesDAO;

public class EspecialidadeWS {

    @Inject
    private EspecialidadesDAO dao;

    public String getEspecialidade(long codigo){
        System.out.println("DAO " + dao);
        return dao.getEspecialidadePorCodigo(codigo);
    }   
}

Filing cabinet web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">

    <display-name>Especialidade</display-name>

    <welcome-file-list>
        <welcome-file>index.jsf</welcome-file>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
    </listener>
    <resource-env-ref>
        <resource-env-ref-name>BeanManager</resource-env-ref-name>
        <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
    </resource-env-ref>

</web-app>

Filing cabinet META-INF\context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <!-- disables storage of sessions across restarts -->
    <Manager pathname="" />
    <Resource name="BeanManager" auth="Container"
        type="javax.enterprise.inject.spi.BeanManager" factory="org.jboss.weld.resources.ManagerObjectFactory" />
</Context>

The archive beans.xml is created, but empty, as recommended.

  • 1

    If the exception is occurring in line 16 of the Specialties, then it must have been injected, and the error may be in it. Could also paste the code of Specialties?

  • Debugging the application I check that the Entitymanager was not injected. I put the code of the class just below Victor. Thanks.

3 answers

0

try this

public class EspecialidadeWS {

    @Inject
    private EspecialidadesDAO dao;

    public String getEspecialidade(long codigo){
        try{
            String codigo = dao.getEspecialidadePorCodigo(codigo);
            return codigo;
        }catch (NullPointerException e) {
            // TODO: handle exception
            return ''
        }
    }   
}

You are not treating the code in case the specialty does not exist. Another thing I could observe is that the attribute "description" and others is not mapped in its entity. Map...

@Column(name="ESPECEALIDADE_ID")
private String descricao;

0

If you are trying to use the main method will not work!

Because: You’re using a resource called CDI, which is basically a module running in your application container that whenever an instance annotated with @EJB or @Inject is used it intercepts the thread and passes an instance it creates itself, or reuses. Basically speaking, running on Tomcat is he who makes a "new Object()" in the entityManager inside Specialtyfor you.

Running on main you will have to create the instance of Entitymanager using Entitymanagerfactory and pass it into your Expertise, just because there’s no little robot doing the job for you.

  • Thank you for the reply Cleiton. What I find strange is the following, with the JSF page works because Tomcat is in the air, but if I have a Webservice class inside that injects the Specialization with @Inject for example, this also does not work, even with Tomcat in the air. Theoretically if the CDI problem doesn’t work is the container isn’t in the air, in this case I mentioned it should work right? At first I thought CDI only worked with Java EE application servers (Wildfly, Glassfish)but then I saw that it also works with Servlet container like Tomcat.

  • @Reginaldo, if you are trying to run by the main method, it will not work, regardless of whether the server is up or not is another jvm running.

  • @Cleitoncardoso I don’t quite understand why this doesn’t work in the Test class. And another question, regarding the class of Webservice Specialties I also could not work, can you tell me why and help me with some hint? Currently the dependency injection is working only in views with JSF. Thanks.

  • @Reginaldo, I updated the answer, take a look.

  • @Cleitoncardoso thank you very much for the reply, I understood right because it does not work in main. But thinking of the Webservice class (Specialties), it is managed by Axis in my case. When a request is made for this webservice, can’t Tomcat use CDI to create these instances as in JSF for example? Thank you.

  • Is your project in any public place? If not, can you put it? So it is easier for someone to download and test to see what is happening.

Show 1 more comment

0

Write down your class EspecialidadeWS with @javax.enterprise.context.RequestScoped to function as web service.

EDIT:

In my projects I use the Resteasy together with the CDI to run the injection you want. Come on: you also need to create, in your project, a class that extends the javax.ws.rs.core.Application:

package abc;

import abc.EspecialidadeWS;

import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;

public class AppRs extends Application {

    private Set<Class<?>> classes;

    public AppRs() {
        classes = new HashSet<>();
        classes.add(EspecialidadeWS.class);
    }

    @Override
    public Set<Class<?>> getClasses() {
        return classes;
    }
}

In the web.xml:

<!--  RESTEasy  -->
<listener>
    <listener-class>
        org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
    </listener-class>
</listener>
<servlet>
    <servlet-name>RESTEasy Servlet</servlet-name>
    <servlet-class>
        org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
    </servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>br.com.t2tecnologia.AppRs</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>RESTEasy Servlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/rest</param-value>
</context-param>
<context-param>
    <param-name>resteasy.injector.factory</param-name>
    <param-value>org.jboss.resteasy.cdi.CdiInjectorFactory</param-value>
</context-param>

In the pom.xml (Maven):

<!--  CDI (esse você já deve ter)  -->
<dependency>
    <groupId>org.jboss</groupId>
    <artifactId>jandex</artifactId>
    <version>2.0.1.Final</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.jboss.weld.servlet</groupId>
    <artifactId>weld-servlet</artifactId>
    <version>2.3.2.Final</version>
    <scope>runtime</scope>
</dependency>
<!--  RESTEasy  -->
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxrs</artifactId>
    <version>3.0.16.Final</version>
</dependency>
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-servlet-initializer</artifactId>
    <version>3.0.16.Final</version>
</dependency>
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-cdi</artifactId>
    <version>3.0.16.Final</version>
</dependency>
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jackson-provider</artifactId>
    <version>3.0.16.Final</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

Class EspecialidadeWS:

@Path("/especialidade")
@GET
public class EspecialidadeWS {

    @Inject private EspecialidadesDAO dao;

    @GET
    @Path("/get/{codigo}")
    public String getEspecialidade(@PathParam("codigo") long codigo){
        return dao.getEspecialidadePorCodigo(codigo);
    }   
}

Finally, write down EspecialidadeWS also with @javax.ws.rs.Path("/especialidade"). If everything works, you should be able to access your web service via http://localhost:8080/seu_projeto/Rest/especialidade/get/1, for example.

  • Victor, I noted the Specialties class with @javax.enterprise.context.Requestscoped and it didn’t work. I also noted the Speciality class only for testing, but it also didn’t work.

  • In your project, you created a class that extends to javax.ws.rs.core.Application?

  • I didn’t, I’m sorry I didn’t, but what’s the point? I created this Webservice class and went to Eclipse (Ctrl+N > Web service) to generate web service with Axis.

  • It turns out that the JSF Give yourself the dependency shot. However, when we call a web service, we are in a "no-owner" place where you need Resteasy or similar to handle web service calls. I prefer Resteasy because it is really easy and use and has integration with CDI, besides converting entities into JSON/XML and vice versa automatically.

  • In this case I need to be SOAP even, due to the communication I must make with another webservice, from a third company, which is SOAP.

  • I have worked on a project with Resteasy and Wildfly, but in this case I need it to be SOAP itself, due to the pattern of another webservice that I will have to communicate. In WS SOAP with Wildlfy I was annotating the class as Webservice and Webmethod for the methods, but using Wildfly. In the case with Tomcat, I had to perform the generation of the webservice through the Eclipse Wizard, at least that’s what I did and it worked, but without using CDI. In that case for me to create WS SOAP with CDI and Tomcat, what else would I have to do? Thank you.

  • With these settings I gave you, it would also work on Tomcat 7 or 8. With Axis, I don’t think I can make it work with CDI, but I’m not sure... You will be in charge of good research. Good luck!

  • I understand, it may be that the problem in this case is Axis then. You have already worked with Webservice SOAP using Tomcat or Wildfly with CXF?

  • I’ve never worked with CXF. I have SOAP web services projects in Glassfish 3, and with REST web services in Tomcat 7/8 and Wildfly 8.2+ (these using JSF, JPA, CDI (Weld) and Resteasy).

  • Quiet. Thank you so much for your help.

Show 5 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.