4
respostas

[Dúvida] Exceção: NullPointerException(CategoryRepository.saveAll(java.lang.Iterable)

durante a pratica do desafio, encontrei a seguinte exceção:
java.lang.NullPointerException: Cannot invoke "com.example.gerenciador_pedidos.repository.CategoryRepository.saveAll(java.lang.Iterable)" because "this.categoryRepository" is null

a exceção redireciona a causa para a classe Main:

//Main

@Component
public class GerenciadorPedidos{
//nome refatorado
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private CategoryRepository categoryRepository;
   
    public void Gerenciador() {
    //metodo refatorado
        Category eletronics = new Category(1L, "Eletronics");
        Category tools = new Category(2L, "Tools");

        Product notebook = new Product(4500.0,"Notebook", eletronics);
        Product smartphone = new Product(2500.0, "Smartphone", eletronics);
        Product watch = new Product(750.0, "Watch", eletronics);
        Product powerScrewdriver = new Product(300.0, "Power Screwdriver", tools);

        eletronics.setProduct(List.of(notebook, smartphone, watch));
        tools.setProduct(List.of(powerScrewdriver));

        categoryRepository.saveAll(List.of(eletronics, tools));

        System.out.println("Categorias e produtos: ");
        categoryRepository.findAll().forEach(category -> {
            System.out.println("Categorias: " + category.getName());
            category.getProduct().forEach(product -> System.out.println("Produtos: " + product.getName()));
        });
     //   Requests requests = new Requests(1L, LocalDate.now());
    }
}
//modelos:
@Entity
public class Category {

    @Id
    private Long id;

    private String name;

    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
    private List<Product> product;

    public Category(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public List<Product> getProduct() {
        return product;
    }

    public void setProduct(List<Product> product) {
        this.product = product;
    }

    public Category() {
    }
}


@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false, unique = true)
    private String name;
    @Column(name = "value")
    private double price;
    @ManyToOne
    @JoinColumn(name = "category_id")
    private Category category;

    public Product(double price, String name, Category category) {
        this.price = price;
        this.name = name;
        this.category = category;
    }
    public Long getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public double getPrice() {
        return price;
    }
    public Category getCategory() {
        return category;
    }

    public Product() {
    }
}

//Repositórios:
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {}

@Repository
public interface CategoryRepository extends JpaRepository<Category, Long> {}
4 respostas

Olá Davi! Como vai?

O problema está ocorrendo porque a instância de CategoryRepository está nula no momento em que você tenta chamá-la no método Main. Isso geralmente acontece quando o Spring não consegue injetar a dependência corretamente.

Aqui estão algumas sugestões para resolver o problema:

  1. Verifique a Anotação @Component: Certifique-se de que a classe Main está sendo gerenciada pelo Spring. A anotação @Component está correta, mas você precisa garantir que a classe Main está sendo escaneada pelo Spring. Isso pode ser feito verificando se o pacote onde a classe Main está localizada está incluído no escaneamento de componentes do Spring.

  2. Construtor da Classe Main: Parece que você está tentando usar um método chamado Main como construtor, mas em Java, o construtor deve ter o mesmo nome da classe e não deve ter um tipo de retorno. Corrija o nome do método para que seja o construtor da classe:

    @Component
    public class Main {
        @Autowired
        private ProductRepository productRepository;
        @Autowired
        private CategoryRepository categoryRepository;
    
        // Construtor sem tipo de retorno
        public Main() {
            // Seu código aqui...
        }
    }
    
  3. Inicialização do Contexto Spring: Certifique-se de que sua aplicação está sendo executada em um contexto Spring. Se você estiver usando uma aplicação Spring Boot, a classe principal deve estar anotada com @SpringBootApplication e você deve iniciar a aplicação com SpringApplication.run().

  4. Teste a Injeção de Dependência: Verifique se as dependências estão sendo injetadas corretamente. Você pode adicionar um método @PostConstruct na sua classe Main para verificar se os repositórios estão sendo injetados corretamente:

    @PostConstruct
    public void init() {
        if (categoryRepository == null) {
            System.out.println("categoryRepository não foi injetado!");
        } else {
            System.out.println("categoryRepository foi injetado com sucesso!");
        }
    }
    

Essas são algumas dicas que podem ajudar a resolver o problema.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

Boa noite.
após usar suas dicas, descobri mais alguns problemas, ainda relacionado á injeção de dependencia:

  • A classe Main não estava sendo escaneada.
    • Quando foi feita a correção do método para construtor, passou a retornar mais duas exceções: "BeanCreationException e "BeanInstantiationException".
  • Minha aplicação está sendo está sendo executada num ambiente Spring, especificamente "Spring sem Boot"
  • As dependencias não foram injetadas, e "init()" retorna false na inicialização, e true ao finalizar.

Não tenho certeza como posso solucionar as novas exceções, porém no modelo anterior (method), decidi corrigir o nome para evitar confusão futura. Aceito orientação na possivel resolução da Exceção.

Oi, Davi!

O erro NullPointerException continua porque, no seu cenário com Spring sem Boot, a injeção com @Autowired não funciona automaticamente se a classe GerenciadorPedidos não for registrada corretamente no ApplicationContext.

A solução aqui é clara: você precisa criar e registrar manualmente o contexto do Spring e obter o bean da classe GerenciadorPedidos, para que as injeções @Autowired funcionem.

Veja como ajustar isso:

  1. Crie uma classe de configuração ou use uma já existente com @ComponentScan:

    
     @Configuration
     @ComponentScan(basePackages = "com.example.gerenciador_pedidos")
     public class AppConfig {
     }
     
  2. Crie uma classe Main para iniciar o contexto e executar o método desejado:

    
     public class Main {
         public static void main(String[] args) {
             AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    
             GerenciadorPedidos gerenciador = context.getBean(GerenciadorPedidos.class);
             gerenciador.executar(); // método renomeado para refletir que é uma ação, não um construtor
    
             context.close();
         }
     }
     
  3. Altere o método Gerenciador() para um nome válido de método (não construtor):

    
     @Component
     public class GerenciadorPedidos {
         @Autowired
         private ProductRepository productRepository;
    
         @Autowired
         private CategoryRepository categoryRepository;
    
         public void executar() {
             Category eletronics = new Category(1L, "Eletronics");
             Category tools = new Category(2L, "Tools");
    
             Product notebook = new Product(4500.0,"Notebook", eletronics);
             Product smartphone = new Product(2500.0, "Smartphone", eletronics);
             Product watch = new Product(750.0, "Watch", eletronics);
             Product powerScrewdriver = new Product(300.0, "Power Screwdriver", tools);
    
             eletronics.setProduct(List.of(notebook, smartphone, watch));
             tools.setProduct(List.of(powerScrewdriver));
    
             categoryRepository.saveAll(List.of(eletronics, tools));
    
             System.out.println("Categorias e produtos: ");
             categoryRepository.findAll().forEach(category -> {
                 System.out.println("Categorias: " + category.getName());
                 category.getProduct().forEach(product -> System.out.println("Produtos: " + product.getName()));
             });
         }
     }
     

Resumo do que foi feito:

  • Você passou a usar um ApplicationContext padrão do Spring para carregar os beans.
  • O método Gerenciador() foi renomeado para executar() para evitar conflito com o construtor.
  • A anotação @ComponentScan garante que GerenciadorPedidos seja reconhecido como bean.

Fico à disposição.

Boa tarde e obrigado pela ajuda desde já!
após registrar as mudanças no código, dessa vez retorna o erro:

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-08-05T17:05:25.063-03:00 ERROR 24629 --- [gerenciador-pedidos] [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class


Action:

Consider the following:
    If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
    If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

Pela descrição do erro, suponho que seja algo haver com as propriedades da aplicação:

//application.properties

spring.application.name=gerenciador-pedidos
hibernate.dialect=org.hibernate.dialect.HSQLDialect
//username e senha omitidos

spring.datasource.url=jdbc:postgresql://localhost/gerenciador-pedidos
hibernate.transaction.jta.platform
spring.jpa.hibernate.ddl-auto=update
spring.datasource.driver-class-name=org.postgresql.Driver

Tentei procurar sobre o erro e não encontrei informação sobre a integraç