I am trying to implement HandlerInterceptorAdapter to be able to capture the request/response as a pre/post processor. For some reason the call doesn't go through my interceptor. There are multiple examples out but I couldn't find the issue in my case. Right now I want to capture the request before it goes to actual service and log some data.
NOTE: I don't have any view to render.
Interceptor class:
public class ESignLoggingInterceptor extends HandlerInterceptorAdapter {
private static final String CLASS_NAME = ESignLoggingInterceptor.class.getSimpleName();
#SuppressWarnings("unused")
#Override
public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler ) throws Exception {
String url = null;
if( request != null ) {
url = request.getRequestURL().toString();
}
return true;
}
}
spring.xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/rest"/>
<bean class="com.mercuryinsurance.esignature.common.logging.ESignLoggingInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/soap"/>
<bean class="com.mercuryinsurance.esignature.common.logging.ESignLoggingInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
I know 2 approaches for solving this problem, that I also faced.
The first is like you are trying. Please check:
Change
<mvc:mapping path="/soap"/> to <mvc:mapping path="/soap/**"/>
<mvc:mapping path="/rest"/> to <mvc:mapping path="/rest/**"/>
Also check if you have al schemas declared. If you actually don't have it declared you should be receiving error.
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd"
The second
Declare your interceptor as below
#Bean
public MappedInterceptor myInterceptor() {
return new MappedInterceptor(null, new MyLoggingInterceptor());
}
EDIT: Add #Component to your class
Related
I use Spring i18n library.
- ReloadableResourceBundleMessageSource
- SessionLocaleResolver
- LocaleChangeInterceptor
There are no errors.
If I use a strong refresh function in chrome, all interceptor methods are executed twice more.
And The Issue only occurs when the pages is used messages.properties.
preHandle ==> Controller ==> postHandle ==> AfterCompletion is executed, and all methods are executed twice more.
I've looked at the lifecycle of the interceptor, but I don't understand why the interceptor runs twice more without reason.
1. servlet-context.xml
<beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basenames" value="/WEB-INF/messages/messages, /WEB-INF/messages/messages_ko_KR" />
</beans:bean>
<beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<beans:property name="defaultLocale" value="ko_KR" />
</beans:bean>
<interceptors>
<beans:bean id="localeChangeInterceptor" class="com.test.util.locale.LocaleChangeInterceptor" />
</interceptors>
2. LocaleChangeInterceptor is implemented by me and is implemented as simple as the code below.
public class LocaleChangeInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String language = request.getParameter("language");
System.out.println("1. preHandle(): " + language);
if(language != null) {
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
localeResolver.setLocale(request, response, StringUtils.parseLocaleString(language));
}
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("2. postHandle()");
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("3. afterCompletion()");
}
}
Console
1. preHandle(): null
main.jsp
2. postHandle()
3. afterCompletion()
1. preHandle(): null
2. postHandle()
3. afterCompletion()
1. preHandle(): null
2. postHandle()
3. afterCompletion()
I don't know whether it is a problem or a natural result of Interceptor's lifecycle.
Resolved.
It was resolved by first creating an Interceptor bean,
then by calling the registered bean by reference from the .
It seems to be an issue because I didn't know well about Spring interceptor registration. I need to find out more.
<beans:bean id="localeChangeInterceptor" class="com.test.util.locale.LocaleChangeInterceptor" />
<interceptors>
<interceptor>
<mapping path="/**" />
<exclude-mapping path="/resources/**" />
<beans:ref bean="localeChangeInterceptor" />
</interceptor>
</interceptors>
I want to apply advice to a method helloWorld. I would like to throttle calls exceeding 'x' TPS and retry those calls.
So I have 2 interceptors -
Throttle Interceptor, which throttles call rate exceeds 'x'
Retry Interceptor, which retries if call is throttled.
The issue is that when I combine the 2 Interceptors the Throttling
interceptor does not seem work even if I provide the Rate as 0, that is the helloWorld methos gets executed.
If I only
use the Throttling Interceptor it works fine.
My Spring Configuration is like this.
<bean id="retryPolicy" class="xyz.RetryPolicyFactoryBean">
<property name="backoffCoefficient"><value>2</value></property>
<property name="multiplierMillis"><value>100</value></property>
<property name="maxDelayMillis"><value>2000</value></property>
<property name="maxAttempts"><value>2</value></property>
<property name="expirationDurationMillis"><value>60000</value></property>
<bean id="retryInterceptor" class="xyz.RetryInterceptor">
<constructor-arg index="0"><ref bean="retryPolicy"/></constructor-arg>
</bean>
<bean id="throttlingInterceptor" class="xyz.ThrottlingInterceptor">
<constructor-arg index="0"><value>key</value></constructor-arg>
</bean>
<bean id="helloWorld" class="xyz.helloWorld" />
<bean id="helloWorldProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="helloWorld" />
<property name="interceptorNames">
<list>
<value>retryInterceptor</value>
<value>throttlingInterceptor</value>
</list>
</property>
</bean>
Throttling Interceptor is like this:
#Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
if (isDecorated(methodInvocation)) {
if (throttler.isThrottled(key)) {
throw new ThrottlingException("Call throttled.");
}
}
return methodInvocation.proceed();
}
My retry interceptor is like this:
public class RetryInterceptor extends RetryAdvice {
public RetryInterceptor(RetryPolicy retryPolicy) {
super(retryPolicy);
}
#Override
public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
return super.invoke(methodInvocation);
}
What am I missing here?
I followed the newer approach using AspectJ Annotations & got it working (atleast now the interceptors are being called).
Annotate the Class which contains the advice with #Aspect
Here is my Throttle Advice:
#Before(pointcut="execution(* com.company.xyz.method())")
public void invoke() throws ThrottlingException {
if (throttler.isThrottled(throttleKey)) {
throw new ThrottlingException("Call Throttled");
}
}
My retry Interceptor:
#AfterThrowing(pointcut="execution(* com.company.xyz.method())", throwing="exception")
public Object invoke(JoinPoint jp, ThrottlingException exception) throws Throwable {
return RetryingCallable.newRetryingCallable(new Callable<Object>() {
#Override
public Object call() throws Exception {
MethodSignature signature = (MethodSignature) p.getSignature();
Method method = signature.getMethod();
return method.invoke(jp.getThis(), (Object[]) null);
}
}, retryPolicy).call();
}
Relevant Spring Config
<bean id="retryInterceptor" class="com.company.xyz.RetryInterceptor">
<constructor-arg index="0"><ref bean="retryPolicy"/></constructor-arg>
</bean>
<bean id="throttlingInterceptor" class="com.company.xyz.ThrottlingInterceptor">
<constructor-arg><value>throttleKey</value></constructor-arg>
</bean>
<aop:aspectj-autoproxy/>
Another point to take care of is the Order in which the Interceptors are called. Use #Order Annotation to ensure the order.
I have a spring application. I introduced a sessionInterceptor to prevent direct access to index.jsp. If the user is not logged in it shouldn't be able to access index.jsp and should be redirected to login.html. The code is hitting the preHandle() method and running all the code but after return false it's not redirecting to login.html. What's wrong? Any gurus out there for help? Thanks in advance.
My preHandle() in SessionInterceptor.java is:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
// if displaying the home page, make sure the user is reloaded.
if (request.getRequestURI().endsWith("login.html")) {
session.removeAttribute("isUserLoggedIn");
}
if (session.getAttribute("isUserLoggedIn") == null && !request.getRequestURI().endsWith("login")) {
response.sendRedirect(request.getContextPath() + "/login.html");
return false;
}
return true;
}
I have tried the following as well but all in vain.
RequestDispatcher dispatcher = request.getServletContext().getRequestDispatcher("/login.html");
dispatcher.forward(request, response);
My dispatcher-servlet.xml settings are:
<bean id="sessionInterceptor" class="com.xxx.xxx.xxx.SessionInterceptor" />
<bean id="annotationMapper" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="sessionInterceptor" />
</list>
</property>
</bean>
<!-- Configures Handler Interceptors -->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.xxx.xxx.xxx.SessionInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
The web.xml is:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
you can try redirecting to a logical path that will be catched from a controller
Try
response.sendRedirect("/NotLogged");
And then create a function like this:
#RequestMapping(value = {"/NotLogged"}, method = RequestMethod.GET)
public String notLogged() {
return "login.html";
}
I hope it will work for you!
When i use return false, i take "Error: Exceeded maxRedirects. Probably stuck in a redirect loop http://localhost:8080/api/login"
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(true){
response.sendRedirect("/api/login");
return false;
}
return true;
}
In the springmvc, when i send this url to spring interceptor, it does not work.
http://localhost/RRAdmin/cgr/cagri.jpg
But when use this url, interceptor works.
http://localhost/RRAdmin/cgr&cagri.jpg
You will see interceptor mapping below
<mvc:interceptor>
<mvc:mapping path="/**.jpg" />
<mvc:mapping path="/**.png" />
<bean class="com.RRAdmin.interceptor.ImageInterceptor" />
</mvc:interceptor>
And you'll see my prehandle method below
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI();
File image = new File(uri);
if(image.exists()) sendFile(image, response.getOutputStream());
return false;
}
Thank you.
I think that you have to add a new mapping path like this:
<mvc:mapping path="/**/*.jpg" />
<mvc:mapping path="/**/**.png" />
Hope it helps.
My system is Spring MVC based and I checked that Spring automatically sets PRAGMA: no-cache. The system is available to the users through SSL. When the users try to download something using the INTERNET EXPLORER 7 or 8 an error like "Internet Explorer cannot download file from server" appears (more details: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q316431&).
I tried to configure the WebContentInterceptor like the code bellow but does not work:
<mvc:interceptors>
<bean id="webContentInterceptor" class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="2100" />
<property name="useExpiresHeader" value="false" />
<property name="useCacheControlHeader" value="false" />
<property name="useCacheControlNoStore" value="false" />
</bean>
</mvc:interceptors>
What can I do avoid Spring send the Pragma: no-cache and related to Cache Control?
Regards!
You can write your own custom interceptor and set the header values to the response object. Interceptors are nothing but filters so override the filter and use the
prehandle and posthandle to set the request and response headers respectively.
Let me know if you want specific examples doing that.
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<beans:bean id="customInterceptor"
class="org.example.interceptors.CustomInterceptor">
</beans:bean>
</mvc:interceptor>
</mvc:interceptors>
public class CustomInterceptor implements HandlerInterceptor{
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView modelAndView) throws Exception {
response.setHeader(...);}
}
The simplest approach is probably just to stop the header from being written with a servlet filter. This way no Spring configuration has to be modified and you pick up the correct cache functionality for free.
public class PragmaFilter implements Filter {
private static String PRAGMA_HEADER = "Pragma";
#Override
public void init(FilterConfig filterConfig) throws ServletException { }
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, new NoPragmaHttpServletResponseWrapper(response));
}
#Override
public void destroy() { }
private final class NoPragmaHttpServletResponseWrapper extends HttpServletResponseWrapper {
private NoPragmaHttpServletResponseWrapper(ServletResponse response) {
super((HttpServletResponse) response);
}
#Override
public void addHeader(String name, String value) {
if (PRAGMA_HEADER.equals(name)) {
return;
}
super.addHeader(name, value);
}
#Override
public void setHeader(String name, String value) {
if (PRAGMA_HEADER.equals(name)) {
return;
}
super.setHeader(name, value);
}
}
}
Try to set cache seconds to an negative value.
If this does not help you will need to override:
protected final void preventCaching(HttpServletResponse response)
or
protected final void applyCacheSeconds(HttpServletResponse response, int seconds, boolean mustRevalidate)
Both methods are implements in WebContentGenerator
<mvc:interceptors>
<bean id="webContentInterceptor" class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="2100" />
<property name="useExpiresHeader" value="false" />
<property name="useCacheControlHeader" value="false" />
<property name="useCacheControlNoStore" value="false" />
<property name="cacheMappings">
<props>
<prop key="/**/**">-1</prop><!-- removes pragma no-cache -->
</props>
</property>
</bean>
</mvc:interceptors>