You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While examining the error, I found an issue within the asynchronous dispatch logic of AwsAsyncContext when interacting with Spring's DispatcherServlet.
Premature Re-dispatch: Currently, AwsAsyncContext prematurly triggers re-dispatch.
When handling asynchronous requests with DispatcherServlet, DispatcherServlet'sdoDispatch should be called to complete the initial request. Only after the initial request concludes, should the doDispatch be called again for re-dispatch. However, in the present implementation, this sequence is disrupted. During the processing of the initial request by the doDispatch method, the dispatch method of AwsAsyncContext is invoked, which in turn directly calls the doFilter method for immediate re-dispatch. This leads to premature execution of the re-dispatch before the post-processing logic of doDispatch(which is handling the initial request) is executed.
EntityManager Bind Timing Issue: While using Spring JPA, due to the aforementioned issue, an error arises when trying to bind the EntityManager to threadLocal during the preHandle phase of the re-dispatch. This is because the EntityManager is already bound from the initial request, and the post-processing logic meant to unbind it hasn't been executed yet. As a result, attempting to bind it again triggers the following error:
Value [org.springframework.orm.jpa.EntityManagerHolder@38a6ca39] already bound to key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@39296cef].
Proposed Solution
To resolve this, I made modifications to the handleRequest function within SpringBootLambdaContainerHandler and dispatch function within AwsAsyncContext.
The snippet for the proposed solution is as follows
publicvoiddispatch() {
// ... [other code]if (!dispatchStarted.get()) {
dispatchStarted.set(true);
} else {
dispatched.set(true);
// Removed the line that directly calls doFilternotifyListeners(NotificationType.START_ASYNC, null);
}
// ... [other code]
}
By ensuring that the post-processing of the initial request is complete and only then re-invoking the doFilter when necessary, we can bypass the issues mentioned above.
If there's an opportunity for this to be reviewed and merged to main, I would be appreciated. If this seems acceptable, I'd like to create a PR.
START RequestId: d13bf2c0-32e4-4f4b-90e6-ec70f34e30eb Version: $LATEST
--
2023-09-07T08:38:45.728Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.FilterChainHolder : Starting REQUEST: filter 0-characterEncodingFilter
2023-09-07T08:38:45.728Z DEBUG 10 --- [ main] c.a.s.p.i.s.AwsProxyHttpServletRequest : Called set character encoding to UTF-8 on a request without a content type. Character encoding will not be set
2023-09-07T08:38:45.728Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.FilterChainHolder : Starting REQUEST: filter 1-formContentFilter
2023-09-07T08:38:45.728Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.FilterChainHolder : Starting REQUEST: filter 2-requestContextFilter
2023-09-07T08:38:45.728Z TRACE 10 --- [ main] o.s.b.w.s.f.OrderedRequestContextFilter : Bound request context to thread: com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest@e344ad3
2023-09-07T08:38:45.728Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.FilterChainHolder : Starting REQUEST: filter 4-com.amazonaws.serverless.proxy.internal.servlet.FilterChainManager$ServletExecutionFilter
2023-09-07T08:38:45.728Z TRACE 10 --- [ main] o.s.web.servlet.DispatcherServlet : GET "/hello", parameters={}, headers={masked} in DispatcherServlet 'dispatcherServlet'
2023-09-07T08:38:45.728Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.AwsHttpServletRequest : Trying to access session. Lambda functions are stateless and should not rely on the session
2023-09-07T08:38:45.728Z TRACE 10 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'controller'
2023-09-07T08:38:45.728Z TRACE 10 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.test.asyncjpa.Controller#hello()
2023-09-07T08:38:45.728Z DEBUG 10 --- [ main] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2023-09-07T08:38:45.728Z TRACE 10 --- [ main] .i.SessionFactoryImpl$SessionBuilderImpl : Opening Hibernate Session. tenant=null
2023-09-07T08:38:45.728Z TRACE 10 --- [ main] org.hibernate.internal.SessionImpl : Opened Session [9b062b94-976a-481e-ac36-6f0106cd5577] at timestamp: 1694075925728
2023-09-07T08:38:45.729Z TRACE 10 --- [ main] o.s.web.method.HandlerMethod : Arguments: []
2023-09-07T08:38:45.729Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.AwsAsyncContext : Initializing async context for request: /hello - GET
2023-09-07T08:38:45.729Z DEBUG 10 --- [ main] c.a.s.p.i.s.AwsProxyHttpServletRequest : Starting async context for request: af2e6256-dece-43a9-8cd3-7797c3282b36
2023-09-07T08:38:45.729Z DEBUG 10 --- [ main] o.s.w.c.request.async.WebAsyncManager : Started async request
2023-09-07T08:38:45.730Z DEBUG 10 --- [ main] o.s.w.c.request.async.WebAsyncManager : Async result set, dispatch to /hello
2023-09-07T08:38:45.730Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.AwsAsyncContext : Dispatching request
2023-09-07T08:38:45.730Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.FilterChainHolder : Starting ASYNC: filter 0-characterEncodingFilter
2023-09-07T08:38:45.730Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.FilterChainHolder : Starting ASYNC: filter 1-formContentFilter
2023-09-07T08:38:45.730Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.FilterChainHolder : Starting ASYNC: filter 2-requestContextFilter
2023-09-07T08:38:45.730Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.FilterChainHolder : Starting ASYNC: filter 4-com.amazonaws.serverless.proxy.internal.servlet.FilterChainManager$ServletExecutionFilter
2023-09-07T08:38:45.730Z TRACE 10 --- [ main] o.s.web.servlet.DispatcherServlet : "ASYNC" dispatch for GET "/hello", parameters={}, headers={masked} in DispatcherServlet 'dispatcherServlet'
2023-09-07T08:38:45.730Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.AwsHttpServletRequest : Trying to access session. Lambda functions are stateless and should not rely on the session
2023-09-07T08:38:45.730Z TRACE 10 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'controller'
2023-09-07T08:38:45.730Z TRACE 10 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.test.asyncjpa.Controller#hello()
2023-09-07T08:38:45.730Z DEBUG 10 --- [ main] o.s.web.servlet.DispatcherServlet : Unresolved failure from "ASYNC" dispatch: java.lang.IllegalStateException: Already value [org.springframework.orm.jpa.EntityManagerHolder@6345e7b9] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@4604b900] bound to thread
2023-09-07T08:38:45.730Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.AwsHttpServletRequest : Trying to access session. Lambda functions are stateless and should not rely on the session
2023-09-07T08:38:45.730Z TRACE 10 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Applying default cacheSeconds=-1
2023-09-07T08:38:45.731Z TRACE 10 --- [ main] o.s.w.s.v.InternalResourceViewResolver : View with key [hello] served from cache
2023-09-07T08:38:45.731Z DEBUG 10 --- [ main] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/avif, image/webp, image/apng, application/xml;q=0.9, */*;q=0.8, application/signed-exchange;v=b3;q=0.7]
2023-09-07T08:38:45.731Z TRACE 10 --- [ main] o.s.web.servlet.DispatcherServlet : Rendering view [org.springframework.web.servlet.view.InternalResourceView: name 'hello'; URL [hello]]
2023-09-07T08:38:45.731Z DEBUG 10 --- [ main] o.s.w.servlet.view.InternalResourceView : View name 'hello', model {}
2023-09-07T08:38:45.731Z DEBUG 10 --- [ main] o.s.web.servlet.DispatcherServlet : Error rendering view [org.springframework.web.servlet.view.InternalResourceView: name 'hello'; URL [hello]]
jakarta.servlet.ServletException: Circular view path [hello]: would dispatch back to the current handler URL [/hello] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:210) ~[task/:na]
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:148) ~[task/:na]
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1415) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1159) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1098) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[task/:na]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[task/:na]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[task/:na]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:527) ~[task/:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[task/:na]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainManager$ServletExecutionFilter.doFilter(FilterChainManager.java:374) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[task/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[task/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[task/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.AwsLambdaServletContainerHandler.doFilter(AwsLambdaServletContainerHandler.java:154) ~[task/:na]
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:174) ~[task/:na]
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:47) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:214) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:257) ~[task/:na]
at com.test.asyncjpa.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:30) ~[task/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
2023-09-07T08:38:45.732Z DEBUG 10 --- [ main] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2023-09-07T08:38:45.732Z TRACE 10 --- [ main] org.hibernate.internal.SessionImpl : Closing session [9b062b94-976a-481e-ac36-6f0106cd5577]
2023-09-07T08:38:45.732Z TRACE 10 --- [ main] o.h.e.jdbc.internal.JdbcCoordinatorImpl : Closing JDBC container [org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl@4e904fd5]
2023-09-07T08:38:45.732Z TRACE 10 --- [ main] o.h.r.j.i.ResourceRegistryStandardImpl : Releasing JDBC resources
2023-09-07T08:38:45.732Z TRACE 10 --- [ main] o.h.r.j.i.LogicalConnectionManagedImpl : Closing logical connection
2023-09-07T08:38:45.732Z TRACE 10 --- [ main] o.h.r.j.i.LogicalConnectionManagedImpl : Logical connection closed
2023-09-07T08:38:45.732Z DEBUG 10 --- [ main] o.s.web.servlet.DispatcherServlet : Unresolved failure from "ASYNC" dispatch: jakarta.servlet.ServletException: Circular view path [hello]: would dispatch back to the current handler URL [/hello] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
2023-09-07T08:38:45.732Z DEBUG 10 --- [ main] c.a.s.p.i.servlet.AwsHttpServletRequest : Trying to access session. Lambda functions are stateless and should not rely on the session
2023-09-07T08:38:45.732Z TRACE 10 --- [ main] o.s.b.w.s.f.OrderedRequestContextFilter : Cleared thread-bound request context: com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest@e344ad3
2023-09-07T08:38:45.732Z ERROR 10 --- [ main] c.a.s.p.internal.LambdaContainerHandler : Error while handling request
jakarta.servlet.ServletException: Circular view path [hello]: would dispatch back to the current handler URL [/hello] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:210) ~[task/:na]
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:148) ~[task/:na]
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1415) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1159) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1098) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[task/:na]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[task/:na]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[task/:na]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:527) ~[task/:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[task/:na]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainManager$ServletExecutionFilter.doFilter(FilterChainManager.java:374) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[task/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[task/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[task/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.AwsLambdaServletContainerHandler.doFilter(AwsLambdaServletContainerHandler.java:154) ~[task/:na]
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:174) ~[task/:na]
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:47) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:214) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:257) ~[task/:na]
at com.test.asyncjpa.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:30) ~[task/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
2023-09-07T08:38:45.733Z ERROR 10 --- [ main] c.a.s.proxy.AwsProxyExceptionHandler : Called exception handler for:
jakarta.servlet.ServletException: Circular view path [hello]: would dispatch back to the current handler URL [/hello] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:210) ~[task/:na]
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:148) ~[task/:na]
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1415) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1159) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1098) ~[task/:na]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[task/:na]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[task/:na]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[task/:na]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:527) ~[task/:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[task/:na]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainManager$ServletExecutionFilter.doFilter(FilterChainManager.java:374) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[task/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[task/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[task/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.servlet.AwsLambdaServletContainerHandler.doFilter(AwsLambdaServletContainerHandler.java:154) ~[task/:na]
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:174) ~[task/:na]
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:47) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:214) ~[task/:na]
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:257) ~[task/:na]
at com.test.asyncjpa.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:30) ~[task/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185) ~[aws-lambda-java-runtime-interface-client-2.3.1-SNAPSHOT.jar:2.3.1-SNAPSHOT]
jakarta.servlet.ServletException: Circular view path [hello]: would dispatch back to the current handler URL [/hello] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:210)
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:148)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1415)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1159)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1098)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:527)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainManager$ServletExecutionFilter.doFilter(FilterChainManager.java:374)
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90)
at com.amazonaws.serverless.proxy.internal.servlet.AwsLambdaServletContainerHandler.doFilter(AwsLambdaServletContainerHandler.java:154)
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:174)
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:47)
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:214)
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:257)
at com.test.asyncjpa.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:30)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379)
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185)
END RequestId: d13bf2c0-32e4-4f4b-90e6-ec70f34e30eb
REPORT RequestId: d13bf2c0-32e4-4f4b-90e6-ec70f34e30eb Duration: 8.30 ms Billed Duration: 9 ms Memory Size: 4096 MB Max Memory Used: 253 MB
### Tasks
The text was updated successfully, but these errors were encountered:
To help us debug your issue fill in the basic information below using the options provided
Serverless Java Container version:
2.0.0-M2
Implementations:
Spring Boot 3
Framework version:
SpringBoot 3.1.3
Frontend service:
HTTP API
Deployment method:
Console
Scenario
Attempted to handle async requests in a SpringBoot3 application with JPA dependency.
Expected behavior
Return a 200 response
Actual behavior
502 error from Lambda
Steps to reproduce
Here is an example springboot3 project that can reproduce this issue.
https://github.com/2012160085/aws-serverless-java-container-async-jpa-example
Clone this repo and run
main
inAsyncJpaApplication
.Problem
While examining the error, I found an issue within the asynchronous dispatch logic of
AwsAsyncContext
when interacting with Spring'sDispatcherServlet
.Premature Re-dispatch: Currently,
AwsAsyncContext
prematurly triggers re-dispatch.When handling asynchronous requests with
DispatcherServlet
,DispatcherServlet
'sdoDispatch
should be called to complete the initial request. Only after the initial request concludes, should thedoDispatch
be called again for re-dispatch. However, in the present implementation, this sequence is disrupted. During the processing of the initial request by thedoDispatch
method, thedispatch
method ofAwsAsyncContext
is invoked, which in turn directly calls thedoFilter
method for immediate re-dispatch. This leads to premature execution of the re-dispatch before the post-processing logic ofdoDispatch
(which is handling the initial request) is executed.EntityManager Bind Timing Issue: While using Spring JPA, due to the aforementioned issue, an error arises when trying to bind the
EntityManager
to threadLocal during the preHandle phase of the re-dispatch. This is because theEntityManager
is already bound from the initial request, and the post-processing logic meant to unbind it hasn't been executed yet. As a result, attempting to bind it again triggers the following error:Proposed Solution
To resolve this, I made modifications to the
handleRequest
function withinSpringBootLambdaContainerHandler
anddispatch
function withinAwsAsyncContext
.The snippet for the proposed solution is as follows
By ensuring that the post-processing of the initial request is complete and only then re-invoking the doFilter when necessary, we can bypass the issues mentioned above.
If there's an opportunity for this to be reviewed and merged to main, I would be appreciated. If this seems acceptable, I'd like to create a PR.
folked repo: https://github.com/2012160085/aws-serverless-java-container
Full log output
This is full TRACE log from CloudWatch
The text was updated successfully, but these errors were encountered: