1
votes

I am confused with some exception handling within a transaction REST controller.

I have an admin service that looks like:

@Override
public SearchedAdminsEvent search(SearchAdminsEvent searchAdminsEvent) {
    Page<Admin> admins = adminRepository.search(searchAdminsEvent.getSearchTerm(), searchAdminsEvent.getPageRequest());
    if (admins.getTotalElements() == 0) {
        throw new SearchedAdminsNotFoundException(searchAdminsEvent.getSearchTerm());
    } else {
        List<EventAdmin> eventAdmins = EventAdmin.newEventAdminsFrom(admins.getContent()); 
        return new SearchedAdminsEvent(searchAdminsEvent.getSearchTerm(), searchAdminsEvent.getPageRequest(), eventAdmins);
    }
}

I have a REST controller that looks like:

@RequestMapping(value = "/search", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@Transactional(readOnly = true)
@ResponseBody
public ResponseEntity<List<AdminResource>> search(@RequestParam(value = "searchTerm", required = true) String searchTerm, @RequestParam(value = "page", required = true, defaultValue = "0") int page, @RequestParam(value = "size", required = true, defaultValue = "10") int size, UriComponentsBuilder builder) {
    HttpHeaders responseHeaders = new HttpHeaders();
    Pageable pageRequest = buildPageRequest(page, size);
    SearchedAdminsEvent searchedAdminsEvent;
    try {
        searchedAdminsEvent = adminService.search(new SearchAdminsEvent(searchTerm, pageRequest));            
    } catch (SearchedAdminsNotFoundException e) {
        return new ResponseEntity<List<AdminResource>>(responseHeaders, HttpStatus.NOT_FOUND);
    }
    responseHeaders.setLocation(builder.path("/admin/search").queryParam("searchTerm", searchTerm).queryParam("page", page).queryParam("size", size).buildAndExpand(searchedAdminsEvent.getSearchTerm()).toUri());
    List<AdminResource> adminResources = adminResourceAssembler.toResources(searchedAdminsEvent.getEventAdmins());
    ResponseEntity<List<AdminResource>> responseEntity = new ResponseEntity<List<AdminResource>>(adminResources, responseHeaders, HttpStatus.OK);
    return responseEntity;
}

It makes use of the @Transactional(readOnly = true) annotation.

If this annotation is present AND if no searched items were found then it gives the following exception:

2014-06-30 16:22:39,736 DEBUG  [JpaTransactionManager] Participating transaction failed - marking existing transaction as rollback-only 
2014-06-30 16:22:39,736 DEBUG  [JpaTransactionManager] Participating transaction failed - marking existing transaction as rollback-only 
2014-06-30 16:22:39,736 DEBUG  [JpaTransactionManager] Participating transaction failed - marking existing transaction as rollback-only 
2014-06-30 16:22:39,736 DEBUG  [JpaTransactionManager] Setting JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@1f9bfd9] rollback-only 
2014-06-30 16:22:39,736 DEBUG  [JpaTransactionManager] Setting JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@1f9bfd9] rollback-only 
2014-06-30 16:22:39,736 DEBUG  [JpaTransactionManager] Setting JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@1f9bfd9] rollback-only 
2014-06-30 16:22:39,737 DEBUG  [JpaTransactionManager] Initiating transaction commit 
2014-06-30 16:22:39,737 DEBUG  [JpaTransactionManager] Initiating transaction commit 
2014-06-30 16:22:39,737 DEBUG  [JpaTransactionManager] Initiating transaction commit 
2014-06-30 16:22:39,737 DEBUG  [JpaTransactionManager] Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@1f9bfd9] 
2014-06-30 16:22:39,737 DEBUG  [JpaTransactionManager] Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@1f9bfd9] 
2014-06-30 16:22:39,737 DEBUG  [JpaTransactionManager] Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@1f9bfd9] 
2014-06-30 16:22:39,754 DEBUG  [JpaTransactionManager] Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@1f9bfd9] after transaction 
2014-06-30 16:22:39,754 DEBUG  [JpaTransactionManager] Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@1f9bfd9] after transaction 
2014-06-30 16:22:39,754 DEBUG  [JpaTransactionManager] Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@1f9bfd9] after transaction 
2014-06-30 16:22:39,755 DEBUG  [EntityManagerFactoryUtils] Closing JPA EntityManager 
2014-06-30 16:22:39,755 DEBUG  [EntityManagerFactoryUtils] Closing JPA EntityManager 
2014-06-30 16:22:39,755 DEBUG  [EntityManagerFactoryUtils] Closing JPA EntityManager 
2014-06-30 16:22:39,760 DEBUG  [ExceptionHandlerExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.List<com.thalasoft.learnintouch.rest.resource.AdminResource>> com.thalasoft.learnintouch.rest.controller.AdminController.search(java.lang.String,int,int,org.springframework.web.util.UriComponentsBuilder)]: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 
2014-06-30 16:22:39,760 DEBUG  [ExceptionHandlerExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.List<com.thalasoft.learnintouch.rest.resource.AdminResource>> com.thalasoft.learnintouch.rest.controller.AdminController.search(java.lang.String,int,int,org.springframework.web.util.UriComponentsBuilder)]: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 
2014-06-30 16:22:39,760 DEBUG  [ExceptionHandlerExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.List<com.thalasoft.learnintouch.rest.resource.AdminResource>> com.thalasoft.learnintouch.rest.controller.AdminController.search(java.lang.String,int,int,org.springframework.web.util.UriComponentsBuilder)]: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 
2014-06-30 16:22:39,762 DEBUG  [ResponseStatusExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.List<com.thalasoft.learnintouch.rest.resource.AdminResource>> com.thalasoft.learnintouch.rest.controller.AdminController.search(java.lang.String,int,int,org.springframework.web.util.UriComponentsBuilder)]: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 
2014-06-30 16:22:39,762 DEBUG  [ResponseStatusExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.List<com.thalasoft.learnintouch.rest.resource.AdminResource>> com.thalasoft.learnintouch.rest.controller.AdminController.search(java.lang.String,int,int,org.springframework.web.util.UriComponentsBuilder)]: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 
2014-06-30 16:22:39,762 DEBUG  [ResponseStatusExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.List<com.thalasoft.learnintouch.rest.resource.AdminResource>> com.thalasoft.learnintouch.rest.controller.AdminController.search(java.lang.String,int,int,org.springframework.web.util.UriComponentsBuilder)]: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 
2014-06-30 16:22:39,763 DEBUG  [DefaultHandlerExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.List<com.thalasoft.learnintouch.rest.resource.AdminResource>> com.thalasoft.learnintouch.rest.controller.AdminController.search(java.lang.String,int,int,org.springframework.web.util.UriComponentsBuilder)]: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 
2014-06-30 16:22:39,763 DEBUG  [DefaultHandlerExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.List<com.thalasoft.learnintouch.rest.resource.AdminResource>> com.thalasoft.learnintouch.rest.controller.AdminController.search(java.lang.String,int,int,org.springframework.web.util.UriComponentsBuilder)]: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 
2014-06-30 16:22:39,763 DEBUG  [DefaultHandlerExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.List<com.thalasoft.learnintouch.rest.resource.AdminResource>> com.thalasoft.learnintouch.rest.controller.AdminController.search(java.lang.String,int,int,org.springframework.web.util.UriComponentsBuilder)]: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 
2014-06-30 16:22:39,773 DEBUG  [DispatcherServlet] Could not complete request 
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:522)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
    at com.thalasoft.learnintouch.rest.controller.AdminController$$EnhancerByCGLIB$$ebae6d18.search(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:201)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
Caused by: javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:73)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:513)
    ... 73 more
2014-06-30 16:22:39,773 DEBUG  [DispatcherServlet] Could not complete request 
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:522)

If I remove the annotation then all is fine and the response contains the searched items.

I suppose an exception is thrown when no searched items are found, which triggers the transaction rollback message.

Here is the exception handler:

@ExceptionHandler(SearchedAdminsNotFoundException.class)
@ResponseBody
public ResponseEntity<ErrorInfo> searchedAdminsNotFoundException(HttpServletRequest request, SearchedAdminsNotFoundException e) {
    String url = request.getRequestURL().toString();
    String errorMessage = localizeErrorMessage("error.admin.search.not.found", new Object[] { e.getSearchTerm() });
    return new ResponseEntity<ErrorInfo>(new ErrorInfo(url, errorMessage), HttpStatus.NOT_FOUND);
}

Is there any way to see somewhere in the log the inner exception which triggered the transaction rollback one ?

I'm on Spring 3.2.9.RELEASE and Hibernate 3.6.10.Final.

Here is the root cause:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/learnintouch-rest] threw exception [Request processing failed; nested exception is org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly] with root cause
javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:73)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:513)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
    at com.thalasoft.learnintouch.rest.controller.AdminController$$EnhancerByCGLIB$$b11b3634.search(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:201)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

UPDATE: Here is my guess... The exception is caught, so it is not displayed in the log. The annotation rolls back the transaction, even if the exception was caught. Am I right ? In that case, how to handle, i.e., catch exceptions in controllers, if using the annotation ?

Kind Regards,

Stephane Eybert

1
The thing that stands out from your log, in my opinion, is the "Participating transaction failed - marking existing transaction as rollback-only" message. Is adminService.search() method transactional, as well? - Andrei Stefan
There is something I don't understand: obviously, your adminService.search method is expected to throw a SearchedAdminsNotFoundException if I'm not mistaken. Why do you want to see the exception in logs? I asked in my previous comment if adminService.search is configured to be transactional, as well (through @Transactional or something similar). If you have that transactional and you do handle SearchedAdminsNotFoundException in some way (by rolling back the adminService.search transaction) but at the same time catching the exception in the controller looks unusual to me. - Andrei Stefan
Assuming my above guess is correct, don't allow the adminService.search method transaction to rollback in case of that exception and let the exception flow until the controller where you catch it and handle it in some other way. But, as I said, this depends on how your adminService.search method is configured, transactionally speaking. - Andrei Stefan
Hi Andrei, no, the admin service is not specifically marked as transactional. In my case, only the controller is mmarked as being transactional. I wonder if it's better to mark the service or the controller as being transactional. - Stephane
You could do that, yes. I'm wondering why you throw an exception though, but I guess this would work as well. The other option would be to handle a 0 value for counting admins (or whatever you are counting in that query) or a greater than 0 value. Meaning, your service method executes the query and returns the value. If it's 0 then you prepare for the user an appropriate web page, otherwise something else. - Andrei Stefan

1 Answers

1
votes

You could propagate the exceptions to controllers, yes, but I'd choose marking the service methods as transactional. I'm wondering why you throw an exception though, but I guess this would work as well. The other option would be to handle a 0 value for counting admins (or whatever you are counting in that query) or a greater than 0 value. Meaning, your service method executes the query and returns the value. If it's 0 then you prepare for the user an appropriate web page, otherwise something else.