带有事务管理器的org.springframework.beans.factory.BeanCreationException

时间:2015-12-29 19:08:11

标签: java spring spring-mvc spring-transactions

我一直在使用Restful应用程序研究Spring MVC,但我很难让它运行起来。

我的申请具有以下结构:

  • @Entity 课程
  • @Repository 类(使用 @Transactional 进行查询)
  • @RestfulController 类(为简化起见,我没有实现服务层)

我想使用 @Transactional 进行查询,但是当我在spring xml文件上配置时,我收到错误消息 on server start

WARN : org.springframework.web.context.support.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'calendarController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private br.com.milo.repository.CalendarRepository br.com.milo.controller.CalendarController.repository; nested exception is java.lang.IllegalArgumentException: Can not set br.com.milo.repository.CalendarRepository field br.com.milo.controller.CalendarController.repository to com.sun.proxy.$Proxy47
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:835)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:667)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:633)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:681)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:552)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:493)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5253)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5543)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1574)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1564)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

只有在我的spring配置文件中添加以下配置时才会出现此错误:

<tx:annotation-driven transaction-manager="transactionManager"/>    

如果删除此行,则问题消失,Restful请求正常,但是,Repository方法不保存数据。在这种情况下,会显示以下消息(此错误发生在另一个Controller上,因为Callendar功能尚未完成。虽然,例外是相关的,因为它与Transaction相关):

Dec 29, 2015 5:03:45 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/milo] threw exception [Request processing failed; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call] with root cause
javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:277)
    at com.sun.proxy.$Proxy45.persist(Unknown Source)
    at br.com.milo.repository.FarmRepository.save(FarmRepository.java:28)
    at br.com.milo.controller.FarmController.insertFarm(FarmController.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at br.com.milo.security.CsrfHeaderFilter.doFilterInternal(CsrfHeaderFilter.java:34)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:120)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

这是我的春季配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc 
                        http://www.springframework.org/schema/mvc/spring-mvc.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.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <mvc:annotation-driven />

    <context:component-scan base-package="br.com.milo" />

    <resources mapping="/resources/**" location="/resources/" />
    <resources mapping="/pages/**" location="/pages/" />
    <resources mapping="/login/**" location="/login/" />

    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <beans:property name="messageConverters">
            <beans:list>
                <beans:ref bean="jsonMessageConverter"/>
            </beans:list>
        </beans:property>
    </beans:bean>

    <beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    </beans:bean>   

    <beans:bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <beans:property name="dataSource" ref="dataSource" />
      <beans:property name="packagesToScan" value="br.com.milo" />
      <beans:property name="jpaVendorAdapter">
         <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
      </beans:property>
      <beans:property name="jpaProperties">
         <beans:props>
            <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</beans:prop>
         </beans:props>
      </beans:property>
   </beans:bean>

   <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <beans:property name="driverClassName" value="org.postgresql.Driver" />
      <beans:property name="url" value="jdbc:postgresql://localhost:5432/milo" />
      <beans:property name="username" value="123" />
      <beans:property name="password" value="123" />
   </beans:bean>

    <beans:bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <beans:property name="entityManagerFactory" ref="myEmf" />
    </beans:bean>
    <!-- Just when I add this line the error above  is shown -->
    <tx:annotation-driven transaction-manager="transactionManager"/>    
</beans:beans>

这是Class CalendarController.java

package br.com.milo.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import br.com.milo.domain.Calendar;
import br.com.milo.domain.Owner;
import br.com.milo.domain.DTO.CalendarMonthDTO;
import br.com.milo.repository.CalendarRepository;
@RestController
@RequestMapping("/rest/calendar")
public class CalendarController {

    private static final Logger logger = LoggerFactory.getLogger(CalendarController.class);

    @Autowired
    private CalendarRepository repository;

    @RequestMapping(value = RestPaths.GET_CALENDAR, method = RequestMethod.GET)
    public @ResponseBody Calendar getCalendar(@PathVariable("id") int id) {
        logger.info("Start Get Calendar. ID=" + id);
        return repository.findById(id);
    }

    @RequestMapping(value = RestPaths.LIST_CALENDARS, method = RequestMethod.GET)
    public @ResponseBody List<Calendar> listCalendars() {
        logger.info("Start List Calendars.");
        List<Calendar> calendars = repository.list();
        return calendars;
    }

    @RequestMapping(value = RestPaths.LIST_CALENDAR_BY_OWNER, method = RequestMethod.GET)
    public @ResponseBody List<Calendar> listByOwner(@RequestBody Owner o) {
        logger.info("Start List Calendars By Owner.");
        List<Calendar> calendars = repository.listByType(o);
        return calendars;
    }

    @RequestMapping(value = RestPaths.UPDATE_CALENDAR, method = RequestMethod.POST)
    public @ResponseBody Calendar updateCalendar(@RequestBody Calendar calendar) {
        logger.info("Start Update Calendar.");
        repository.update(calendar);
        return calendar;
    }

    @RequestMapping(value = RestPaths.INSERT_CALENDAR, method = RequestMethod.POST)
    public @ResponseBody Calendar insertCalendar(@RequestBody Calendar calendar) {
        logger.info("Start Insert Calendar.");
        repository.save(calendar);
        return calendar;
    }

    @RequestMapping(value = RestPaths.DELETE_CALENDAR, method = RequestMethod.PUT)
    public @ResponseBody Calendar deleteCalendar(@PathVariable("id") int calendarId) {
        logger.info("Start delete Calendar.");
        Calendar calendar = repository.findById(calendarId);
        repository.delete(calendar);
        return calendar;
    }

    @RequestMapping(value = RestPaths.LIST_CALENDAR_BY_MONTH, method = RequestMethod.GET)
    public @ResponseBody List<Calendar> listByMonth(@RequestBody CalendarMonthDTO calendarDTO) {
        logger.info("Start List Calendar By Month.");
        List<Calendar> calendars = repository.listByMonth(calendarDTO.getOwner(), calendarDTO.getYear(), calendarDTO.getMonth());
        return calendars;
    }

}

这是CalendarRepository.java类

package br.com.milo.repository;

import java.util.List;

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

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import br.com.milo.domain.Calendar;
import br.com.milo.domain.Owner;

@Repository
public class CalendarRepository implements br.com.milo.repository.Repository<Calendar, Owner>{

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    @Transactional
    public void save(Calendar calendar) {
        entityManager.persist(calendar);
    }

    @Override
    @Transactional
    public void update(Calendar calendar) {
        entityManager.merge(calendar);
    }

    @Override
    @Transactional
    public void delete(Integer id) {
        this.delete(this.findById(id));
    }

    @Override
    @Transactional
    public void delete(Calendar calendar){
        entityManager.remove(calendar);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Calendar> list() {
        Query query = entityManager.createQuery("from Calendar c order by c.calendarDate DESC");
        return query.getResultList();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Calendar> listByType(Owner o) {

        if(o != null){
            Query query = entityManager.createQuery("from Calendar c join c.ownerList o where o.name = :owner");
            query.setParameter("owner", o.getName());
            return query.getResultList();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public List<Calendar> listByMonth(Owner o, int year, int month) {

        if(o != null){
            Query query = entityManager.createQuery("from Calendar c join c.ownerList o "
                + "where o.name = :owner "
                + "and month(e.calendarDate)=:month "
                + "and year(e.calendarDate)=:year");
            query.setParameter("owner", o.getName());
            query.setParameter("month", month);
            query.setParameter("year", year);
            return query.getResultList();
        }
        return null;
    }

    @Override
    public Calendar findById(Integer id) {
        Calendar calendar = entityManager.find(Calendar.class, id);
        return calendar;
    }

}

提前感谢您查看我的问题!

1 个答案:

答案 0 :(得分:1)

repository中的CalendarController字段应该由界面定义,而不是类。 Spring在CalendarRepository周围创建了一个代理,它实现了相同的接口,但不是CalendarRepository的子类。

这个问题是关于完全相同的问题:@Autowired return exception on UserDetails in Spring-security

  

您正在尝试按类自动装配用户详细信息服务,但这不起作用,因为spring bean实际上是围绕该类创建的代理(而不是该类的实例)。然而,代理将实现原始bean的所有接口,因此通过接口注入是安全的。

     

交换此行:

@Autowired
private MyCustomUserDetailsService myCustomUserDetailsService;
     

这个:

@Autowired
private UserDetailsService myCustomUserDetailsService;
     

阅读Spring AOP中Proxying Mechanisms的部分以了解详细信息。

因此,在您的情况下,您可以使用所需的方法创建新的interface CalendarRepository,然后在class CalendarRepositoryImpl implements CalendarRepository中实施:

interface CalendarRepository extends br.com.milo.repository.Repository<Calendar, Owner>{
    void save(Calendar calendar);
    void update(Calendar calendar);
    void delete(Integer id);
    ... (and all other methods you need)
}

@Repository
class CalendarRepositoryImpl implements CalendarRepository {
    ... (what you currently have in CalendarRepository)
}

class CalendarController {
    @Autowired
    CalendarRepository repository; // NOT CalendarRepositoryImpl
}