1

I am learning Spring Framework and now I am trying to make a simple Spring Boot application that would list all entries from a database (using Hibernate).

First I had a problem when SessionFactory would not be defined, but I managed to define it in Config Class. However, when I try to run the app now, I get the following error:

Description:

The dependencies of some of the beans in the application context form a cycle:

   indexController (field private com.prvi.dao.CustomerDAO com.prvi.controllers.IndexController.customerDAO)
      ↓
   customerDAOImpl (field private org.hibernate.SessionFactory com.prvi.dao.CustomerDAOImpl.sessionFactory)
┌─────┐
|  sessionFactory defined in class path resource [com/prvi/ConfigPrvi.class]
└─────┘

Basically, I have IndexController, who gets GET / request, then it calls customerDAO to get list of customers and customerDAO uses sessionFactory to get Session and performs a query on DB. (I have omitted Service layer from the app for sake of simplicity)

Now, I have read that this error happens when a bean is dependent on a bean that is dependent on a first bean, making cyclical dependency. However, I do not understand where I made this cycle and how to fix it. Also, other answers on this topic have not provided me enough information to correct the error. They were mostly oversimplifies where cycle is clear, which is not the case here.

Here is what I have tried so far:

PrviApplication.java - entry point for Spring Boot

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

ConfigPrvi.java - My Configuration file

@Configuration
@EnableAutoConfiguration
public class ConfigPrvi {
    @Bean
    public HibernateJpaSessionFactoryBean sessionFactory(EntityManagerFactory emf){
        HibernateJpaSessionFactoryBean factory = new HibernateJpaSessionFactoryBean();
        factory.setEntityManagerFactory(emf);
        return factory;
    }
}

IndexController.java - my Controller class, which handles GET /

@Controller
@RequestMapping("/")
public class IndexController {

    @Autowired
    private CustomerDAO customerDAO;

    @GetMapping("/")
    public String listCustomers(Model model){
        model.addAttribute("customers", customerDAO.getAllCustomers());
        return "index";
    }
}

CustomerDAO.java - just an interface

public interface CustomerDAO {
    public List<Customer> getAllCustomers();
}

CustomerDAOImpl.java - implementation, retrieves data from database

@Repository
public class CustomerDAOImpl implements CustomerDAO {

    @Autowired
    private SessionFactory sessionFactory;

    @Transactional
    public List<Customer> getAllCustomers(){
        Session session = sessionFactory.getCurrentSession();
        Query<Customer> query = session.createQuery("from Customer order by lastName", Customer.class);
        List<Customer> customers = query.getResultList();
        return customers;
    }
}

Is it perhaps that cycle was made here:

main --> controller --> dao --> sessionFactory --> config --> main

If so, how can I rewrite the code so that I get rid of it?

EDIT: Added pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.prvi</groupId>
    <artifactId>prvi</artifactId>
    <version>0.0.1</version>
    <packaging>jar</packaging>

    <name>prvi</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.2.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.2.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>
Miha Jamsek
  • 1,193
  • 2
  • 17
  • 33
  • Circular logic in my code generally means that I am not looking at the problem correctly and that's lead to an overall design logic flaw. – Rabbit Guy Jul 07 '17 at 18:40
  • Can you share the error log with us? Also, the service layer... – Stefa Jul 07 '17 at 18:44
  • @ŠtefFoReal The error is right there at the beginning of their post. What service layer? They have a controller that uses a dao directly. – Sotirios Delimanolis Jul 07 '17 at 18:46
  • In an idiomatic spring-boot/-data app you don't implement the DAO class, see https://spring.io/guides/gs/accessing-data-jpa/ (spring-data auto-implements every `CrudRepository` it finds). And you would probably not even define any hibernate related beans because boot autoconfigures things when it finds them on the classpath. – zapl Jul 07 '17 at 18:48
  • @SotiriosDelimanolis he said: 'I have omitted Service layer for sake of simplicity'. It ain't clear if he omitted it from the post or from the app. – Stefa Jul 07 '17 at 18:50
  • @ŠtefFoReal I omitted Service from app. Here is error log https://1drv.ms/t/s!As69yfwJGiingaggOBTJR4Mh15o0gQ – Miha Jamsek Jul 07 '17 at 18:51
  • @zapl So the problem was, because I tried to do it Spring MVC way in Spring Boot project? – Miha Jamsek Jul 07 '17 at 18:54
  • @MihaJamsek please share maven dependencies with us. – Stefa Jul 07 '17 at 18:57
  • @ŠtefFoReal pom.xml added to question – Miha Jamsek Jul 07 '17 at 18:59
  • @MihaJamsek no, unrelated to MVC, that's still used and it's the component responsible for `@Controller`s and such. What "spring-boot" adds is autoconfiguration and spring projects before boot had typically lots of them, your own hibernate config, etc. What ["spring-data(-jpa)"](http://projects.spring.io/spring-data-jpa/) does is to implement all the repository logic for you, you just need to define an interface. You can use bare spring projects with your own spring-data configuration, or you can use spring-boot with spring-data to have all the configs done for you. – zapl Jul 07 '17 at 19:01
  • @zapl So, in my case, I would just define interface CustomerDAO with method getAllCustomers() and that is all? Can you please recommend some documentation (beside what you already linked) on how to start with spring-boot as i have searched already for it and found nothing helpful. i want to know how to setup simple website that interacts with db (and then build on top of that) – Miha Jamsek Jul 07 '17 at 19:07
  • You're following [these instructions](https://stackoverflow.com/a/33881946/438154)? It currently looks like you're asking for a `EntityManagerFactory` bean for the `HibernateJpaSessionFactoryBean`, which Spring Boot can provide, but that seemingly needs a `SessionFactory` which is provided by the `HibernateJpaSessionFactoryBean`, thus circular. – Sotirios Delimanolis Jul 07 '17 at 19:09
  • They have an example with mysql here: https://github.com/spring-guides/gs-accessing-data-mysql/tree/master/complete (sourcecode) / https://spring.io/guides/gs/accessing-data-mysql/ (explanation). There is for example no mention of hibernate in the pom or code. – zapl Jul 07 '17 at 19:09
  • @SotiriosDelimanolis yes, I had error saying i need to define bean for sessionFactory and these instructions helped me get rid of that error. Any suggestion how i can remove this cycle? – Miha Jamsek Jul 07 '17 at 19:12
  • @zapl Thank you, you have been very helpful! – Miha Jamsek Jul 07 '17 at 19:12
  • Regarding methods `getAllCustomers()`, you'd have to name it `findAll()` afaik because spring-data treats method names as implementation instruction, see also https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation – zapl Jul 07 '17 at 19:19

0 Answers0