Catch Spring MVC No Mapping Error - spring

I configured below exception resolver in my web configuration file but I am not sure why it cannot handle
errors such as this 'No Matching error found for servlet request: path '/etc'
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.Exception">
exception
</prop>
</props>
</property>
</bean>
My app relies on Ajax and there are cases that I change the target url based on some user interactions.
My question is, is it possible for me to catch the error in my Spring MVC and forward it to my exception.jsp so that my user wont get
a nasty 404.

SimpleMappingExceptionResolver (and the HandlerExceptionResolver framework in general) will only be invoked to handle exceptions generated by the request handler (i.e. your controllers). If no handler is configured to handle the request, then it won't get that far, and your resolver won't be invoked.
The simplest thing for you to do is to configure a 404-handling page in your web.xml, e.g.
<error-page>
<error-code>404</error-code>
<location>/error.html</location>
</error-page>

You could set up a catch-all #RequestMapping and throw a custom exception if it is executed. Then you could handle that exception with the SimpleMappingExceptionResolver or an #ExceptionHandler method (maybe in a #ControllerAdvice class).
The catch-all controller:
#RequestMapping(value = "/**")
public ModelAndView noHandlerMappingFound() throws HandlerNotFoundException {
throw new HandlerNotFoundException("No handler mapping found.");
}
Here HandlerNotFoundException is your custom exception type.
The controller advice:
#ExceptionHandler(NoSuchEntityException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
public ModelAndView handleNoSuchEntityException(final HttpServletRequest req, final Exception ex) {
return new ModelAndView("error-page");
}

Related

Set custom response in Spring interceptor

Here is my interceptor method where i want to set custom response to tell the UI what happened
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession(false);
if (session != null)
return true;
else{
response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT)
return false;
}
}
And in web.xml
<error-page>
<error-code>408</error-code>
<location>/error.html</location>
</error-page>
spring-servlet.xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/login" />
<bean class="com.example.CustomInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
When the session is timed out its not sending any response after return false.
Even the below is not working
response.sendRedirect("http://localhost:8080/home");
You can try very simple thing. Change your mvc:interceptros structure to
<mvc:interceptors>
<bean class="com.example.CustomInterceptor" />
</mvc:interceptors>
This essentially mean apply the interceptor to all applicable requests. I will come in a moment to why I say applicable in a moment. If above works then the issue is with your mapping.
Now as you know interceptors are configured at the level of HandlerMapping and it will be RequestMappingHandlerMapping (Spring 3.1+ with mvc:annotation-driven) or DefaultAnnotationHandlerMapping in your case.
Now as you have use <mvc:mapping path="/**" /> will map to all requests (including subpaths) as long as they are valid mappings. So lets say you have controller
#RequestMapping(value="/home", method = RequestMethod.GET)
public String welcome() {
return "welcome";
}
you cannot hit http://localhost:8080/yourProjectName/home/test and expect it to hit the interceptor. So you have to hit http://localhost:8080/yourProjectName/home as that is a valid HandlerMapping.
As to to response first debug if your interceptor is getting hit for any requests. If it does work then
response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT);
should redirect you to error.html as you have used
<error-page>
<error-code>408</error-code>
<location>/error.html</location>
</error-page>

Session destroy event with JTA Transaction

I am working on JBOSS application and I am facing issue for loggin sessionTimeout event
I want to make JTA transaction once the session is expire.
My code is as follow
spring.xml
...
<bean
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
id="transactionManager">
<property name="sessionFactory" >
<ref local="sessionFactory" />
</property>
</bean>
<bean id="msg" class="com.Message">
....
</bean>
...
web.xml
...
<listener>
<listener-class>
com.demo.MySessionListener
</listener-class>
</listener>
...
Class File
public class MySessionListener implements HttpSessionListener{
public void sessionCreated(HttpSessionEvent event) {
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(session.getServletContext());
Message msg = (Message)ctx.getBean("msg");
msg.save(); // throws error org.springframework.transaction.CannotCreateTransactionException
}
}
I found that All the JTA operation must be done in session, But in this case how can I achieve this ? Because I want to perform JTA transaction because of the session expiration event.
Let me know if anyone have solve this problem even before.
Thanks
StackTrace
at org.jboss.web.tomcat.service.session.ClusteredSession.removeAttributeInternal(ClusteredSession.java:1292)
at org.jboss.web.tomcat.service.session.ClusteredSession.expire(ClusteredSession.java:844)
at org.jboss.web.tomcat.service.session.ClusteredSession.expire(ClusteredSession.java:740)
at org.jboss.web.tomcat.service.session.ClusteredSession.isValid(ClusteredSession.java:720)
at org.jboss.web.tomcat.service.session.ClusteredSession.isValid(ClusteredSession.java:685)
at org.jboss.web.tomcat.service.session.JBossCacheManager.processExpires(JBossCacheManager.java:1236)
at org.jboss.web.tomcat.service.session.JBossManager.backgroundProcess(JBossManager.java:817)
at org.jboss.web.tomcat.service.session.JBossCacheManager.backgroundProcess(JBossCacheManager.java:1185)
at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1270)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1555)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1564)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1564)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1544)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'workContext': 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? If you are actually operating within a web request and still receive this message,your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.getTarget(Cglib2AopProxy.java:661)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:611)
at com.ideas.carparkpro.commons.bean.CproWorkContext$$EnhancerByCGLIB$$ef8de176.getDataSource()
at com.ideas.carparkpro.core.util.UserRoutingDataSource.determineCurrentLookupKey(UserRoutingDataSource.java:103)
... 30 more
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request? If you are actually operating within a web request and still receive this message,your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:102)
at org.springframework.web.context.request.SessionScope.get(SessionScope.java:88)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:285)
... 36 more

Handling error 500 by Interceptor in Spring MVC

I have created my Interceptor class and have overridden only the afterCompletion method.
When ever the system throws an error ( 500, 404 ), the system breaks and does not reach afterCompletion method of my interceptor. Is there any way so that the request can reach the afterCompletion method with the exception occured.
Interceptor class
public class ClassName extends HandlerInterceptorAdapter {
#Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex) throws Exception {
if (ex != null) {
//do somthing here
}
}
}
interceptor declaration
<mvc:interceptors>
<bean class="x.y.z.ClassName" />
</mvc:interceptors>
Can anyone guide me one this.
I am using SWF + MVC and realized different ways of registering interceptors ,
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="DataCollectorFlowRegistry" />
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor"/>
</list>
</property>
</bean>
This works for me.

The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler

I wanted to use both annotation mapping and xml mapping in Spring MVC. My application-context.xml as follows:
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="personal/account/history">accountHistoryController</prop>
</props>
</property>
</bean>
<bean id="accountHistoryController" class="com.fg.banking.ib.controller.AccountHistoryController" />
<bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<context:annotation-config />
<mvc:annotation-driven />
<context:component-scan base-package="com.fg.banking.ib.controller, com.fg.banking.ib.helper, com.fg.banking.corporate.controller" />
I am getting the following error when I try to access the url. I have configured the SimpleControllerHandlerAdapter as above.
javax.servlet.ServletException: No adapter for handler
[com.fg.banking.ib.controller.AccountHistoryController#218531e6]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:1128)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:903)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
What to do?
This error also occurs when you define a restController but forget to define the requestMapping.
#RestController
#RequestMapping("/api/orders") // <---- dont't forget the requestMapping
This problem occurred for me when I tried to define RestController path by using in this way:
#RestController("/test")
public class TestController {}
In the above section, the meaning of this declaration is different. Here actually "/test" is defined as bean name rather than path for the controller.
After defining the path in this way it worked for me:
#RestController
#RequestMapping("/test")
public class TestController {}
I resolved the issue. I forgot to add the #Controller annotation in controller class. There are fore we can use the both methods(annotation mapping & XML mapping) together in an application.
Try adding the following as a handler mapper(Worked for me):
<bean id="HandlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
Make sure you have implemented Controller in your controller classes and overrided handleRequest method.
Here our controller class should extends
import org.springframework.web.servlet.mvc.AbstractController;
public class AppController extends AbstractController{ }
Here we need to implement the abstract method as :
protected modelandview handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception { return null; }

Spring AOP and apache shiro configuration.Annotations not been scanned

I've been struggling with a configuration which requires a knowledge in AOP.
i must admit that AOP is that part i'm trying to get for a while without success.
It seems that my shiro annotations are not scanned and thus are ignored.
i've tried using shiro 1.1.0+ maven3+spring 3.0.5.RELEASE, hibernate 3.6.1.Final with ZK 5.0.6.
i got my hibernaterealm working , talking to database, i got the authentication working, i successfully(i believe) get the roles and permission loaded.
so to test the authorization side i have somewhere in my code this :
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isPermitted("businessaccount:list")) {
throw new AuthorizationException("User not authorized");
}
and it works fine.
So i know my permissions were loaded.i'll be convenient for me using annotations to i've put it in implementation class, because i didn't plan on using interface at first place with my controller classes which are extending ZK GenericForwardController.
i've seen this bug and i've decided to do a try with one interface with the #RequiresPersmissions on methods.
apparently it's still not working as in it's giving access to unauthorized subject.there is no error in my log.Maybe i'm doing something wrong here are snippet of the codes:
#Component("layouteventhandler")
public class LayoutEventHandlerImpl extends GenericForwardComposer implements LayoutEventHandler {
Logger logger = Logger.getLogger(LayoutEventHandlerImpl.class);
Menuitem logout;
//...
#Override
public void onClick$pAccounts() {
try {
execution.sendRedirect("/accounts/personal/list");
} catch (Exception ex) {
logger.info("Error redirecting to personal accounts", ex);
}
}
#Override
public void onClick$bAccounts() {
try {
execution.sendRedirect("/accounts/business/list");
} catch (Exception ex) {
logger.info("Error redirecting to business accounts", ex);
}
}
//.....
}
its interface it :
public interface LayoutEventHandler {
#RequiresPermissions(value="personalaccount:list")
public void onClick$pAccounts();
#RequiresPermissions(value="businessaccount:list")
public void onClick$bAccounts();
//.....
}
here is my shiro applicationcontext
<bean id="hibernateRealm" class="com.personal.project.admin.webapp.security.DatabaseRealm" />
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="hibernateRealm" />
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<!-- <property name="proxyTargetClass" value="true" />-->
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- Secure Spring remoting: Ensure any Spring Remoting method invocations can be associated
with a Subject for security checks. -->
<bean id="secureRemoteInvocationExecutor" class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- ... -->
is it in there something that i should do? thanks for reading and helping out
I don't know Shiro, but I'm guessing that you've put annotations on your bean classes which implement interfaces and then you're proxying them for security, transactions, and/or something else. When that happens, the object that's returned is a JDK dynamic proxy, which isn't an instance of your bean's concrete class, only of the interface it implements. Therefore any annotation scanning that depends on annotations in the concrete class won't find them.
To expand on Ryan Stewart's answer, you need to add
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
to the implementing class (not the interface) and move the Shiro annotations to it.
I encountered a similar problem when I was running two spring contexts. There is a parent root context that defined Database, Service, Security and non-SpringMVC web beans and a child web context for a Spring MVC REST api which contained the Controllers I want to proxy. The Configuration for each context was class path scanning separate packages.
In this case make sure that the DefaultAdvisorAutoProxyCreator and the AuthorizationAttributeSourceAdvisor beans that are requied are defined in the child web context (i.e. where the Rest Controllers are class path scanned) as defining them in the parent context does not work (the documentation on the DefaultAdvisorAutoProxyCreate is quite clear about this in hindsight!).
Posting this in case someone else encounters the same issue.

Resources