Issue
So I've been learning Spring for a few weeks. I am trying to make a simple project involving a Controller -> Service -> Repository -> Database pattern.
I started having this problem, but could not find the solution to it. I stumbled upon some similar problems online with the same error, but none of them gave my solution, everything seems normal in my project.
This is the error on output:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field repository in com.Library.services.LibraryService required a bean named 'entityManagerFactory' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean named 'entityManagerFactory' in your configuration.
This are the files of my project (file tree):
This is my code:
Main class:
package com.Library;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EntityScan("com.Library.services")
@EnableJpaRepositories("com.Library.repositories")
public class LibraryApplication {
public static void main(String[] args) {
SpringApplication.run(LibraryApplication.class, args);
}
}
Model:
package com.Library.models.dtos;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
@Getter
@Setter
@Entity
public class BookCategory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
private String Name;
}
Repository:
package com.Library.repositories;
import com.Library.models.dtos.BookCategory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface BookCategoryRepository extends JpaRepository<BookCategory,Long> {
List<BookCategory> findAll();
}
Service:
package com.Library.services;
import com.Library.models.dtos.BookCategory;
import com.Library.repositories.BookCategoryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class LibraryService {
@Autowired
BookCategoryRepository repository;
public List<BookCategory> getAllCategories() {
return repository.findAll();
}
}
Controller:
package com.Library.controllers;
import com.Library.models.dtos.BookCategory;
import com.Library.services.LibraryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
public class LibraryController{
@Autowired
LibraryService libraryService;
public List<BookCategory> getAllCategories() {
return libraryService.getAllCategories();
}
}
What could be the issue?
Solution
This bean definition is usually provided automatically by Spring Boot Auto-Configuration. The spring reference manual explains how to diagnose such issues:
The Spring Boot auto-configuration tries its best to “do the right thing”, but sometimes things fail, and it can be hard to tell why.
There is a really useful ConditionEvaluationReport available in any Spring Boot ApplicationContext. You can see it if you enable DEBUG logging output. If you use the spring-boot-actuator (see the Actuator chapter), there is also a conditions endpoint that renders the report in JSON. Use that endpoint to debug the application and see what features have been added (and which have not been added) by Spring Boot at runtime.
Many more questions can be answered by looking at the source code and the Javadoc. When reading the code, remember the following rules of thumb:
- Look for classes called
*AutoConfiguration
and read their sources. Pay special attention to the@Conditional*
annotations to find out what features they enable and when. Add--debug
to the command line or a System property-Ddebug
to get a log on the console of all the auto-configuration decisions that were made in your app. In a running application with actuator enabled, look at the conditions endpoint (/actuator/conditions
or the JMX equivalent) for the same information.
In your case, a simple full text search finds that Hibernate is auto-configured by org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
, which is declared as follows:
@AutoConfiguration(after = { DataSourceAutoConfiguration.class })
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class, SessionImplementor.class })
@EnableConfigurationProperties(JpaProperties.class)
@Import(HibernateJpaConfiguration.class)
public class HibernateJpaAutoConfiguration {
}
As you can tell from the ConditionalOnClass annotation, this configuration is only applied if your classpath contains the classes LocalContainerEntityManagerFactoryBean
from spring-orm-jpa, EntityManager
from the JPA spec, and SessionImplementor
from the hibernate jar.
Most likely, you are missing one of these JAR files (maven dependencies), or have the wrong version of one. The ConditionEvaluationReport should tell you which, and the precise package names to check for.
Answered By - meriton
Answer Checked By - Mary Flores (JavaFixing Volunteer)