Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Transactional cause nosuchbeandefinitionexception in spring framework

I have a problem when annotating with @transactional a method of my service class. Such annotation cause a NoSuchBeanDefinitionExcpetion in my test class where the service class is autowired. If the transactional annotation is removed it works fine again. Why is this happening, I couldn't find a clue in spring documentation.

This is my application-context.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"
xsi:schemaLocation="
     http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                    http://www.springframework.org/schema/jdbc 
                    http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
                    http://www.springframework.org/schema/context 
                    http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<context:component-scan base-package="<mypackage...>" />

<import resource="data-context.xml"/>

<import resource="resources-context.xml"/>

<import resource="persistence-context.xml"/>

This is part of my persistence-context.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"
xsi:schemaLocation="http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                    http://www.springframework.org/schema/context 
                    http://www.springframework.org/schema/context/spring-context-3.1.xsd">


<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSourceConnection" />
    <property name="configLocation"
        value="classpath:configuration/mybatis/config.xml"></property>
</bean>


<bean id="txManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSourceConnection" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

<bean id="accessDao" class="dao.impl.AccessDaoImpl">
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

<bean id="utilitiesDao" class="dao.impl.UtilitiesDaoImpl">
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

<bean id="portafoglioDao" class="dao.impl.PortafoglioDaoImpl">
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

part of my test class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:configuration/applicationContext.xml" })
public class MyTest {

@Autowired
ApplicationContext context;

@Autowired
DriverManagerDataSource dataSourceConnection;

@Autowired
AccessAppDelegate accessApp;

the class that generates the problem

@Service
public class AccessAppDelegate extends Delegate implements DelegateInterface {

private PersonalCodesManager pcm;
AccessApp accessReq;

@Override
@Transactional
public void elaborateRequestImpl() throws Exception {
    accessReq = (AccessApp) requestBean;
    if (accessReq.getLan() != null) {
        lang = StringUtilities.toLan(accessReq.getLan());
        accessDao.updateDeviceLanguage(accessReq.getUser().getImei(),
                accessReq.getLan());
    }
    if (requestWrap.getRequestType().compareTo(
            ApplicativeConsts.INTESTAZIONE_REQUEST_LOGIN) == 0)
        elaborateRequestLogin();
    else
        elaborateRequestAttivazione();
}

some private methods...

public PersonalCodesManager getPcm() {
    return pcm;
}

public void setPcm(PersonalCodesManager pcm) {
    this.pcm = pcm;
}

@Override
public String getUserId() {
    accessReq = (AccessApp) requestBean;
    return accessReq.getUser().getId();
}

@Override
public Class getRequestType() {
    return AccessApp.class;
}

}

the class Delegate

@Component
public class Delegate{


String jsonReq;
String jsonRes;

@Autowired
ApplicationContext ctx;
@Autowired
AccessDao accessDao;

Locale lang;
java.sql.Timestamp timestamp;
RequestWrapper requestWrap;

UserAndDeviceTable userInfo;
AuthUserTable auth;

BaseResponse responseBean;
BaseRequest requestBean;

public void elaborateRequest(String body,boolean authenticationRequired){
    DelegateInterface endpointImplementation = (DelegateInterface) this;
    timestamp = new java.sql.Timestamp(new java.util.Date().getTime());
    if (body.startsWith("json=")){
        body = body.split("json=")[1];
    }
    requestWrap = new RequestWrapper(body);
    requestBean=requestWrap.getReq(endpointImplementation.getRequestType());
    this.jsonReq = requestWrap.getRequestBody();
    lang = StringUtilities.toLan("en");
    try {
        if (authenticationRequired) {
            auth = this.accessDao.checkSessioneAperta(requestBean.getSessionID(), timestamp);
            if(auth==null) {
                throw new Exception("Unauthorized Access");
            }else{
                setUserInfo(auth.getEmail());
            }
        }else{
            setUserInfo(endpointImplementation.getUserId());
        }
        if(userInfo!=null){
            lang=StringUtilities.toLan(userInfo.getLanguage());
        }
        endpointImplementation.elaborateRequestImpl();
    } catch (Exception e) {
        responseBean= new BaseResponse(String.valueOf(ApplicativeConsts.RC_ERRORE),ctx.getMessage(ApplicativeConsts.MSG_ERRORE_GENERAL, null, lang));
        e.printStackTrace();
    }
    try {
        ObjectMapper mapper = new ObjectMapper(); 
        this.jsonRes = mapper.writeValueAsString(responseBean);
    } catch (Exception e) {
        e.printStackTrace();
    } 
}

public ModelMap getResponse(ModelMap model) {
    // TODO Auto-generated method stub
    model.addAttribute(ApplicativeConsts.INTESTAZIONE_RESPONSE, responseBean);
    return model;
}

public void setUserInfo(String email) {
    List<UserAndDeviceTable> userList = accessDao.findUserAndDeviceTableByEmail(email);
    if (userList.size()==1){
        this.userInfo = userList.get(0);
    }
}

public String getJsonReq() {
    return jsonReq;
}

public String getJsonRes() {
    return jsonRes;
}

public BaseResponse getResponseBean() {
    return responseBean;
}

}

the interface

public interface DelegateInterface {

public void elaborateRequestImpl() throws Exception;
public ModelMap getResponse(ModelMap response);
public String getUserId();
public Class getRequestType();
}

The exception

            org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'TestClass': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: it.something.be.delegates.AccessAppDelegate it.something.controller.somethingControllerTestAuto.accessApp; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [it.something.be.delegates.AccessAppDelegate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
                at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374)
                at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
                at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
                at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
                at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220)
                at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301)
                at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
                at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303)
                at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
                at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
                at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
                at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
                at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
                at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
                at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
                at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
                at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
                at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
                at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
                at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
                at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
            Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: it.something.be.delegates.AccessAppDelegate it.something.controller.somethingControllerTestAuto.accessApp; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [it.something.be.delegates.AccessAppDelegate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
                at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506)
                at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
                at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
                ... 26 more
            Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [it.something.be.delegates.AccessAppDelegate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
                at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:924)
                at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:793)
                at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707)
                at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
                ... 28 more
like image 210
user1387219 Avatar asked Dec 05 '22 15:12

user1387219


1 Answers

This is because you are requesting spring to auto wire to a field which is not an interface. Adding @Transactional results in your object being wrapped in a proxy - the proxy will implement all the interfaces implemented by the class. It can be auto wired to fields of the interface type only. Change the below field definition in your test to the corresponding interface to fix the issue.

@Autowired
AccessAppDelegate accessApp;
like image 54
gkamal Avatar answered May 13 '23 01:05

gkamal