SpringMVC Invoking a global method - spring

I am a beginner in springMVC so take it easy on me guys...i am trying to invoke a method every time a user enters my web application regardless of the page/place.
I tried ContextRefreshedEvent but it only works when the application starts.
Is there any way to achieve this ?

Example would be
public class MyInterceptoor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
}
}
It is required to wire interceptor in your config.
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/myproject/**"/>
<bean class="com.mvc.myproject.MyInterceptoor" />
</mvc:interceptor>
</mvc:interceptors>
Spring Documentation HandlerInterceptorAdapter

You can use Spring Interceptor – HandlerInterceptor.
http://www.journaldev.com/2676/spring-mvc-interceptor-example-handlerinterceptor-handlerinterceptoradapter

For SpringBoot you can do this. Make a HandlerInterceptorAdaptor
#Component
public class AccessInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("preHandled for controller = " + handler);
return true;
}
}
Add it to a Spring WebMvcConfiguration class:
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Autowired
AccessInterceptor accessInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(accessInterceptor).addPathPatterns("/**");
}
}
Enjoy ...

Related

How to not use aspect in spring to write the request param and response param to the console

I found the class InvocableHandlerMethod.invokeForRequest will get the request param from request and invoke the controller class to get the return value.
What should I modify the method to write the params to the console?
I want to extends ServletInvocableHandlerMethod and override the method invokeForRequest but I can't call getMethodArgumentValues because it is private.should I copy the class of ServletInvocableHandlerMethod and InvocableHandlerMethod to modify the private method? Or is there have another way to log the request and response params without aspect?
Just create interceptor
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class LoggingInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// log here
return true; // let go further
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// log here
}
}
and register it
// example for Spring MVC annotation-based configuration
public class YourWebConfig extends WebMvcConfigurer {
...
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor());
}
...
}

Pre-conditions within #RequestMapping method?

I don't know how to redirect user if they do not meet certain preconditions for a #RequestMapping.
I have a simple form that after completion sends the user to "/secondForm" which is unrelated to "/firstForm", how can I restrict access to "/secondForm", if first form has not been completed?
What makes this more difficult for me there is a controller in the middle.
firstForm --- (submit)---> emailController ----(redirect)----> secondForm
If you want to redirect a user to another page when certain conditions are met, you can use an interceptor. Example interceptor class:
#Component
public class RedirectInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) {
if (request.getRequestURI().contains("secondForm") && modelAndView.getModel().get("someBoolean") == false {
try {
response.sendRedirect("/firstForm");
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
}
}
And register it in configuration class:
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Autowired
RedirectInterceptor redirectInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(redirectInterceptor);
}
}
If you prefer xml configuration over java then you can alternatively use this in your spring config xml:
<mvc:interceptors>
<bean id="redirectInterceptor" class="path.to.your.interceptor.RedirectInterceptor"/>
</mvc:interceptors>
Found an additional way:
Using FlashAttribute, by assigning before the redirect in emailController that sets a value.
In applicationController, by using an if statement if there isn't a FlashAttribute then redirect is called to the root of the application.

Spring Boot Value annotation inside HandlerInterceptorAdaper

I have a HandlerInterceptorAdapter like
#Component
public class TestInterceptor extends HandlerInterceptorAdapter{
#Value("${thing:defaultValue}")
private String thing;
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// Do something with thing, but thing is null.
}
}
Is it not possible to get config values injected into this class? What's going on here? I would have expected it to at least have the default value but it has nothing.
You need to make sure that Spring is actually instantiating the Component :)
So, like
#Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
#Autowired
TestInterceptor test;
#Override
public void addInterceptors(InterceptorRegistry registry){
InterceptorRegistration testreg = registry.addInterceptor(test);
// ...
}
}
By Autowiring it in to the Configurer, it makes Spring aware of it.

Spring requests preprocessing per session

I'd like create Spring request Interceptor which will be able to get some data from session and change some #Autowired components before request.
I can create Interceptor and register it, but it can't get access to session beans:
#Component
#Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class TokenInterceptor extends HandlerInterceptorAdapter {
#Autowired
private MyServicePerSession myServicePerSession;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(myServicePerSession.getName()); // NullPointerException!!!
return true;
}
}
Above in the method preHandle(...) per each request I get NullPointerException.
Here is my config:
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
//...
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TokenInterceptor());
}
}
How I said everything work fine except injecting MyServicePerSession.
I will really appreciate if you can give me advice about it, or some other ways to solve that problem.
You are trying to set a new object but you have to set a spring bean.
new TokenInterceptor() // is not spring bean
#Autowired private TokenInterceptor tokenInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor);
// You have to set bean here
}
If this doesn't work, you can check this http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch04s02.html

Is it possible to wire a Spring MVC Interceptor using annotations?

Is it possible to wire a Spring MVC Interceptor using annotations and if so could someone provide me with an example of how to do so?
By wire via annotation I am referring to doing as little in the XML configuration as possible. For example in this configuration file I found at http://www.vaannila.com/spring/spring-interceptors.html;
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:interceptors-ref="loggerInterceptor" />
<bean id="loggerInterceptor" class="com.vaannila.interceptor.LoggerInterceptor" />
How little configuration could you get away with there? I imagine an #Autowired would remove the need to explicitly declare the bean in line 2, but would it be possible to get rid of line 1 with an annotation as well?
Stumbled upon this question while searching exactly this. Finally I found out that it works in Spring 3.1 using #EnableWebMVC in conjunction with WebMvcConfigurerAdapter.
Simple Example:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="webapp.base.package")
public class WebApplicationConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggerInterceptor());
}
}
As far as I know, there are no ways to configure Spring MVC interceptors without XML at all.
However, there are some simplifications with mvc namespace in the latest versions of Spring 3.0.x (not Spring 3.0.0!):
<mvc:interceptors>
<bean class="com.vaannila.interceptor.LoggerInterceptor" />
</mvc:interceptors>
See also:
MVC Simplifications in Spring 3.0
I implemented a working solution using a custom #Interceptor annotation in the spirit of Spring's #Controller annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE})
#Documented
#Component
public #interface Interceptor {
String[] pathPatterns() default {};
String[] excludePathPatterns() default {};
}
This annotation should be applied to HandlerInterceptor types like so:
#Interceptor
public class BuildTimestampInterceptor extends HandlerInterceptorAdapter {
private final String buildTimestamp;
public BuildTimestampInterceptor(#Value("${build.timestamp}") String buildTimestamp) {
this.buildTimestamp = buildTimestamp;
}
#Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
req.setAttribute("buildTimestamp", buildTimestamp);
return true;
}
}
Finally, the processor class, InterceptorProcessor, is a Spring bean that extends WebMvcConfigurerAdapter and implements BeanPostProcessor in order to scan for the custom #Interceptor annotations and register beans having that anntation as HandlerInterceptors inside the overridden addInterceptors method:
#Component
public class InterceptorProcessor extends WebMvcConfigurerAdapter implements BeanPostProcessor {
private final Map<HandlerInterceptor,Interceptor> interceptors = new HashMap<>();
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
scanForInterceptorAnnotation(bean, beanName);
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String string) throws BeansException {
return bean;
}
protected void scanForInterceptorAnnotation(Object bean, String beanName) {
Optional<Interceptor> optionalInterceptor = getInterceptorAnnotation(bean.getClass());
if (optionalInterceptor.isPresent() && bean instanceof HandlerInterceptor) {
interceptors.put((HandlerInterceptor) bean, optionalInterceptor.get());
}
}
private Optional<Interceptor> getInterceptorAnnotation(Class cls) {
Annotation[] annotations = cls.getAnnotationsByType(Interceptor.class);
if (hasValue(annotations)) {
return Optional.of((Interceptor) annotations[0]);
}
return Optional.empty();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
interceptors.forEach((HandlerInterceptor key, Interceptor val) -> {
InterceptorRegistration registration = registry.addInterceptor(key);
if (hasValue(val.pathPatterns())) {
registration.addPathPatterns(val.pathPatterns());
}
if (hasValue(val.excludePathPatterns())) {
registration.excludePathPatterns(val.excludePathPatterns());
}
});
}
private static <T> boolean hasValue(T[] array) {
return array != null && array.length > 0;
}
}
Just remember to have your spring application scan for this processor bean in order to have it actually register your #Interceptors. Something like:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"org.my.controller", "org.my.utils.processor"})
public class WebConfig extends WebMvcConfigurerAdapter {...
I dont know about spring-AOP but if you're using AspectJ via Spring you can use #Aspect, #Pointcut, #Advise and more...
there's also a nice article on howto use these annotation with Spring AOP here:
http://java-x.blogspot.com/2009/07/spring-aop-with-aspecj-annotations.html
like Markus Kreusch'answers,It also could work like this
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="webapp.base.package")
public class WebApplicationConfig extends WebMvcConfigurerAdapter {
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping RequestMappingHandlerMapping= super.requestMappingHandlerMapping();
Object[] interceptors = new Object[1];
interceptors[0] = new RoleInterceptor();
RequestMappingHandlerMapping.setInterceptors(interceptors);
return RequestMappingHandlerMapping;
}
}

Resources