Search code examples
spring-mvcjpaentitymanager

No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call


No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call

when I do a test with JUnit, persist method works and I see that my object is inserted, but when I call the method via my Controller doesn't work

here is my Project :

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">



<!--    <bean id="notification" class="com.app.sqli.notification.NotificationTask" /> -->

<!--    <task:scheduled-tasks> -->
<!--        <task:scheduled ref="notification" method="notifier" cron="*/2 * * * * *"/> -->
<!--    </task:scheduled-tasks> -->

<context:component-scan base-package="com.app.sqli" />  

    <mvc:annotation-driven />
    <bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="dataSource" ref="dataSource" />
       <property name="packagesToScan" value="com.app.sqli.entities" />
      <property name="jpaVendorAdapter">
         <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
      </property>
      <property name="jpaProperties">
         <props>
            <prop key="hibernate.hbm2ddl.auto">validate</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
         </props>
      </property>
   </bean>


   <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://localhost:3306/sqli" />
      <property name="username" value="root" />
      <property name="password" value="" />
   </bean>


    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
      <property name="entityManagerFactory" ref="entityManagerFactoryBean" />
   </bean>


   <tx:annotation-driven />


</beans>

my Model Class:

package com.app.sqli.models;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Collaborateur {

    @Id
    private int id;
    private String nom;

    public int getId() {
        return id;
    }

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

    public String getNom() {
        return nom;
    }

    public void setNom(String nom) {
        this.nom = nom;
    }

}

my DAO Class

package com.app.sqli.dao;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

import com.app.sqli.models.Collaborateur;

@Repository
public class CollaborateurDao implements IcollaborateurDao{

    @PersistenceContext
    private EntityManager em;

    @Override
    public void addCollaborateur(Collaborateur c) {
    em.persist(c);

    }

}

My Service Class

package com.app.sqli.services;

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

import com.app.sqli.dao.IcollaborateurDao;
import com.app.sqli.models.Collaborateur;

@Service
@Transactional
public class CollaborateurService implements IcollaborateurService{

    @Autowired
    private IcollaborateurDao cdao;

    @Override
    public void addCollaborateur(Collaborateur c) {
        cdao.addCollaborateur(c);

    }


}

And My Controller

package com.app.sqli.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.app.sqli.models.Collaborateur;
import com.app.sqli.services.IcollaborateurService;

@org.springframework.stereotype.Controller
public class Controller {
    @Autowired
    private IcollaborateurService cserv;

    @RequestMapping(value = "/index")
    public String index(Model m) {
        System.out.println("insertion ...");
        Collaborateur c = new Collaborateur();
        c.setId(11);
        c.setNom("nom");
        cserv.addCollaborateur(c);
        return "index";
    }

}

Solution

  • thank you @mechkov for your time and help, My problem is resolved by changing my configuration file, so I have used a Configuration Class with annotations and its works so fine, I still Don't know where the problem was

        @Configuration
        @ComponentScan(basePackages = "your package")
        @EnableTransactionManagement
        public class DatabaseConfig {
    
            protected static final String PROPERTY_NAME_DATABASE_DRIVER = "com.mysql.jdbc.Driver";
            protected static final String PROPERTY_NAME_DATABASE_PASSWORD = "password";
            protected static final String PROPERTY_NAME_DATABASE_URL = "jdbc:mysql://localhost:3306/databasename";
            protected static final String PROPERTY_NAME_DATABASE_USERNAME = "login";
    
            private static final String PROPERTY_PACKAGES_TO_SCAN = "where your models are";
            @Bean
            public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter){
                LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
                entityManagerFactoryBean.setDataSource(dataSource);
                entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
                entityManagerFactoryBean.setPackagesToScan(PROPERTY_PACKAGES_TO_SCAN);
                return entityManagerFactoryBean;
            }
    
            @Bean
            public BasicDataSource dataSource(){
                BasicDataSource ds = new BasicDataSource();
                ds.setDriverClassName(PROPERTY_NAME_DATABASE_DRIVER);
                ds.setUrl(PROPERTY_NAME_DATABASE_URL);
                ds.setUsername(PROPERTY_NAME_DATABASE_USERNAME);
                ds.setPassword(PROPERTY_NAME_DATABASE_PASSWORD);
                ds.setInitialSize(5);
                return ds;
            }
    
            @Bean
            public JpaVendorAdapter jpaVendorAdapter(){
                HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
                adapter.setDatabase(Database.MYSQL);
                adapter.setShowSql(true);
                adapter.setGenerateDdl(true);
    
    //I'm using MySQL5InnoDBDialect to make my tables support foreign keys
    adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect");
                return adapter;
            }
    
            @Bean
            public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
                return new JpaTransactionManager(entityManagerFactory);
            }
    
    
        }