No thread-bound request error in parallel stream in controller - java

I have an endpoint on my controller which takes a list of IDs. For each ID I fetch details from a REST endpoint which I would like to do asynchronously. This is my implementation:
#PostMapping("/leaderboard")
#ApiOperation("Get clients leaderboard statistics")
public List<Dto> clientLeaderboard(#RequestBody List<String> accountIds) {
IntStream.range(0, accountIds.size()).parallel().forEach(i -> {
AccountDTO accountDTO = accountMaintenanceRestClient.getAccount(accountIds.get(i));
// More logic
}
}
This then gives me the error:
Unhandled exception occurred
java.lang.IllegalStateException: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
I've actually experienced this error before and managed to fix it in an answer here. Is the same solution applicable here? If so how can I provide my existing executor to this parallel stream?
Edit
AccountMaintenanceRestClient code. I'm using OpenFeign as part of this.
public interface AccountMaintenanceRestClient {
#RequestLine("GET /account/{accountId}")
#Profiled(tag = "AccountMaintenanceRestClient.{$0}.getAccountBalance", logFailuresSeparately = true)
AccountDTO getAccount(#Param("accountId") String accountId);
#RequestLine("GET /referencedata/statuscode")
#Profiled(tag = "AccountMaintenanceRestClient.getStatusCodes", logFailuresSeparately = true)
Map<String, String> getStatusCodes();
#RequestLine("GET /referencedata/websites")
#Profiled(tag = "AccountMaintenanceRestClient.getWebsitesIds", logFailuresSeparately = true)
List<WebSiteDTO> getWebsitesIds();
}
Stacktrace:
java.lang.IllegalStateException: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:593)
at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:735)
at java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:160)
at java.util.stream.ForEachOps$ForEachOp$OfInt.evaluateParallel(ForEachOps.java:189)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.util.stream.IntPipeline.forEach(IntPipeline.java:404)
at java.util.stream.IntPipeline$Head.forEach(IntPipeline.java:560)
at com.foobar.wt.igip.gateway.web.controllers.surge.paris.SurgeParisController.clientLeaderboard(SurgeParisController.java:58)
at com.foobar.wt.igip.gateway.web.controllers.surge.paris.SurgeParisController$$FastClassBySpringCGLIB$$a143909.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:667)
at com.foobar.wt.igip.gateway.web.controllers.surge.paris.SurgeParisController$$EnhancerBySpringCGLIB$$67cb3a1e.clientLeaderboard(<generated>)
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:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:854)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:765)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
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.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:54)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:111)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at uk.co.igindex.commons.bluegreen.IGClusterDetailsFilter.doFilter(IGClusterDetailsFilter.java:46)
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.doFilterInternal(FilterChainProxy.java:208)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:128)
at org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:66)
at org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:103)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:121)
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.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1757)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1716)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.springframework.web.context.support.WebApplicationContextUtils.currentRequestAttributes(WebApplicationContextUtils.java:309)
at org.springframework.web.context.support.WebApplicationContextUtils.access$400(WebApplicationContextUtils.java:64)
at org.springframework.web.context.support.WebApplicationContextUtils$RequestObjectFactory.getObject(WebApplicationContextUtils.java:325)
at org.springframework.web.context.support.WebApplicationContextUtils$RequestObjectFactory.getObject(WebApplicationContextUtils.java:320)
at org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler.invoke(AutowireUtils.java:307)
at com.sun.proxy.$Proxy134.getHeader(Unknown Source)
at com.foobar.wt.igip.gateway.support.FeignSSOTokenRequestInterceptor.apply(FeignSSOTokenRequestInterceptor.java:22)
at feign.SynchronousMethodHandler.targetRequest(SynchronousMethodHandler.java:158)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:88)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
at com.sun.proxy.$Proxy156.getAccount(Unknown Source)
at com.foobar.wt.igip.gateway.web.controllers.surge.paris.SurgeParisController.lambda$clientLeaderboard$2(SurgeParisController.java:59)
at java.util.stream.ForEachOps$ForEachOp$OfInt.accept(ForEachOps.java:205)
at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)
at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
FeignSSOTokenRequestInterceptor:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
#Component
public class FeignSSOTokenRequestInterceptor implements RequestInterceptor {
private static final String SSO_HEADER_NAME = "X-SECURITY-TOKEN";
private final HttpServletRequest request;
#Autowired
public FeignSSOTokenRequestInterceptor(HttpServletRequest request) {
this.request = request;
}
#Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header(SSO_HEADER_NAME, request.getHeader(SSO_HEADER_NAME));
}
}

Your FeignSSOTokenRequestInterceptor depends on HttpServletRequest proxied bean.
The request is exposed via threadlocal so threads in threadpool has no knowledge/aware of it, hence exception occurs when it try to read the request from threadlocal map.
So basically the problem narrowed down to how to set the request to the threadpool's thread context.
Setup a threadpool like your referenced post then submit the task,
#Autowired
ThreadPoolTaskExecutor poolExecutor;
CountdownLatch counter = new CountdownLatch(accountIds.size());
IntStream.range(0, accountIds.size()) // Note that .parallel is omitted
.forEach(() -> poolExecutor.submit(() -> {
try {
your task
} finally {
counter.countDown();
}
}))
counter.await(); // Wait for all tasks complete
This is prefered way, because the default parallel stream is used a common shared pool, you should not place a task has heavy IO like API access to that)

I would like to throw some light on the question.
FeignSSOTokenRequestInterceptor is your custom RequestInterceptor and you are trying to access ServletRequest inside the apply method which is evident from the stack trace
RequestObjectFactory.getObject(WebApplicationContextUtils.java:320)
This RequestObjectFactory is a static inner class which gives you access the current request
private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable {
private RequestObjectFactory() {
}
public ServletRequest getObject() {
return WebApplicationContextUtils.currentRequestAttributes().getRequest();
}
public String toString() {
return "Current HttpServletRequest";
}
}
the current request is derived from the RequestContextHolder class which gets the attribute from the current thread as shown below after a series of method calls
//This is the current thread which holds the request attributes
private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes");
//This is the place where you get the actual exception from the spring RequestContextHolder class.
public static RequestAttributes currentRequestAttributes() throws IllegalStateException {
RequestAttributes attributes = getRequestAttributes();
if (attributes == null) {
if (jsfPresent) {
attributes = RequestContextHolder.FacesRequestAttributesFactory.getFacesRequestAttributes();
}
if (attributes == null) {
throw new IllegalStateException("No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.");
}
}
return attributes;
}
public static RequestAttributes getRequestAttributes() {
RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get();
if (attributes == null) {
attributes = (RequestAttributes)inheritableRequestAttributesHolder.get();
}
return attributes;
}
final verdict:
so make sure you are not trying to access the ServletRequest from the RequestInterceptor if you are using parallel streams. since parallel streams must be used only with stateless, non-interfering, and associative operations
since requestAttributesHolder.get() looks for the current thread do not use parallel streams on it as shown below .which is not recommended and parallelism has a lot of things to be considered refer(link)
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
#SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
if you do not have any code that is accessing the current request and it's being called from the OpenFeign class files then the only way is to use the sequential streams instead of parallel streams.which is straightforward
accountIds.stream().forEach(accountId -> {
AccountDTO accountDTO = accountMaintenanceRestClient.getAccount(accountId);
// More logic
}

Related

Error while intercepting a hibernate event

My goal is to find out what columns where changed during an update on my MySQL database.
My first idea was to use the Hibernate Event System. I have implemented a PreUpdateEventListener. The event allows access to the changed object and I'm retrieving the older object from the database. I am using the Java Object Diff Library to compare the two objects. Since I only need the first layer to be compared I configured the Comparator as follows:
public static List<String> compareTillFirstLayer(Object pre, Object post) {
ArrayList<String> changedProperties = new ArrayList<String>();
InclusionResolver inclusionResolver = new InclusionResolver() {
#Override
public Inclusion getInclusion(DiffNode node) {
if (node.getParentNode().isRootNode()) {
return Inclusion.INCLUDED;
}
return null;
}
#Override
public boolean enablesStrictIncludeMode() {
return true;
}
};
ObjectDiffer objectDiffer = ObjectDifferBuilder.startBuilding().inclusion().resolveUsing(inclusionResolver)
.and().build();
DiffNode root = objectDiffer.compare(pre, post);
root.visitChildren(new DiffNode.Visitor() {
#Override
public void node(DiffNode node, Visit visit) {
changedProperties.add(node.getPropertyName());
}
});
return changedProperties;
}
This returns the changed properties of the object. To find the connection to the database columns I use the Hibernate Configuration and it's mapping like this:
for (String property : changedProperties) {
PersistentClass persistentClass = HibernateUtil.getHibernateUtil().getConfiguration()
.getClassMapping(Consumer.class.getName());
String columnName = ((Column) persistentClass.getProperty(property).getColumnIterator().next())
.getName();
System.out.println(columnName);
}
This workes just fine for my Consumer object but it fails with other objects like an Appointment or a Vehicle object.
Even the exceptions differ from object to object.
If I try to monitor the changes of the Appointment I recieve the following exception:
java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(ArrayList.java:854)
at de.applicodata.serviceportal.persistence.hibernateEventListeners.PreUpdateEventImpl.onPreUpdate(PreUpdateEventImpl.java:88)
at org.hibernate.action.EntityUpdateAction.preUpdate(EntityUpdateAction.java:237)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:86)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:185)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at de.applicodata.serviceportal.persistence.dao.GeneralDAO.commit(GeneralDAO.java:189)
at de.applicodata.serviceportal.persistence.dao.GeneralDAO.update(GeneralDAO.java:556)
at de.applicodata.serviceportal.logic.entities.Appointment.updatePersistenceObject(Appointment.java:167)
at de.applicodata.serviceportal.faces.beans.MyAppointmentsBean.updateAppointmemt(MyAppointmentsBean.java:777)
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:498)
at org.apache.el.parser.AstValue.invoke(AstValue.java:279)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:273)
at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at net.bull.javamelody.JsfActionListener.processAction(JsfActionListener.java:67)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:89)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
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 net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:239)
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:215)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at de.applicodata.serviceportal.faces.listener.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:36)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at de.applicodata.serviceportal.faces.listener.SessionTimeoutFilter.doFilter(SessionTimeoutFilter.java:129)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:199)
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:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:1025)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1136)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
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)
While monitoring changes on the Vehicle object I receiver the following exception although the Objects are diffrent from another:
java.lang.IllegalStateException: Couldn't find a differ for type: [B
at de.danielbechler.diff.differ.DifferProvider.retrieveDifferForType(DifferProvider.java:55)
at de.danielbechler.diff.differ.DifferDispatcher.compare(DifferDispatcher.java:196)
at de.danielbechler.diff.differ.DifferDispatcher.compareWithCircularReferenceTracking(DifferDispatcher.java:172)
at de.danielbechler.diff.differ.DifferDispatcher.compare(DifferDispatcher.java:159)
at de.danielbechler.diff.differ.DifferDispatcher.dispatch(DifferDispatcher.java:105)
at de.danielbechler.diff.differ.BeanDiffer.compareUsingIntrospection(BeanDiffer.java:114)
at de.danielbechler.diff.differ.BeanDiffer.compareUsingAppropriateMethod(BeanDiffer.java:104)
at de.danielbechler.diff.differ.BeanDiffer.compare(BeanDiffer.java:90)
at de.danielbechler.diff.differ.DifferDispatcher.compare(DifferDispatcher.java:202)
at de.danielbechler.diff.differ.DifferDispatcher.compareWithCircularReferenceTracking(DifferDispatcher.java:172)
at de.danielbechler.diff.differ.DifferDispatcher.compare(DifferDispatcher.java:159)
at de.danielbechler.diff.differ.DifferDispatcher.dispatch(DifferDispatcher.java:105)
at de.danielbechler.diff.ObjectDiffer.compare(ObjectDiffer.java:52)
at de.applicodata.serviceportal.persistence.hibernateEventListeners.HibernateEventObjectComparator.compareTillFirstLayer(HibernateEventObjectComparator.java:34)
at de.applicodata.serviceportal.persistence.hibernateEventListeners.PreUpdateEventImpl.onPreUpdate(PreUpdateEventImpl.java:63)
at org.hibernate.action.EntityUpdateAction.preUpdate(EntityUpdateAction.java:237)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:86)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:185)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at de.applicodata.serviceportal.persistence.dao.GeneralDAO.commit(GeneralDAO.java:189)
at de.applicodata.serviceportal.persistence.dao.GeneralDAO.update(GeneralDAO.java:556)
at de.applicodata.serviceportal.logic.entities.Vehicle.updatePersistenceObject(Vehicle.java:509)
at de.applicodata.serviceportal.faces.beans.WerWiSalesVehicleBean.updateVehicle(WerWiSalesVehicleBean.java:1892)
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:498)
at org.apache.el.parser.AstValue.invoke(AstValue.java:279)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:273)
at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at net.bull.javamelody.JsfActionListener.processAction(JsfActionListener.java:67)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:89)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
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 net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:239)
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:215)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at de.applicodata.serviceportal.faces.listener.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:36)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at de.applicodata.serviceportal.faces.listener.SessionTimeoutFilter.doFilter(SessionTimeoutFilter.java:129)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:357)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:199)
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:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:1025)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1136)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
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)
I really don't know where to start on this one since the exceptions are so different from eachother. Any tips on what might cause this behaviour are appreciated!
If any further information is needed I'll provide it.
Edit: The Vehicle error is kind of resolved. It was due to a missing feature in the before mentioned Java Object Diff Library. Source I am currently working on a workaround for excluding arrays from the comparison
The first part of the question is answered. Due to the Java Object Diff Library not beeing able to work with arrays I decided to just exclude these from the comparison.
This works just fine with the rewritten compareTillFirstLayer method like this:
public class HibernateEventObjectComparator {
public final static InclusionResolver inclusionResolver = new InclusionResolver() {
#Override
public Inclusion getInclusion(DiffNode node) {
if (node.getParentNode().isRootNode() && node.getValueType().isArray()) {
return Inclusion.EXCLUDED;
} else if (node.getParentNode().isRootNode()) {
return Inclusion.INCLUDED;
} else {
return null;
}
}
#Override
public boolean enablesStrictIncludeMode() {
return true;
}
};
public static List<String> compareTillFirstLayer(Object pre, Object post) {
ArrayList<String> changedProperties = new ArrayList<String>();
ObjectDiffer objectDiffer = ObjectDifferBuilder.startBuilding().inclusion().resolveUsing(inclusionResolver)
.and().build();
DiffNode root = objectDiffer.compare(pre, post);
root.visitChildren(new DiffNode.Visitor() {
#Override
public void node(DiffNode node, Visit visit) {
changedProperties.add(node.getPropertyName());
}
});
return changedProperties;
}
...
EDIT: The second problme is solved as well.
The list of columns I got from hibernate was empty if it referred to a collection. Since I didn't need these columns I'm simply checking if a column is availabe and only iterate over the columns array if there are columns inside. Sadly I have no answer to why the columns array for any collection is empty.

Error creating bean with name 'scopedTarget.oauth2ClientContext' despite defining RequestContextListener

My app has multiple spring security configurations and one of them happens to be Oauth2 (using this eaxmple).
Spring security in general is getting plugged in via:
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.addFilter(GzipFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
context.addFilter(new FilterHolder( new DelegatingFilterProxy( DEFAULT_FILTER_NAME ) ), "/*",EnumSet.allOf( DispatcherType.class ));
AnnotationConfigWebApplicationContext securityContext = new AnnotationConfigWebApplicationContext();
securityContext.setConfigLocation("com.test.auth");
DispatcherServlet dispatcherServlet = new DispatcherServlet(securityContext);
context.addServlet(new ServletHolder(dispatcherServlet), "/");
context.addServlet(new ServletHolder(new ServletContainer(createResourceConfig(AuthController.class))), "/auth/*");
Oauth2 which looks like this:
#Order(4)
#EnableOAuth2Client
#EnableWebSecurity
#Configuration
public class Oauth2Config extends WebSecurityConfigurerAdapter {
#Bean
#Order(0)
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
#Autowired
private OAuth2ClientContext oauth2ClientContext;
#Autowired
private OAuth2ClientContextFilter oauth2ClientContextFilter;
#Autowired
private AuthConfig authConfig;
private OAuth2ProtectedResourceDetails authorizationCodeResource() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId("google-oauth-client");
details.setClientId(authConfig.getProperty("oauth2.clientId"));
details.setClientSecret(authConfig.getProperty("oauth2.clientSecret"));
details.setUserAuthorizationUri(authConfig.getProperty("oauth2.userAuthorizationUri"));
details.setAccessTokenUri(authConfig.getProperty("oauth2.accessTokenUri"));
details.setTokenName(authConfig.getProperty("oauth2.tokenName"));
details.setScope(Arrays.asList(authConfig.getPropertyList("oauth2.scope")));
details.setAuthenticationScheme(AuthenticationScheme.query);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
return details;
}
#Bean
public OAuth2ClientAuthenticationProcessingFilter
oauth2ClientAuthenticationProcessingFilter() {
// Used to obtain access token from authorization server (AS)
OAuth2RestOperations restTemplate = new OAuth2RestTemplate(
authorizationCodeResource(),
oauth2ClientContext);
OAuth2ClientAuthenticationProcessingFilter filter =
new OAuth2ClientAuthenticationProcessingFilter(authConfig.getProperty("oauth2.filterCallbackPath"));
filter.setRestTemplate(restTemplate);
// Set a service that validates an OAuth2 access token
// We can use either Google API's UserInfo or TokenInfo
// For this, we chose to use UserInfo service
filter.setTokenServices(googleUserInfoTokenServices());
return filter;
}
#Bean
public GoogleUserInfoTokenServices googleUserInfoTokenServices() {
GoogleUserInfoTokenServices userInfoTokenServices =
new GoogleUserInfoTokenServices(authConfig.getProperty("oauth2.userInfoUri"), authConfig.getProperty("oauth2.clientId"));
// TODO Configure bean to use local database to read authorities
// userInfoTokenServices.setAuthoritiesExtractor(authoritiesExtractor);
return userInfoTokenServices;
}
#Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
// May need an OAuth2AuthenticationEntryPoint for non-browser clients
return new LoginUrlAuthenticationEntryPoint(authConfig.getProperty("oauth2.filterCallbackPath"));
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/", "/static/**", "/webjars/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint());
http
.antMatcher("/auth/oauth/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.addFilterAfter(
oauth2ClientContextFilter,
ExceptionTranslationFilter.class)
.addFilterBefore(
oauth2ClientAuthenticationProcessingFilter(),
FilterSecurityInterceptor.class)
.anonymous()
.disable();
}
#Override
protected AuthenticationManager authenticationManager() throws Exception {
return new NoopAuthenticationManager();
}
}
private static class NoopAuthenticationManager implements AuthenticationManager {
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
throw new UnsupportedOperationException(
"No authentication should be done with this AuthenticationManager");
}
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
While accessing the callback url api/auth/oauth/callback, I get following exception:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'scopedTarget.oauth2ClientContext': Scope
'session' is not active for the current thread; consider defining a
scoped proxy for this bean if you intend to refer to it from a
singleton
On searching SO, the suggested solution is to add RequestContextListener bean but even after adding that I got no success.
One solution also suggested using FilterRegistrationBean but I am not using Springboot so I am not sure whether it would have solved my problem or not.
Full exception trace:
2018-02-22 12:47:36,440 - /api/auth/oauth/callback
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'scopedTarget.oauth2ClientContext': Scope
'session' is not active for the current thread; consider defining a
scoped proxy for this bean if you intend to refer to it from a
singleton; nested exception is java.lang.IllegalStateException: No
thread-bound request found: Are you referring to request attributes
outside of an actual web request, or processing a request outside of
the originally receiving thread? If you are actually operating within
a web request and still receive this message, your code is probably
running outside of DispatcherServlet/DispatcherPortlet: In this case,
use RequestContextListener or RequestContextFilter to expose the
current request. at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:355)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at
org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192)
at com.sun.proxy.$Proxy64.getAccessToken(Unknown Source) at
org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:169)
at
org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:105)
at
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:60)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
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:331)
at
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
at
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)
at
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)
at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at
org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83)
at
org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:364)
at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
at
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
at
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
at
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
at
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497) at
org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310) at
org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at
org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
at
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Unknown Source) Caused by:
java.lang.IllegalStateException: No thread-bound request found: Are
you referring to request attributes outside of an actual web request,
or processing a request outside of the originally receiving thread? If
you are actually operating within a web request and still receive this
message, your code is probably running outside of
DispatcherServlet/DispatcherPortlet: In this case, use
RequestContextListener or RequestContextFilter to expose the current
request. at
org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at
org.springframework.web.context.request.SessionScope.get(SessionScope.java:91)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340)
... 55 more
I solved the problem. And in this era of Springboot, someone who is working on a slightly older system, might find the answer useful, so sharing it.
The RequestContextListenerneeds to be added in jetty configuration like this:
context.addEventListener(new RequestContextListener());
I was adding it in my security config file, like this:
#Bean
#Order(0)
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
Someone can find this useful, add following in AbstractAnnotationConfigDispatcherServletInitializer implemntation class:
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addListener(new RequestContextListener());
}

What is the best way to handle Invalid CSRF token found in the request when session times out in Spring security

I"m using Spring MVC/Security 3.X. The issue is that I'm getting 403 at the login page whenever the session timeout, where underneath "InvalidCsrfTokenException" is being thrown by Spring framework :
threw exception [org.springframework.security.web.csrf.InvalidCsrfTokenException: Invalid CSRF Token '7b4aefe9-6685-4c70-adf1-0d633680523a' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.] with root cause
org.springframework.security.web.csrf.InvalidCsrfTokenException: Invalid CSRF Token '7b4aefe9-6685-4c70-adf1-0d633680523a' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
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:107)
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:107)
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:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:119)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
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:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
As It's mentioned in spring documentation the CSRF timeout is an issue that should be handled. One way to handle this scenario is to have custom AccessDeniedHandler where we an intercept CSRF exception. Something like:
static class CustomAccessDeniedHandler extends AccessDeniedHandlerImpl{
#Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException accessDeniedException)
throws IOException, ServletException {
if (accessDeniedException instanceof MissingCsrfTokenException
|| accessDeniedException instanceof InvalidCsrfTokenException) {
//What goes in here???
}
super.handle(request, response, accessDeniedException);
}
}
Question: What is the best way to handle this situation without having to refresh the page( which is bad user experience) or have an endless session? Thanks for your help in advance.
The easiest way I found to handle invalidate CSRF token when session times out at the login page is one of the followings:
Redirect the request again to the login page again vi CustomAccessDeniedHandler:
static class CustomAccessDeniedHandler extends AccessDeniedHandlerImpl{
#Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException accessDeniedException)
throws IOException, ServletException {
if (accessDeniedException instanceof MissingCsrfTokenException
|| accessDeniedException instanceof InvalidCsrfTokenException) {
if(request.getRequestURI().contains("login")){
response.sendRedirect(request.getContextPath()+"/login");
}
}
super.handle(request, response, accessDeniedException);
}
}
Add refresh header as Neil McGuigan suggested:
<meta http-equiv="refresh" content="${pageContext.session.maxInactiveInterval}">
Furthermore you must create a bean for the new CustomAccessDeniedHandler and register it. The following example shows this for Java config.
In any config class:
#Bean
public AccessDeniedHandler accessDeniedHandler() {
return new CustomAccessDeniedHandler();
}
In your security config modify the configure method as follows:
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
// ...
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
}
Also see here.
a more Optimum solution will be for Spring security to handle this situation in their framework.
When using Spring Security, you must send the '_csrf', there are the following ways:
In Form:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
In Ajax:
<head>
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
<!-- ... -->
</head>
$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
Source: http://docs.spring.io/autorepo/docs/spring-security/3.2.0.CI-SNAPSHOT/reference/html/csrf.html
I using construct: csrf().disable(). After that the error message will be disapeared and the app works properly (under Spring Boot 2.3, JSF 2.4, JDK 14):
#Configuration
#EnableWebSecurity(debug = false)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.httpBasic().disable().csrf().disable();
}
}

Java-Spring, strange NullPointerException

I'll explain the situation.
I have an application web, java + spring + hibernate. Actually, i want to integrate DWR with Spring, so I did all the configuration and I think what I did works fine since I get this windows:
Now, we can focus on the findUsername(String username) methodo inside the dwr code:
#Autowired
UserBo userBo;
public boolean findUsername(String username) {
System.out.println("I'm in the DWR");
try {
User user = userBo.findByUsername(username);
if(user != null) {
return true;
}
else {
return false;
}
}
catch (Exception e) {
System.out.println(e.toString());
return false;
}
}
And this is the code of userBo.findByUsername(String username) methodo:
public User findByUsername(String username) {
System.out.println("I'm in the BO");
return userDao.findByUsername(username);
}
And the DAO Code:
#Transactional
public User findByUsername(String username) {
session = sessionFactory.openSession();
System.out.println("I'm in the DAO");
String hql = "FROM User Tab WHERE Tab.username= :username";
Query query = session.createQuery(hql);
query.setParameter("username", username);
#SuppressWarnings("unchecked")
List<User> userFound = (List<User>) query.list();
if (userFound.size() > 0) {
session.close();
return userFound.get(0);
}
return null;
}
But when the code reach userBo.findByUsername(username); method call i get the NullPointerException.
I'm pretty sure the bo + day working good because I've used it in some other part of the application.
I don't understand the problem.
Can someone help me?
EDIT: The StackTrace
lcc.dwr.CCServiceDWR.findUsername(CCServiceDWR.java:26)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.directwebremoting.impl.CreatorModule$1.doFilter(CreatorModule.java:229)
org.directwebremoting.impl.CreatorModule.executeMethod(CreatorModule.java:241)
org.directwebremoting.impl.DefaultRemoter.execute(DefaultRemoter.java:379)
org.directwebremoting.impl.DefaultRemoter.execute(DefaultRemoter.java:332)
org.directwebremoting.dwrp.BaseCallHandler.handle(BaseCallHandler.java:104)
org.directwebremoting.servlet.UrlProcessor.handle(UrlProcessor.java:120)
org.directwebremoting.spring.DwrController.handleRequestInternal(DwrController.java:234)
org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:822)
javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
If spring context is fully initialized spring guarantees that all #autowired fields are not-null beans.
However if you call some bean's method before spring context is fully initialized, the #autowired field can be null.
Check if you call findUsername(String username) before context is ready and if yes - this may be the reason...
If you want to do some call and be sure that context is ready try such pattern:
#Component
public class SpringContextMonitor implements ApplicationListener<ApplicationEvent> {
#Autowired
private SomeDao dao;
...
#Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent) {
onStart((ContextRefreshedEvent) event);
}
}
private void onStart(ContextRefreshedEvent event) {
// do your initialization here
dao.getSomething();
dao2.getSomething();
...
}
...
}
In that code, method onStart is call just after context become ready.
Found the problem: I misses this line in the dwr-servlet.xml
<context:component-scan base-package="lcc.*" />

Catching Hibernate exceptions

I have a #Repository as follows:
#Repository
public class OrderRepository {
#Autowired
SessionFactory sessionFactory;
public void update(Order order) {
sessionFactory.getCurrentSession().update(order);
}
}
Which is called by a #Service as follows:
#Transactional
#Service
public class OrderService {
#Autowired
OrderRepository orderRepository;
public void updateOrder(Order order) {
orderRepository.update(order);
}
}
There are some instances where the order being updated has been removed from the database (this is expected and is benign). When this occurs an exception is thrown:
SEVERE: Servlet.service() for servlet [DispatcherServlet] in context with path [/project] threw exception [Request processing failed; nested exception is org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1] with root cause
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:81)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:63)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3281)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3183)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:159)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:555)
at org.springframework.transaction.support.AbstractOrderTransactionManager.processCommit(AbstractOrderTransactionManager.java:757)
at org.springframework.transaction.support.AbstractOrderTransactionManager.commit(AbstractOrderTransactionManager.java:726)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
at uk.co.domain.services.OrderService$$EnhancerBySpringCGLIB$$35a2d392.updateOrder(<generated>)
at uk.co.domain.controllers.OrderController.test(RequestController.java:51)
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:749)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
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.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:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
I am trying to catch the HibernateOptimisticLockingFailureException within the repository:
#Repository
public class OrderRepository {
#Autowired
SessionFactory sessionFactory;
public void update(Order order) {
try {
sessionFactory.getCurrentSession().update(order);
} catch (HibernateOptimisticLockingFailureException e) {
System.out.println("Exception occurred");
}
}
}
Sadly it does not work and the user still sees the exception. I have also tried catching HibernateException and StaleStateException and neither of these work either.
I tried adding the same try/catch to the Service instead of the Repository, but this does not work. I would appreciate any pointers.
The actual update query is executed at flush time. Not when you're calling update() on the session. In this particular case, the flush happens just before the transaction wrapping the call to the service method is committed. BTW, that can be seen in the stack trace:
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
So, if you want to catch the exception, you should catch it outside of the service:
try {
orderService.updateOrder(order);
}
catch (ConcurrencyFailureException e) {
...
}
Even if you explicitely flush() from inside the service or DAO method, catching the exception there is a bad idea, since it will leave the Hibernate session in an unreliable state. The transaction should be rollbacked and the session should be closed immediately. That's what happens automatically if you let the exception bubble, so you'd better catch it in the code which calls the service.

Categories