Spring Integration: ClientHttpRequestInterceptor intercept() method not called when request is sent - spring

I have set up a spring-integration application as followed, and want to log the outbound request using ClientHttpRequestInterceptor.
The setup is below.
I sent the Http-get using curl and got result, but the method CustomClientHttpRequestInterceptor.intercept() never gets called when app is debugged.
I must have missed something in the setup. Thanks for helping.
Configuration:
<bean id="customRT" class="org.springframework.web.client.RestTemplate">
<property name="interceptors">
<list>
<bean class="hello.CustomClientHttpRequestInterceptor" />
</list>
</property>
</bean>
<int:chain...>
<int:header-enricher....
<int-http:outbound-gateway url="http://example.com/vhosts"
rest-template="customRT"
http-method="GET"/>
</int:chain>
public class CustomClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
logger.info("request.getURI().toString());
return execution.execute( request, body );
}

The configuration and code are correct. I've forgot that there is a cache installed, and that's why the intercept() method never gets called.

Related

With Spring MVC can you make one controller call another controller to handle an error page?

I have a controller which can throw an exception. When it does throw an exception it will show my errorpage.jsp, instead of the jsp page I wanted to show. An exxample of this controller is:
public class myController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, Object> model = new HashMap<>();
// Some logic which can throw an error....
return model;
}
}
The application-servlet.xml looks like this:
...
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/login.html">myController</prop>
<prop key="/errorpage.html">myErrorController</prop>
</props>
</property>
</bean>
...
Normally when an error, like navigating to a page that doesn't exist, occurs the error controller will be called which will return a hashmap of variables for the error page jsp. However, when the login controller encounters an error it will show the error page, but it won't call the error controller which would provide some of these parameters, so the page is incomplete.
Is there some way to define in the servlet.xml for the myController to call the myErrorController when it encounters an error and redirects to the error page?
You can annotate a controller class with #ControllerAdvice which will be shared between all Controllers. Then using the #ExceptionHandler annotation you can create methods to handle specific exceptions.
Example:
#ControllerAdvice
public class ExceptionHandlerAdvice {
#ExceptionHandler(MyException.class)
public ModelAndView handleException(MyException e, HttpServletRequest request, HttpServletResponse response) { // included servlet request and response
ModelAndView model = new ModelAndView("error/errorpage.jsp");
model.addObject("exception", e);
return model;
}
}
And anytime you throw MyException in any of your other controllers, this controller advice method will handle the exception for you! As the exception, servlet request and response is passed to the ExceptionHandler method, all of that information is available to you.
Example in another controller:
#Controller
public class SomeController {
#Autowired
private DataService dataService;
#RequestMapping(value = '/', method = RequestMethod.POST)
public String doSomething() {
return dataService.foobar(); // throws MyException which is handled with ExceptionHandler
}
}

Upgrading to spring-3.1 seems to break my CustomWebArgumentResolver

I'm trying to upgrade a spring MVC app from 3.0.6 to 3.1.2 and some controllers that used to work don't seem to work anymore. I've read the spring docs, but I'm confused about what's compatible with what.
We've got a CustomWebArgumentResolver that looks for any request parameter named "asOf" and coverts its value to a date. We call it, unimaginatively, the "AsOfDateConverter." When upgrading to spring-3.1.2, I took advantage of the new namespace functionality and added this to my applicationContext:
<mvc:annotation-driven conversion-service="conversionService">
<mvc:argument-resolvers>
<bean id="customWebArgumentResolver" class="my.converters.CustomWebArgumentResolver">
</bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
The CustomWebArgumentResolver is straightforward:
public class CustomWebArgumentResolver implements WebArgumentResolver {
private AsOfDateConverter asOfDateConverter;
#Override
public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception {
if (isAsOfDateParameter(methodParameter)) {
return asOfDateConverter.convert(webRequest.getParameter("asOf"));
}
return UNRESOLVED;
}
Then an example controller might look something like this:
#Controller
#Secured({BaseController.ROLE_LOGGED_IN})
#org.springframework.transaction.annotation.Transactional
public class DashboardController extends BaseController {
public static final String URL = "/dashboard";
#RequestMapping(value=URL, method=RequestMethod.GET)
public ModelAndView get(#RequestParam(required=false) String requestedMeterType, #AsOf Date asOf) {
debug(log, "Rendering dashboard asOf %s", asOf);
etc etc
The "asOf" parameter is coming in null, and I'm sure I'm missing something obvious. If anyone out there neck deep in the latest MVC 3.1 stuff could point me in the right direction I'd be grateful.
Thanks!
Tom
EDIT:
The AsOf annotation:
#Target(ElementType.PARAMETER)
#Retention(RetentionPolicy.RUNTIME)
public #interface AsOf {
}
More of my applicationContext:
<mvc:annotation-driven conversion-service="conversionService">
<mvc:argument-resolvers>
<bean class="[blah].AsOfDateHandlerMethodArgumentResolver">
<property name="asOfDateConverter">
<bean class="[blah].AsOfDateConverter"/>
</property>
</bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
<!-- Added to re-support #Controller annotation scanning after upgrading to spring-3.1. -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="[blah].converters.CustomerConverter"/>
<bean class="[blah].converters.AccountConverter"/>
<bean class="[blah].converters.DateConverter"/>
<bean class="[blah].converters.CustomerCommunicationInstanceConverter"/>
<bean class="[blah].converters.MeterTypeConverter"/>
<bean class="[blah].converters.AreaAmountConverter" p:precision="0"/>
<bean class="[blah].converters.LengthAmountConverter" p:precision="1"/>
</set>
</property>
</bean>
The API has changed with Spring 3.1 - the interface to implement to resolve a controller argument is HandlerMethodArgumentResolver. You can continue to use CustomWebArgumentResolver, by adapting it to a HandlerMethodArgumentResolver
However changing the code to use HandlerMethodArgumentResolver also will be easy:
public class CustomWebArgumentResolver implements HandlerMethodArgumentResolver {
private AsOfDateConverter asOfDateConverter;
#Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
if (isAsOfDateParameter(methodParameter)) {
return asOfDateConverter.convert(webRequest.getParameter("asOf"));
}
return UNRESOLVED;
}
#Override
public boolean supportsParameter(MethodParameter parameter) {
return (methodParameter.getParameterAnnotation(AsOf.class)!=null)
}
Edit
After looking through your comments, I think I have an idea about what could be going wrong. Can you please check your #AsOf annotation, you probably have not declared the retention of Runtime, which could be the reason why the the WebArgumentResolver is not taking effect:
#Retention(RetentionPolicy.RUNTIME)
public #interface AsOf {
}
Anyway here is a gist with a full working test along the same lines:
https://gist.github.com/3703430

Spring 3.0 MVC Handler Interceptors not working

I am trying out the HandlerInterceptors from Spring MVC 3.0.
Below is my interceptor
public class SessionInterceptor extends HandlerInterceptorAdapter {
#Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("inside preHandle");
if(request.getSession().getAttribute(SessionConsta nts.USER_SESSION_NAME) == null) {
response.sendRedirect("welcome");
return false;
}
return true;
}
}
Below is my configuration in my xml
<mvc:annotation-driven/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/services/*"/>
<bean class="com.ca.myca.interceptors.SessionInterceptor " />
</mvc:interceptor>
</mvc:interceptors>
But the interceptor is not getting called.
Please let me know if I am missing any thing.
In our application we are using double ** for any service sub-path match, so try changing it and check if it helps:
<mvc:mapping path="/services/**"/>
You are using <mvc:annotation-driven/> with mvc interceptor.
Please check on Spring reference:
http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/servlet/DispatcherServlet.html
"When running in a Java 5+ environment, a default AnnotationMethodHandlerAdapter will be registered as well. HandlerAdapter objects can be added as beans in the application context, overriding the default HandlerAdapters. Like HandlerMappings, HandlerAdapters can be given any bean name (they are tested by type)."
<mvc:annotation-driven/> is supposed to be used for annotation-driven MVC controllers like #RequestMapping, #Controller etc, but I have seen there is no need to define "<mvc:annotation-driven/>" for supporting it.
Unless you are using jackson (for json support), you can try to remove <mvc:annotation-driven/> and use "<context:annotation-config>" instead for common use like autowiring etc.
try what is suggested in Configuration of Spring MVC and JSON using Jackson.
Put you interceptor in <mvc:interceptors> tag
<mvc:interceptors>
<bean class="xx.x..x..x...UserSessionInterceptor" />
</mvc:interceptors>
you can keep <mvc:annotation-driven/> and <context:annotation-config>
In reference to the post above by arviarya, <mvc:annotation-driven /> in the config XML results in a different handler Object being passed to the interceptor. In our interceptor method we had:
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav) throws Exception {
if (mav != null && handler instanceof HandlerMethod) {
// something we want to have happen
}
This was being called with the #Controller-derived object without the <mvc:annotation-driven />, but was called with the HandlerMethod-derivedobject when it was present. For our if block to work, I needed the tag in our config XML.

Spring dependency injection to other instance

from the app-context.xml:
<bean id="userDao" class="com.vaannila.dao.UserDAOImpl">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<bean name="MyServiceT" class="com.s.server.ServiceT">
<property name="userDao" ref="userDao"/>
</bean>
and inside ServiceT.java:
private UserDAO userDao;
public void setUserDao(UserDAO userDao){
this.userDao = userDao;
}
the issue is: the setUserDao is called when the server goes on but when I call my doGet method:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
writer.write("hello");
}
the userDao is null.
I put a breakpoint inside the setUserDao method and than another one inside the doGet method and saw that it is not the same insatnce... what is the reason? how can I fix it?
thanks!
Spring is atowiring your bean correctly, the problem is that servlet container instantiates your servlet independently of spring. So you basically have two different instances - one created by spring and another created by container.
One workaround is to use ServletContextAttributeExporter, by putting the following in your app-context.xml:
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="userDao">
<ref bean="userDao"/>
</entry>
</map>
</property>
and then, in your servlet:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
UserDao userDao = (UserDao)getServletContext().getAttribute("userDao");
// do something with userDao
PrintWriter writer = response.getWriter();
writer.write("hello");
}
another is to access the WebApplicationContext directly:
protected void doGet(HttpServletRequest reqest, HttpServletResponse response)
throws ServletException, IOException {
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
UserDao userDao =(UserDao)springContext.getBean("userDao");
}
... or simply use Spring MVC and let it autowire everything like it should.
Also see this blog post. It might be easier to convert your servlet to HttpRequestHandler and let it be served by HttpRequestHandlerServlet, both provided by spring.

How to access Spring RequestContext from a Freemarker TemplateDirectiveModel

I'm using Spring MVC with Freemarker as view technologie. I have a TemplateDirectiveModel object which needs to access Spring's RequestContext within the execute method. Currently I do it like this:
public class MyDirective implements TemplateDirectiveModel
{
public void execute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body) throws TemplateException, IOException
{
StringModel model = (StringModel) env.getGlobalVariable("springMacroRequestContext");
RequestContext requestContext = (RequestContext) model.getWrappedObject();
}
}
But I can't believe that this is the right way to do it. I have the feeling I missed something important. Maybe there are special classes and annotations for handling Freemarker direcives in Spring? Maybe I can let Spring inject something into the directive class with which I can access Springs request scope?
You could subclass FreeMarkerConfigurer, overriding its postProcessConfiguration(Configuration config)method.
Your implementation would just put a request-aware dependency in the configuration, as a shared variable for example (as preconised by the FM documentation).
Should do the trick, Spring-style...
There is an easier way to do this. If you are already using spring's FreeMarkerConfigurer, you can hand it a map of variables:
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"
p:templateLoaderPath="/some_path_here">
<property name="freemarkerVariables">
<map>
<entry key='macroName' value-ref="templateModelRef" />
</map>
</property>
</bean>
<bean id="templateModelRef" class="...class..extends TemplateModel">
<property name="someResource" value-ref="resourceRef"/>
</bean>
Now at least in a class that extends TemplateDirectiveModel's execute method you have access to that injected property.
public class MyDirective extends TemplateDirectiveModel {
private MyResource someResource;
#Override
public void execute(Environment env, Map params, TemplateModel[] loopVars,TemplateDirectiveBody body) throws TemplateException, IOException {
StringModel sharedVariable = (StringModel)env.getConfiguration().getSharedVariable("beanName");
MyClass sweetness = (MyClass)sharedVariable.getWrappedObject();
}
}
Now in your .ftl you can use:
<#macroName />
and it will have spring dependencies auto injected.

Resources