The method is not intercepted by the transaction consultant, although the "add transactional method" observed in the logs

I have @Transactional @Controller, but its methods are launched using the Spring MVC framework without a transaction. In the exception trace, I do not find a transaction advisor that catches the call:

org.hibernate.HibernateException: No Session found for current thread
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
org.example.businesslogic.MyController.userLoggedIn(SwiperRest.java:48)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:483)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)

On the other hand, the log clearly indicates that controller methods were detected as transactional:

DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'metaDataSourceAdvisor'
DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'MyController.userLoggedIn' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG o.s.a.f.a.InfrastructureAdvisorAutoProxyCreator - Creating implicit proxy for bean 'myController' with 0 common interceptors and 1 specific interceptors
DEBUG o.s.a.f.CglibAopProxy - Creating CGLIB proxy: target source is SingletonTargetSource for target object [org.example.businesslogic.MyController@7c0f1b7c]
DEBUG o.s.a.f.CglibAopProxy - Unable to apply any optimisations to advised method: public java.lang.String org.example.businesslogic.MyController.userLoggedIn(java.lang.String,java.lang.String)
DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'MyController.locationProfiles' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG o.s.a.f.CglibAopProxy - Unable to apply any optimisations to advised method: public java.util.List org.example.businesslogic.MyController.locationProfiles(java.lang.String)

Excerpt from the controller class:

@Transactional
@Controller
@RequestMapping("/zendor")
public class MyController
{
  @Autowired private SessionFactory sf;

  @RequestMapping(method=POST, value="userLoggedIn")
  public @ResponseBody String userLoggedIn(@RequestParam String u_id, @RequestParam String d_id) {
    Session hb = sf.getCurrentSession();
    ...
  }
}

This is my web application initializer, I do not have web.xml:

public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
    @Override
    protected Class<?>[] getRootConfigClasses() { return new Class[] { RootConfig.class }; }
    @Override
    protected Class<?>[] getServletConfigClasses() { return new Class[] { WebMvcConfig.class }; }
    @Override
    protected String[] getServletMappings() { return new String[] { "/" }; }

    @Override public void onStartup(ServletContext ctx) throws ServletException {
      ctx.setInitParameter("spring.profiles.active", "production");
      super.onStartup(ctx);
    }
}

This is the link to the root configuration:

package org.example.config;

@Configuration
@ComponentScan
public class RootConfig
{
}

It is in the same package as these, which fall into the default scan range of components:

@Configuration
@EnableWebMvc
@ComponentScan("org.example.businesslogic")
public class WebMvcConfig extends WebMvcConfigurationSupport
{
}

@Configuration
@EnableTransactionManagement
@ComponentScan("org.example.businesslogic")
public class DataConfig implements TransactionManagementConfigurer
{
  @Autowired private DataSource dataSource;
  ...
}

When the same configuration is used by Spring -test SpringJUnit4ClassRunner, the methods get recommendations and transactions work.

userLoggedIn @Autowired @Transactional @Component, .

?

Spring 4.0.5.

1

, , WebMvcConfig, .

, , ,

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

    @Override
    protected Class<?>[] getServletConfigClasses() { return null; }

: may not be empty or null. , null rootConfigClasses RootConfig servletConfigClasses, , " ".

2

, , Spring Web Security, , -, , SecurityWebApplicationInitializer, , , , , -. , root webapp, root webapp .

+4
2

AbstractAnnotationConfigDispatcherServletInitializer getRootConfigClasses() getServletConfigClasses(). , WebApplicationInitializer ( ) a ContextLoaderListener AnnotationConfigWebApplicationContext, @Configuration ( @Component ) getRootConfigClasses(). DispatcherServlet @Configuration ( ...) getServletConfigClasses().

Servlet ServletContextListener. , ContextLoaderListener refresh AnnotationConfigWebApplicationContext, ( , ). ApplicationContext ServletContext.

DispatcherServlet.

, DispatcherServlet refresh ApplicationConfigWebApplicationContext, , ApplicationContext ServletContext ( ContextLoaderListener), .

beans ApplicationContext, MVC, , , .. beans, @Controller beans, ApplicationContext , .


, , ,

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

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

ContextLoaderListener RootConfig, beans, @Controller, @Transactional.

DispatcherServlet WebMvcConfig, @ComponentScan, @Controller beans, , TransactionInterceptor ( @EnableTransactionManagement > ). DispatcherServlet @Controller beans ( beans, @RequestMapping) ApplicationContext. @Controller beans, . , , , ContextLoaderListener.

, bean (), .


:

  • : ,
  • : , MVC

, . DispatcherServlet . .

, , , @Service. -y, .. .

+3

- : RootConfig WebMvcConfig . RootConfig , WebMvcConfig, , , . (txManager, datasource, sessionfactorybean ..), -: , handlermappings ..

WebMvcConfig ( WebApplicationInitializer), . , , , (), ().

, RootConfig WebMvcConfig .

+1

Source: https://habr.com/ru/post/1545685/


All Articles