0

I am trying to execute some selects in my DAO class but I got no success after reading a lot of similar questions but with different setups.

I keep getting EntityManager null which throws java.lang.NullPointerException.

Please check here https://github.com/famibica/challenge if you want to take a look at the entire project.

This is my ChallengeApplication class:

import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
@Configuration
public class ChallengeApplication {

    public static void main(String[] args) {
        SpringApplication.run(ChallengeApplication.class, args);
    }

    static final String responseExchange = "response.exchange";
    static final String routingKey = "response.routing.key";
    static final String insertionQueue = "insertion.queue";
    static final String validationQueue = "validation.queue";

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        return connectionFactory;
    }

    @Bean
    Queue queueInsertion() {
        return new Queue(insertionQueue, true);
    }

    @Bean
    Queue queueValidation() {
        return new Queue(validationQueue, true);
    }

    @Bean
    DirectExchange exchange() {
        return new DirectExchange(responseExchange);
    }


@Bean
SimpleMessageListenerContainer messageListenerContainerInsertion() {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(connectionFactory());
    container.setConcurrentConsumers(3);
    container.setQueueNames(insertionQueue);
    container.setMessageListener(new ListenerInsertion());
    return container;
}

@Bean
SimpleMessageListenerContainer messageListenerContainerValidation() {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(connectionFactory());
    container.setConcurrentConsumers(3);
    container.setQueueNames(validationQueue);
    container.setMessageListener(new ListenerValidation());
    return container;
}

}

My DAO interface:

import java.util.Collection;
import java.util.List;
import java.util.Optional;

public interface DAO<T> {

    Optional<T> get(long id);

    Collection<T> getAll();

    List<T> getList(String[] params);

    T getSpecific(T t);

    boolean save(T t);

    void update(T t, String[] params);

    boolean delete(T t);
}

My DAO Class:

import java.util.Collection;
import java.util.List;
import java.util.Optional;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

import org.springframework.amqp.rabbit.support.ListenerExecutionFailedException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public class WhitelistDAO implements DAO<Whitelist> {

    @PersistenceContext
    private EntityManager em;
    //EntityManagerFactory emf;
    //EntityManager em = emf.createEntityManager();

    @Override
    public Collection<Whitelist> getAll() {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Whitelist> criteria = cb.createQuery(Whitelist.class);
        Collection<Whitelist> resultList = em.createQuery(criteria).getResultList();
        return resultList;
    }

    @Override
    public List<Whitelist> getList(String[] params) {
        TypedQuery<Whitelist> query = em.createQuery("SELECT c FROM Whitelist c WHERE (c.client = ?1 OR c.client = 'global')", Whitelist.class);
        query.setParameter(1, params[0]);

        try {
            return query.getResultList();
        } catch (IllegalStateException | PersistenceException e) {
            return null;
        }
    }

    @Override
    public Whitelist getSpecific(Whitelist t) {
        TypedQuery<Whitelist> query = em.createQuery("SELECT c FROM Whitelist c WHERE (c.client = ?1 OR c.client = 'global') and regex = ?2", Whitelist.class);
        query.setParameter(1, t.getClient());
        query.setParameter(2, t.getRegex());
        query.setMaxResults(1);

        try {
            return query.getSingleResult();
        } catch (NoResultException e) {
            System.out.println("Null1");
            return null;
        } catch (ListenerExecutionFailedException e) {
            System.out.println("Error");
            System.err.println(e);
        }
        System.out.println("Null2");
        return null;
    }


    @Override
    @Transactional
    public boolean save(Whitelist t) {
        try {
            this.em.persist(t);
            return true;
        } catch (Exception e) {
            return false;
        }       
    }

    @Override
    public Optional<Whitelist> get(long id) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    @Transactional
    public void update(Whitelist t, String[] params) {
        // TODO Auto-generated method stub

    }

    @Override
    @Transactional
    public boolean delete(Whitelist t) {
        return false;

    }
}

I did try in the DAO class to create an Entity Manager like this, but then I had many other errors together:

EntityManagerFactory emf;
EntityManager em = emf.createEntityManager();

This is where I am calling the whitelistDAO:

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;

import com.google.gson.Gson;
import com.google.gson.JsonParseException;

@EnableAutoConfiguration
@Component
public class ListenerInsertion implements MessageListener {

    @Autowired
    private static DAO<Whitelist> whitelistDAO = new WhitelistDAO();

    @Override
    public void onMessage(Message message) {
        System.out.println("Received Insertion: " + new String(message.getBody()) + " From: "
                + message.getMessageProperties().getReceivedRoutingKey());
        try {
            InputData inputData = new Gson().fromJson(new String(message.getBody()), InputData.class);
            System.out.println("InputData: " + inputData);
            receivedInsertion (inputData);
        } catch (JsonParseException e) {
            System.out.println("It was not possible to read the input");
        }
    }

    @TransactionalEventListener
    public void receivedInsertion(InputData inputData) {
        Whitelist whitelist = new Whitelist();
        String client = inputData.getClient();

        if (client == null) {
            whitelist.setClient("global");
        } else {
            whitelist.setClient(inputData.getClient());
        }
        whitelist.setRegex(inputData.getRegex());

        System.out.println("Received Insertion Whitelist: " + whitelist);
        try {
            // Forçando assim funciona
            // A estrutura da tabela whitelist
            // String client, String regex (igual a classe Whitelist)
            // --------------------------------------------------------
//          String query = "select * from whitelist limit 1";
//          Class.forName("com.mysql.cj.jdbc.Driver");
//          Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/axr_challenge","root","secret");
//          Statement st = con.createStatement();
//          ResultSet rs = st.executeQuery(query);
//          rs.next();
//          String result = rs.getString("client");
//          System.out.println("Result: " + result);
            // --------------------------------------------------------
            //System.out.println("ENTITY MANAGER----> " + em);
            Whitelist selectedWhitelist = whitelistDAO.getSpecific(whitelist);
            System.out.println("selectedWhitelist: " + selectedWhitelist);
//          if (selectedWhitelist == null || !selectedWhitelist.equals(whitelist)) {
//              whitelistDAO.insertWhitelist(whitelist);
//              System.out.println("Whitelist Added");
//          } else {
//              System.out.println("Already added before");
//          }
//
        } catch (NullPointerException dae) {
            System.out.println("Whitelist NOT Added");
            System.err.println(dae);
        }
    }

}

Here I tried to connect directly to the database itself, and it worked and executed the select, I also checked that the connection to the database is done, changing a password in the application.properties, for example, would throw an error about the wrong password.

        String query = "select * from whitelist limit 1";
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/axr_challenge","root","secret");
        Statement st = con.createStatement();
        ResultSet rs = st.executeQuery(query);
        rs.next();
        String result = rs.getString("client");
        System.out.println("Result: " + result);

If anybody could help me I would be grateful.

Thank you!

Matheus Bica
  • 1,055
  • 3
  • 13
  • 23
  • Don't use `static` for anything stateful. Don't use `new` except in an `@Bean` method (and avoid those unless you have to do particular preprocessing). Use constructor injection. You can _probably_ let Boot configure your RabbitMQ components, and you _definitely_ can use Spring Data JPA to autogenerate your DAO instead of writing it yourself. – chrylis -cautiouslyoptimistic- Apr 18 '20 at 08:25
  • 1
    Check out Spring Data JPA. You just write an interface, and Spring Data provides the implementation. (Also note that it's almost never a good idea to be manually opening database connections yourself, since those are usually handled for you by the framework. Simply use Spring Boot properties to configure the `DataSource`, and everything should work.) – chrylis -cautiouslyoptimistic- Apr 18 '20 at 21:33
  • I solved my issue, the issue was in what Chrylis said, I removed the creation using new(specifically in the ChallengeApplication.java from the Listeners) and then it worked =D – Matheus Bica Apr 18 '20 at 22:14

0 Answers0