1

everyone!

Java + Eclipse + Maven + SpringMVC + Hibernate + Tomcat

I made project by manual https://www.boraji.com/index.php/spring-mvc-4-hibernate-5-restful-crud-operations-example exactly the same and it can not work in my Eclipse((( Because:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bookDaoImpl': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getSessionFactory' defined in com.example.spring.config.AppConfig: Invocation of init method failed;

Can any help, what I must to fix for my project working? Now CRUD methods don't work, but server Tomcat is running...

My project is on https://github.com/OlegSandro/library-service or you can see my code below:

pom.xml:

<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.example.spring</groupId>
  <artifactId>library-service</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <failOnMissingWebXml>false</failOnMissingWebXml>
    <hibernate.version>5.2.8.Final</hibernate.version>
  </properties>

  <dependencies>
    <!-- Servlet API -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- Spring MVC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <!-- Spring ORM -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <!-- Hibernate ORM -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <!-- Hibernate-c3p0 Integration -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-c3p0</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <!-- c3p0 -->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.2</version>
    </dependency>
    <!-- MySQL Connector -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>6.0.5</version>
    </dependency>
    <!-- Jackson API for JSON -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.7</version>
    </dependency>

  </dependencies>

  <build>
    <sourceDirectory>src/main/java</sourceDirectory>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>

        <!-- Embedded Apache Tomcat required for testing war -->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <path>/</path>
            </configuration>
        </plugin>
    </plugins>
  </build>
</project>

model.Book.java

    package com.example.spring.model;

    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;

    @Entity(name = "Book")
    public class Book {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String title;
        private String author;

        public Book() {
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getAuthor() {
            return author;
        }

        public void setAuthor(String author) {
            this.author = author;
        }
    }

controller.BookController.java

package com.example.spring.service;

    import java.util.List;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import com.example.spring.dao.BookDao;
    import com.example.spring.model.Book;

    @Service
    @Transactional(readOnly = true)
    public class BookServiceImpl implements BookService {

        @Autowired
        private BookDao bookDao;

        @Transactional
        public long save(Book book) {
            return bookDao.save(book);
        }

        public Book get(long id) {
            return bookDao.get(id);
        }

        @Transactional
        public void update(long id, Book book) {
            bookDao.update(id, book);

        }

        @Transactional
        public void delete(long id) {
            bookDao.delete(id);
        }

        public List<Book> list() {
            return bookDao.list();
        }

    }

service.BookServiceImpl.java

package com.example.spring.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.spring.dao.BookDao;
import com.example.spring.model.Book;

@Service
@Transactional(readOnly = true)
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao;

    @Transactional
    public long save(Book book) {
        return bookDao.save(book);
    }

    public Book get(long id) {
        return bookDao.get(id);
    }

    @Transactional
    public void update(long id, Book book) {
        bookDao.update(id, book);

    }

    @Transactional
    public void delete(long id) {
        bookDao.delete(id);
    }

    public List<Book> list() {
        return bookDao.list();
    }

}

dao.BookDaoImpl.java

package com.example.spring.dao;

import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.example.spring.model.Book;

@Repository
public class BookDaoImpl implements BookDao {

    @Autowired
    private SessionFactory sessionFactory;

    public long save(Book book) {
        sessionFactory.getCurrentSession().save(book);
        return book.getId();
    }

    public Book get(long id) {
        return sessionFactory.getCurrentSession().get(Book.class, id);
    }

    public void update(long id, Book book1) {
        Session session = sessionFactory.getCurrentSession();
        Book book2 = session.byId(Book.class).load(id);
        book2.setTitle(book1.getTitle());
        book2.setAuthor(book1.getAuthor());
        session.flush();
    }

    public void delete(long id) {
        Session session = sessionFactory.getCurrentSession();
        Book book = session.byId(Book.class).load(id);
        session.delete(book);
    }

    public List<Book> list() {
        Session session = sessionFactory.getCurrentSession();
        CriteriaBuilder cb = session.getCriteriaBuilder();
        CriteriaQuery<Book> cq = cb.createQuery(Book.class);
        Root<Book> root = cq.from(Book.class);
        cq.select(root);
        Query<Book> query = session.createQuery(cq);
        return query.getResultList();
    }

}

config.WebConfig.java

package com.example.spring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.example.spring.controller" })
public class WebConfig extends WebMvcConfigurerAdapter {

}

config.AppConfig.java

package com.example.spring.config;

import java.util.Properties;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import static org.hibernate.cfg.Environment.*;

@Configuration
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
@ComponentScans(value = { @ComponentScan("com.example.spring.dao"),
        @ComponentScan("com.example.spring.service")})
public class AppConfig {

    @Autowired
    private Environment env;

    @Bean
    public LocalSessionFactoryBean getSessionFactory() {
        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();

        Properties props = new Properties();
        // Setting JDBC properties
        props.put(DRIVER, env.getProperty("mysql.driver"));
        props.put(URL, env.getProperty("mysql.url"));
        props.put(USER, env.getProperty("mysql.user"));
        props.put(PASS, env.getProperty("mysql.password"));

        // Setting Hibernate properties
        props.put(SHOW_SQL, env.getProperty("hibernate.show_sql"));
        props.put(HBM2DDL_AUTO, env.getProperty("hibernate.hbm2ddl.auto"));

        // Setting C3P0 properties
        props.put(C3P0_MIN_SIZE, env.getProperty("hibernate.c3p0.min_size"));
        props.put(C3P0_MAX_SIZE, env.getProperty("hibernate.c3p0.max_size"));
        props.put(C3P0_ACQUIRE_INCREMENT, env.getProperty("hibernate.c3p0.acquire_increment"));
        props.put(C3P0_TIMEOUT, env.getProperty("hibernate.c3p0.timeout"));
        props.put(C3P0_MAX_STATEMENTS, env.getProperty("hibernate.c3p0.max_statements"));

        factoryBean.setHibernateProperties(props);
        factoryBean.setPackagesToScan("com.example.spring.model");

        return factoryBean;
    }

    @Bean
    public HibernateTransactionManager getTransactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(getSessionFactory().getObject());
        return transactionManager;
    }
}

config.MyWebAppInitializer.java

package com.example.spring.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { AppConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

resources.db.properties

# MySQL properties
mysql.driver=com.mysql.cj.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/library
mysql.user=root
mysql.password=****

# Hibernate properties
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update

#C3P0 properties
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.acquire_increment=1
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=150
  • What I found when using annotation configuration was to call `factory.afterPropertiesSet();` for my `LocalSessionFactoryBean` after calling `factoryBean.setHibernateProperties(props);` though that might not tackle exactly your issue. Also after comparing your code, the only thing where you might go wrong, is the `Build + Deploy + Run application` part – XtremeBaumer May 15 '19 at 08:02
  • Thanks @XtremeBaumer for you answer! I tried to call `factoryBean.afterPropertiesSet();` after `factoryBean.setHibernateProperties(props);factoryBean.setPackagesToScan("com.example.spring.model");` in my `AppConfig.getSessionFactory()`, but it didn't help me. What about `Build + Deploy + Run app`, at first I use `mvn clean install` and then `mvn tomcat7:run` and I don't see, where I could make a mistake, because it is 2 commands only – Oleg Sandro May 15 '19 at 08:36

1 Answers1

1

Was able reproduce this issue locally and fix it.

Try updating artifact version of mysql-connector-java to latest

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.16</version>
</dependency>

This is required if you are using latest / newer MySQL version (other than the version mentioned in the post)

Relevant issue: How to resolve Unable to load authentication plugin 'caching_sha2_password' issue

If it doesn't help, kindly provide complete stack trace, else accept the solution.

BTW, would recommend to use spring boot, which is much simpler and advanced.

Guru
  • 964
  • 9
  • 12
  • Wow, thanks a lot! Your answer helped me. Yes, really, I use the latest version of MySQL (8.0.16) and I didn't notice that the manual author's version of MySQL stayed in maven dependencies. Also thank you for your advice about Spring Boot – Oleg Sandro May 15 '19 at 11:37
  • @Oleg Sandro answer has worked for you, kindly accept the answer, otherwise won't be able to help others with comments. – Guru May 16 '19 at 09:23
  • Please, excuse me. I don't speak English very well and I didn't understand at once, what is `to accept the answer`. I am on the [stackoverflow.com](https://stackoverflow.com) site for the first time and think, maybe you want me to press the check mark to the left hand of the answer, in this case I just did it – Oleg Sandro May 17 '19 at 03:29
  • Thanks @OlegSandro. Once the answer is accepted, a green check box appears in front of the answer provide. This also adds point in the reputation of the individual. Only after set of such points different set of features like commenting etc gets unlocked. As I am also new as a contributor to stack overflow, many such useful features won't be available to me unless get enough reputation points. Thanks for accepting the answer. – Guru May 17 '19 at 07:39
  • Thank you for your detailed explanation. Now I understand it all. You taught me a some stack overflow literacy :) – Oleg Sandro May 17 '19 at 12:57