I am playing with the SimpleMappingExceptionResolver to see how it works and to see if it will be of use to us for a client but I am having problems understanding it.
What I have tried is visiting a particular page in my application and having it throw an exception in the handleRequestInternal method.
When I throw a RecoverableDataAccessException (subclass of DataAccessException) then the correct error page is displayed as expected.
When I throw a freemarker.core.InvalidReferenceException or java.lang.NumberFormatException then the exception bubbles through to the page and the default 500 error page (ie, no styling) is shown.
Below is the mapping I am using.
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.dao.DataAccessException">/general/error/500</prop>
<prop key="freemarker.core.InvalidReferenceException">/general/error/500</prop>
<prop key="NumberFormatException">/general/error/500</prop>
</props>
</property>
<property name="defaultErrorView" value="/general/error/500" />
</bean>
I at least expected the default error view to get hold of the exception and display my specific error page but that is not happening.
Am I using the SimpleMappingExceptionHandler correctly here?
[edit] I am using jetty.
[edit] I've realised that the SMER doesn't handle errors thrown during render which explains why it can't catch the ones I've specifically having trouble with. Can the SMER be made to cope with 500 style errors?
As you've discovered, SimpleMappingExceptionResolver will not work for exceptions thrown in the view layer. It implements the interface HandlerExceptionResolver which, as the name implies, only handles exceptions thrown by the handler (i.e. the controller).
If you need to handle exceptions thrown by the view, you can either write a HandlerInterceptor, overriding the afterCompletion() method, or write a non-Spring servlet Filter. In both cases, you won't get the benefit of Spring's view resolver, you'll have to handle rendering yourself.
One word of warning, though - when you get exceptions in the view layer, it's not always possible to handle them gracefully, since the server may have begun to flush the view output to the client when the exception is thrown, in which case the server cannot then render a separate error page. This is why it's good practice to do as much logic as you can in the controller layer, so that exceptions are caught as early as possible.
Related
I've inherited a bit of a monster system. It is a Spring framework server meant to run on Weblogic.
The code as it stands seems to work perfectly for another developer. I can clean, compile and package the project without error. However, when I try to deploy the generate .war file to my Weblogic server, I get the following error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.com.example.portal.uil.delegate.ExceptionLogDelegate': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
This error points me to the following bean, which is in an external library:
<bean id="com.externalLibrary.ExceptionLogDelegate" class="com.externalLibrary.ExceptionLogDelegate" scope="session">
<aop:scoped-proxy />
<property name="errorLogBuffer" ref="com.externalLibrary.ErrorLogDao" />
</bean>
After searching around for that error for a while, it seems that it is most often experienced when the aop:scope-proxy tag is omitted. This bean is being loaded as such:
<bean id="exceptionResolver" class="foo.mypackage.SoapFaultDetailExceptionResolver">
<property name="marshaller" ref="marshaller"/>
<property name="exceptionLogDelegate" ref="foo.mypackage.ExceptionLogDelegate"/>
</bean>
The strange thing is that with no files changed, this exact code works fine on my colleague's machine, so I assume I'm missing some magic configuration step.
Could anyone perhaps point me at thing to look for?
Kind Regards
I debug my app and the expression doesn't execute.
<bean id="remover" class="org.example.Remover"/>
<bean id="key" class="java.lang.String">
<constructor-arg value="KEY"/>
</bean>
<integration:service-activator input-channel="middleChannel"
expression="#remover.remove(key)"/>
No Exception. method doesn't call.
That’s not true: there must be an exception. You don’t show the whole flow to determine the part who swallows your exception on the matter.
Your expression is like:
#remover.remove(key)
You correctly call remover bean, but there is no such a property like key in the Message object - just only headers and payload. That’s why I’m making a conclusion that you have problems.
You can turn on debug logs for the Spring Integration category and follow you the trace of the call.
I am learning Spring MVC framework, and created a simple "Hello world" kind of web-application using Spring MVC framework.
My controller code is like this:
#Controller
public class SimpleController {
#RequestMapping("/welcome")
ModelAndView handleIncomingWelcomeReq() {
ModelAndView mw = new ModelAndView("WelcomePage","welcomeKey","WelcomeKey's value!");
return mw;
}
}
The spring configuration is:
<beans>
<context:component-scan base-package="com.example.controller, com.example.util"/>
<bean id="viewResolver1" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"> <value>/WEB-INF/</value> </property>
<property name="suffix"> <value>.jsp</value> </property>
</bean>
</beans>
The code is straightforward, for /welcome , handleIncomingWelcomeReq() gets invoked and welcomePage.jsp is returned to the client.
For this simple application, we need to specifically mention the view page which it returns. Now my question is:
In real enterprise web-applications, how do we organise the view / page which gets returned for matching url. Wouldn't the spring configuration get too big, because we have to specifically mention the page which gets returned for each incoming url.
Is this the way Spring MVC builds the real life enterprise web application. Each page specifically mentioned in the spring configuration page?
Any inputs on this which help clarify this really appreciated.
The responsibility of defining the page flow specifically lies on individual controllers and views; for instance, you usually map a web request to a controller, and the controller is the one that decides which logical view needs to be returned as a response. This is sufficient for straightforward page flows, but when your application gets more and more complex (real enterprise web-applications) in terms of user interface flows, maintainance becomes a nightmare. If you are going to develop such a complex flow-based application, then Spring Web Flow can be a good companion. Spring Web Flow allows you to define and execute user interface flows within your web application.
I am trying to show an custom error message on any occurrence of exception or error in my business layer. I am catching the exception in my controller and I would like to display it in my JSP.
This exception or error is not associated with any field in the screen, it's a pure server exception. I am also using an Annotated Controller. I am using Prototype for making AJAX requests to my controller.
In Spring you can register a HandlerExceptionResolver which will catch exceptions thrown by your Spring MVC controllers and forward them to the view layer for rendering. These are described in the Spring docs here. Start with the SimpleMappingExceptionResolver (see javadoc) which gives a simple mechanism for mapping exception types to views.
However, if the exception occurs outside if your Spring controller, for whatever reason, then you'll need a more generic fall-back solution, which involves configuring error pages in your web.xml file. This is not Spring-specific. See here for an example of how to do it.
From a jsp is thrown a NullPointerException for example using <% null.toString(); %>
This exception is not handled by the HandlerExceptionResolver, but thrown to the web container(tomcat) and converted into a code 500 error.
How can I configure spring to get that error in my HandlerExceptionResolver ?
Details:
Spring can be configured to handle exceptions thrown inside Controllers, but not exceptions thrown by view.
Of course i can resolve the NullPointerException, but i want to design a solution that will gracefully resolve any possible problem on the web application in order to display a user friendly message to the user.
See the HandlerInterceptor interface instead. You'll want the afterCompletion method. You can then intercept the response and then set the appropriate header information to redirect to a container-configured error web page. You're right that Spring doesn't have this functionality, this is going to have to be specified by the web.xml which determines which codes map to which pages.
I have not worked with this particular bit of the spring framework, but the docs say
"Interface to be implemented by objects than can resolve exceptions thrown during handler mapping or execution, in the typical case to error views. Implementors are typically registered as beans in the application context.
Error views are analogous to the error page JSPs, but can be used with any kind of exception including any checked exception, with potentially fine-granular mappings for specific handlers."
so I'd imagine that given that NullPointer extends RuntimeException the framework isn't designed to catch it. Is there a reason the exception(s) can't be handled in the controller directly?