I use Spring-boot tomcat in my project.
I have multipart file upload and the limit is set as follows.
#Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize("1MB");
factory.setMaxRequestSize("1MB");
return factory.createMultipartConfig();
}
But, if user is trying to load a file of more than 1 MB, it is throwing some exception.
led; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (4719402) exceeds the configured maximum (1048576)] with root cause
org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (4719402) exceeds the configured maximum (1048576)
at org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:811) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.tomcat.util.http.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:256) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:280) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.connector.Request.parseParts(Request.java:2734) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.connector.Request.parseParameters(Request.java:3073) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.connector.Request.getParameter(Request.java:1095) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:380) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:70) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-embed-core-8.0.28.jar:8.0.28]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-embed-core-8.0.28.jar:8.0.28]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_73]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_73]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.28.jar:8.0.28]
I am not sure, how can i handle this exception so that user will get some meaningful error message in the screen.
I am not sure, but i think you can handle this exception using error page:
// in web.xml
<error-page>
<error-code>413</error-code>
<location>/ErrorHandlerServlet</location>
</error-page>
... handlers for other http codes ...
413 - http code for "Request Entity Too Large" error.
Declare ErrorHandlerServlet error page (e.g. create JSP with <%# page page isErrorPage="true" %> directive) and handle 413:
Integer statusCode = (Integer) httpRequest.
getAttribute("javax.servlet.error.status_code");
if (statusCode == 413) {
// print message...
}
// handle another error...
You do something like this:
catch (Exception e) {
redirectAttributes.addFlashAttribute("message",
"You failed to upload, because file size too big " + name + " => " + e.getMessage());
}
Catch exception, then push a flash message to user's browser: redirectAttributes.addFlashAttribute()
This is offical tutorial for handling your uploading process (in Spring): https://spring.io/guides/gs/uploading-files/
Related
When building a rest web service using Spring Mvc in SpringBoot project, exceptions eccured as below:
2017-05-24 10:16:10.849 ERROR 10 --- [io-8080-exec-89] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet dispatcherServlet threw exception
java.lang.IllegalStateException: getWriter() has already been called for this response
at org.apache.catalina.connector.Response.getOutputStream(Response.java:575)
at org.apache.catalina.connector.ResponseFacade.getOutputStream(ResponseFacade.java:194)
at javax.servlet.ServletResponseWrapper.getOutputStream(ServletResponseWrapper.java:100)
at org.springframework.http.server.ServletServerHttpResponse.getBody(ServletServerHttpResponse.java:89)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:237)
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:232)
at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:198)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:130)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:726)
at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:592)
at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:526)
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:389)
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:254)
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:349)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:175)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
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)
However, the rest service functions well, and can be called and return expected results. Here is the code block where i call the method getWritter():
#RequestMapping(value = "/kafka/picfile", method = RequestMethod.POST)
public void uploadPicture(HttpServletResponse response) {
String result = "";
response.reset();
response.setCharacterEncoding("UTF-8");
PrintWriter writer = null;
String prefix = "<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
"</head>\n" +
"<body>";
String suffix = "</body>\n" +
"</html>";
try {
writer = response.getWriter();
Picture picture = new Picture("testname", "this is a test picture");
result = kafkaService.send(picture);
if(!"success".equals(result)){
result = "error[xxxxxxxxxxxxx]";
}
} catch (Exception e) {
result = "error["+e.getMessage()+"]";
}
result = prefix+"\n"+result+"\n"+suffix;
if(writer != null){
writer.write(result);
writer.flush();
writer.close();
}
}
I have viewed many concerned questions and corresponding answers, but none of them really suits my problem. Looking forward to your comments. Thanks!
Add response.reset(); before using response.
example:
response.reset();
response.getOutputStream();
You can see in stack trace HandlerMethodReturnValueHandlerComposite, this means something is returning a response to Spring "handler".
Then Spring uses the AbstractJackson2HttpMessageConverter to convert the returned value.
So I guess the problem is not in this method, please inspect or post here all your controller code at least.
My spring boot application uses mongo during startup and it start very smoothly.
Now after start up I Shut the mongo and hit any controller of my application. But the control never reaches to the controller level Hence mongo exception can not be handled by #ControllerAdvice.
I have also tried to make a generic exception handler and registered that class in application.java like this
#Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return container -> {
ErrorPage error401Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,"/error");
container.addErrorPages(error401Page);
};
This works fine as long as mongo is up and running.
Once mongo is down I get the following stack trace
org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:77)
org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2114)
org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:1904)
org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:1712)
org.springframework.data.mongodb.core.MongoTemplate.findById(MongoTemplate.java:636)
org.springframework.session.data.mongo.MongoOperationsSessionRepository.findSession(MongoOperationsSessionRepository.java:127)
org.springframework.session.data.mongo.MongoOperationsSessionRepository.getSession(MongoOperationsSessionRepository.java:78)
org.springframework.session.data.mongo.MongoOperationsSessionRepository.getSession(MongoOperationsSessionRepository.java:44)
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:326)
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:343)
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:214)
javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:255)
org.springframework.web.util.WebUtils.getSessionId(WebUtils.java:288)
org.springframework.web.servlet.FrameworkServlet.publishRequestHandledEvent(FrameworkServlet.java:1077)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:164)
org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:112)
org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:64)
org.springframework.boot.web.support.ErrorPageFilter.forwardToErrorPage(ErrorPageFilter.java:187)
org.springframework.boot.web.support.ErrorPageFilter.handleException(ErrorPageFilter.java:170)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:134)
org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:61)
org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:94)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:112)
org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)
JBWEB000071: root cause com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches ReadPreferenceServerSelector{readPreference=primary}. Client view of cluster state is {type=STANDALONE, servers=[{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused: connect}}]
com.mongodb.connection.BaseCluster.createTimeoutException(BaseCluster.java:369)
com.mongodb.connection.BaseCluster.selectServer(BaseCluster.java:101)
com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.<init>(ClusterBinding.java:75)
com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.<init>(ClusterBinding.java:71)
com.mongodb.binding.ClusterBinding.getReadConnectionSource(ClusterBinding.java:63)
com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:210)
com.mongodb.operation.FindOperation.execute(FindOperation.java:482)
com.mongodb.operation.FindOperation.execute(FindOperation.java:79)
com.mongodb.Mongo.execute(Mongo.java:772)
com.mongodb.Mongo$2.execute(Mongo.java:759)
com.mongodb.DBCollection.findOne(DBCollection.java:777)
com.mongodb.DBCollection.findOne(DBCollection.java:747)
com.mongodb.DBCollection.findOne(DBCollection.java:694)
org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2143)
org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2127)
org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:1901)
org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:1712)
org.springframework.data.mongodb.core.MongoTemplate.findById(MongoTemplate.java:636)
org.springframework.session.data.mongo.MongoOperationsSessionRepository.findSession(MongoOperationsSessionRepository.java:127)
org.springframework.session.data.mongo.MongoOperationsSessionRepository.getSession(MongoOperationsSessionRepository.java:78)
org.springframework.session.data.mongo.MongoOperationsSessionRepository.getSession(MongoOperationsSessionRepository.java:44)
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:326)
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:343)
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:214)
javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:255)
org.springframework.web.util.WebUtils.getSessionId(WebUtils.java:288)
org.springframework.web.servlet.FrameworkServlet.publishRequestHandledEvent(FrameworkServlet.java:1077)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:164)
org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:112)
org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:64)
org.springframework.boot.web.support.ErrorPageFilter.forwardToErrorPage(ErrorPageFilter.java:187)
org.springframework.boot.web.support.ErrorPageFilter.handleException(ErrorPageFilter.java:170)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:134)
org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:61)
org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:94)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:112)
org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)
For every controller I am getting this stack trace. I want to handle this gracefully. Please suggest at what point I should handle mongo connection exceptions after application startup. I am using spring-boot-starter-data-mongodb maven dependency for my project
SessionRepositoryFilter http://docs.spring.io/spring-session/docs/current/api/org/… added by your #EnableMongoHttpSession is the code that fails here. It executes before any controller-related machinery (including advices) may come into play, so if it fails, it does so before any controller scope is created.
But you can create a filter, insert it into filter chain before Mongo Http Session filter and try to catch and handle that exception:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
try {
chain.doFilter(request, response);
} catch (TranslatedException e) {
// somehow handle it, like display an error message
}
}
where TranslatedException is the exception to which spring translates MongoTimeoutException (it cannot be seen from your stack trace).
I have a Spring Boot application that uses Data JPA / Hibernate / JDBC and MySQL with a default timeout of 8 hours. When left running overnight, it crashes with the following exception:
javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: could not prepare statement
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:458)
at repository.NativeQuery.findMostRecentRegistrations(NativeQuery.java:110)
at admin.AdminController.adminDashboard(AdminController.java:126)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:237)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
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:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:157)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:103)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:120)
at org.springframework.boot.context.web.ErrorPageFilter.access$000(ErrorPageFilter.java:61)
at org.springframework.boot.context.web.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:95)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:113)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:614)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
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)
Caused by: org.hibernate.exception.JDBCConnectionException: could not prepare statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:65)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:196)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:160)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1885)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1839)
at org.hibernate.loader.Loader.doQuery(Loader.java:910)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355)
at org.hibernate.loader.Loader.doList(Loader.java:2554)
at org.hibernate.loader.Loader.doList(Loader.java:2540)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370)
at org.hibernate.loader.Loader.list(Loader.java:2365)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:353)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1909)
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:311)
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:141)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:449)
... 112 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
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:422)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.Util.getInstance(Util.java:387)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:917)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:896)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:885)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:860)
at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1235)
at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1230)
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4132)
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4101)
at sun.reflect.GeneratedMethodAccessor146.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126)
at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81)
at com.sun.proxy.$Proxy78.prepareStatement(Unknown Source)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:162)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:186)
... 128 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 39,274,020 milliseconds ago. The last packet sent successfully to the server was 39,274,020 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
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:422)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:981)
at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3652)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2460)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1962)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2066)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1863)
... 125 more
Caused by: java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3634)
... 133 more
Following recommendations from Spring Boot JPA - configuring auto reconnect and other posts, I have the following settings in application.properties which should keep the connection alive:
spring.datasource.url: jdbc:mysql://localhost:3306/<database-name>
spring.datasource.username=<username>
spring.datasource.password=<password>
spring.datasource.driverClassName=com.mysql.jdbc.Driver
#
spring.datasource.testWhileIdle=true
spring.datasource.timeBetweenEvictionRunsMillis=3600000
spring.datasource.validationQuery=SELECT 1
spring.datasource.testOnBorrow=true
#
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
The only clue I have is that the crash happens upon a native query (see line #4 in the stack trace above), while other database accesses seem to still work without problems after the app runs overnight. (The query itself works perfectly fine, so I am not publishing it here for brevity.) This tends to suggest that after a native query is run, a connection to the database over which it was executed is retained but not kept alive. Is there a setting to maintain that connection?
Update:
I added the following method to my NativeQuery class (where all native query methods reside):
#Component
public class NativeQuery {
...
private static final long KEEP_ALIVE_MILLIS = 60 * 60 * 1000;
#Scheduled(initialDelay = KEEP_ALIVE_MILLIS, fixedRate = KEEP_ALIVE_MILLIS)
private void connectionKeepAlive() {
boolean success = true;
String msg = "Database connection keep-alive ";
try {
Query query = entityManager.createNativeQuery("SELECT 1");
BigInteger result = (BigInteger)query.getSingleResult();
if (result != null && result.equals(BigInteger.ONE)) {
msg += "succeeded";
}
else {
msg += "failed with result " + (result != null ? result.toString() : "N/A");
success = false;
}
}
catch (Exception e) {
msg += "crashed with exception: " + e.toString();
success = false;
}
if (success) {
if (log.isInfoEnabled())
log.info(msg);
}
else {
if (log.isErrorEnabled())
log.error(msg);
}
}
...
}
This code executes a keep-alive query once per hour. I let it run overnight and when I logged back in and executed a native query, the above exception was no longer reported. So, this fix seems to work.
However, this also implies that all native queries share the same connection. What happens if multiple queries need to be concurrently executed and there is only a single instance of the NativeQuery class, per Spring Boot's general instantiation rules?
A side comment: Notice how query.getSingleResult() returns a BigInteger. Technically, SELECT 1 returns MySQL BIGINT, which is a 64-bit integer, so a Java long would suffice. Inside Hibernate, someone simply translated BIGINT to BigInteger, even though the database dialect is clearly set as MySQL5.
I suggest you to add this config to your application.properties add retest :
spring.datasource.validationQuery=SELECT 1
spring.datasource.testOnBorrow=true
You are using tomcat connection pool. you can maybe try to use a more robust connection pool, like HikariCP
I have developed a simple web application that accesses Facebook data through Spring Boot (v1.2.6.RELEASE) and Spring Social Facebook (v2.0.2.RELEASE) similar to the example given here
I have created a new App in Facebook which use Graph API version 2.5.
According to this example i have modified facebookConnect.html putting this different scope to the method POST request:
<html>
<head>
<title>Facebook Extractor</title>
</head>
<body>
<h3>Connect to Facebook</h3>
<form action="/recommender/connect/facebook" method="POST">
<input type="hidden" name="scope" value="public_profile, user_friends, email, user_likes" />
<div class="formInfo">
<p>You aren't connected to Facebook yet. Click the button to connect this application with your Facebook account.</p>
</div>
<p><button type="submit">Connect to Facebook</button></p>
</form>
</body>
handled by ConnectController which kick off the OAuth authorization code flow...
After OAuth success (with permission granted) and connection is done, i get the following error:
(#3) application does not have the capability to make this api call.
Here the main part of the controller which handle the redirect from Facebook App:
#Controller
#Scope(value="session")
public class FacebookExtractor {
private Logger logger = Logger.getLogger(FacebookExtractor.class);
private Facebook facebook;
#Autowired
GraphDatabase graphDatabase;
#Autowired
PersonRepository personRepository;
#Autowired
UserProfileRepository userProfileRepository;
#Autowired
AttributeDefinitionRepository attributeDefinitionRepository;
#Autowired
AttributeRepository attributeRepository;
#Autowired
ConceptRepository conceptRepository;
#Autowired
RecommenderGovConsumerRepository recGovRepository;
#Autowired
GovConsumerInfluencedByGovConsumerRelationshipRepository influenceRepository;
#Autowired
ExtractorListener listener;
private String userBind;
#Inject
public FacebookExtractor(Facebook facebook) {
this.facebook = facebook;
}
#RequestMapping(method = RequestMethod.GET, value = "/facebookExtractor")
public ModelAndView FacebookDataUserExtraction() {
if (!facebook.isAuthorized()) {
return new ModelAndView("redirect:/recommender/connect/facebook");
}
String account=userBind;
Long netId = null;
Transaction tx = graphDatabase.beginTx();
try {
User user = facebook.userOperations().getUserProfile();
Person p = savePerson(user);
UserProfile up = saveUserProfile(user);
up.setUser(p);
userProfileRepository.save(up);
p.setProfile(up);
saveSocialInteractions(up);
saveSocialPreferences(up);
personRepository.save(p);
netId=p.getId();
tx.success();
} finally {
tx.close();
}
if (account != null) {
/*
* Binding di Facebook riuscito.
*/
listener.onProfileDataCompleted(netId, SNAccountType.Facebook);
listener.onInteractionsCompleted(netId, InteractionType.Friendship, SNAccountType.Facebook);
return new ModelAndView("redirect:http://localhost:8080/portal",
"accountF", account);
} else {
//vista opportuna per estrazione avvenuta senza bind
return new ModelAndView("facebookNoBindExtraction");
}
}
Watching the stack trace error, seems i'm getting error at this line in controller:
User user = facebook.userOperations().getUserProfile();
but it is strange because I should have permission to get basic user profile data by default.
Note: the same code with an older App in Facebook which use Graph API version 2.3 works perfectly, but i need a new one for different purpose and can't force a new App in Facebook to use that version...
Here the stack error i get....
12:01:16.953 [http-nio-9080-exec-5] ERROR
o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet
[dispatcherServlet] in context with path [] threw exception [Request
processing failed; nested exception is
org.springframework.social.UncategorizedApiException: (#3) Application
does not have the capability to make this API call.] with root cause
org.springframework.social.UncategorizedApiException: (#3) Application
does not have the capability to make this API call. at
org.springframework.social.facebook.api.impl.FacebookErrorHandler.handleFacebookError(FacebookErrorHandler.java:91)
~[spring-social-facebook-2.0.2.RELEASE.jar:2.0.2.RELEASE] at
org.springframework.social.facebook.api.impl.FacebookErrorHandler.handleError(FacebookErrorHandler.java:59)
~[spring-social-facebook-2.0.2.RELEASE.jar:2.0.2.RELEASE] at
org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:614)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:570)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:253)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.social.facebook.api.impl.FacebookTemplate.fetchObject(FacebookTemplate.java:214)
~[spring-social-facebook-2.0.2.RELEASE.jar:2.0.2.RELEASE] at
org.springframework.social.facebook.api.impl.FacebookTemplate.fetchObject(FacebookTemplate.java:209)
~[spring-social-facebook-2.0.2.RELEASE.jar:2.0.2.RELEASE] at
org.springframework.social.facebook.api.impl.UserTemplate.getUserProfile(UserTemplate.java:53)
~[spring-social-facebook-2.0.2.RELEASE.jar:2.0.2.RELEASE] at
org.springframework.social.facebook.api.impl.UserTemplate.getUserProfile(UserTemplate.java:49)
~[spring-social-facebook-2.0.2.RELEASE.jar:2.0.2.RELEASE] at
it.cerict.recommender.extractor.controllers.FacebookExtractor.FacebookDataUserExtraction(FacebookExtractor.java:89)
~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method) ~[na:1.8.0_60] at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
~[na:1.8.0_60] at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
~[na:1.8.0_60] at java.lang.reflect.Method.invoke(Method.java:497)
~[na:1.8.0_60] at
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
~[tomcat-embed-websocket-8.0.26.jar:8.0.26] at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
it.cerict.recommender.config.CORSFilter.doFilter(CORSFilter.java:22)
~[classes/:na] at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE] at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
~[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
[na:1.8.0_60] at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
[na:1.8.0_60] at
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
[tomcat-embed-core-8.0.26.jar:8.0.26] at
java.lang.Thread.run(Thread.java:745) [na:1.8.0_60]
The problem is with PROFILE_FILEDS in
public User getUserProfile(String facebookId) {
return graphApi.fetchObject(facebookId, User.class, PROFILE_FIELDS);
}
Array PROFILE_FIELDS contains many many fields and as I understang correctly spring-social docs, Facebook returned only this fields you have rights to view.
But now something changed:
$curl "https://graph.facebook.com/v2.5/me?access_token=[access_tokens]&fields=[all_the_fields_from_PROFILE_FIELDS]
{"error":{"message":"(#3) Application does not have the capability to make this API call.","type":"OAuthException","code":3,"fbtrace_id":"Antivssjj1d"}}
$ curl "https://graph.facebook.com/v2.3/me?access_token=[access_token]&fields=id,about"
{"id":"1135898619755433"}
In the meantime I've found sollution. Instead
User profile = facebook.userOperations().getUserProfile()
we can use
User profile = facebook.fetchObject("me", User.class, "id", "name", "link", "email");
//Note: facebook = org.springframework.social.facebook.api.Facebook
//Note: User.class = org.springframework.social.facebook.api.User.class
Or wait the update of spring-social-facebook, there is a pull request pending on the repository: https://github.com/spring-projects/spring-social-facebook/pull/171
UPDATE: Fix for me with the 2.0.3.RELEASE version.
I continued to get this error, even after adding the publish_actions scope that my app needed. The issue in my case was that I needed Facebook to review my app. This is the case if your app was created after April 30th, 2014 and one or more of the following is true:
You want your App to be listed in the Facebook App Center
You want to create new, or edit existing, Open Graph actions and stories
Your app asks people for any extended permissions including publish_actions
Have a look at the Facebook Login Review FAQs for more info on the review process.
I'm working on an app with Spring Boot 1.2.5 RELEASE and having a problem that's difficult to replicate, and seems to be related to my session. Doing lots of research indicates that when using the #SessionAttribute annotation my session will end when my web page accesses another controller. Although I also found some information that indicates this is no longer true with the most recent Spring Boot. Also, the other controller does not use the same template or session identifier as this controller.
Alternatively I think my session may be expiring, but I can't seem to find any information talking about a default time out.
The app is straightforward, just a web page to edit form data. Sometimes when the save button is clicked an exception is thrown saying something to the effect that "adminForm" is not valid model data. I'm sorry I have been unable to replicate the exception and had not saved it.
The code is below, thanks in advance for your comments.
#SessionAttributes("adminForm")
#Controller
public class Admin_FormController
{
final static protected long INDEX_RA = 1L;
#Autowired
private AdminDataRepository rep;
#RequestMapping(value="/admin", method=RequestMethod.GET)
public String adminForm(Model model)
{
AdminData ad = rep.findById(INDEX_RA);
// If there is no configuration record, create one and assign the primary key
if(ad == null)
{
ad = new AdminData();
ad.setId(INDEX_RA);
}
model.addAttribute("adminForm", ad);
return "adminForm";
}
#RequestMapping(value="/admin", method=RequestMethod.POST)
public #ResponseBody AdminData adminSubmit(#ModelAttribute("adminForm") AdminData ad, Model model)
{
rep.save(ad);
model.addAttribute("adminForm", ad);
return ad;
}
}
UPDATE:
Here is the exception that is thrown:
2015-07-28 11:12:16.564 ERROR 52963 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Expected session attribute 'adminForm'] with root cause
org.springframework.web.HttpSessionRequiredException: Expected session attribute 'adminForm'
at org.springframework.web.method.annotation.ModelFactory.initModel(ModelFactory.java:115)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:753)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)
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 was able to solve this problem by specifying that the session should never time out. This is fine in our case since this app is secured behind a single sign on appl. Here is what I added to the application.properties file:
server.session-timeout=-1