Spring : Command object not getting populated - spring

I have two controllers , a simple form controller and a multiaction controller.
Now, in simpleformcontroller, i want to redirect a request to multiaction controller.
Here's code snippet in simpleformcontroller
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) {
MyObject myOb = (MyObject )command;
system.out.println(myOb.toString);
ModelAndView mav = new ModelAndView(new RedirectView("another.htm"));
mav.addObject("Obj",myOb);
return mav;
}
another.htm binds to a method in multiaction controller.
<bean id="MyController" class="MyController">
<property name="methodNameResolver">
<bean class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/another.htm">another</prop>
</props>
</property>
</bean>
</bean>
and the code in multiactioncontroller is
public class MyController extends MultiActionController {
public ModelAndView another(HttpServletRequest request,
HttpServletResponse response, MyObject myObj) {
system.out.println(myObj.toString());
}
}
The output is, all fields of Myobj are nulls in mutiactioncontroller whereas they have valid values when passed in simpleformcontroller.
Am i missing something here or is this not the right way to pass command objects ?
Any help is appreciated.

Unless you store your MyObject in The session, you will always get null. It occurs because The user data does not survive redirect. To store your command object in The session, use setSessionForm in The SimpleFormController and Then retrieve your command by using
public ModelAndView another(HttpServletRequest request, HttpServletResponse response, HttpSession session, MyObject myObj) throws CRPMException {
instead

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
}
}

Access session scoped variable in spring interceptor

How can i access session scoped variable in spring interceptor?
Session scoped class:
#Component
#Scope("session")
public class User {
}
Controller:
#Controller
#RequestMapping("/restricted")
#Scope("request")
public class RestrictedController {
#Autowired
private User user;
}
Dispatcher servlet:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/restricted/*"/>
<bean class="com.interceptors.RestrictedInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
Interceptor class:
public class RestrictedInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
}
}
In prehandle i want to check if user is logged in (some other checks as well), how can i access session scoped user variable here? Autowiring user in Interceptor class throws exception.
You should be able to access your session-scoped user using the following code:
request.getSession().getAttribute("scopedTarget.user");
See related post here and org.springframework.aop.scope.ScopedProxyUtils class.

Spring 2.5 Ajax 1.7, updater receive wrong response

I am using Spring 2.5, and use Ajax.updater (1.7) to get an response from an requestmapping in Spring.
In the request mapping I am returning an ModelAndView which refers to an jsp with some text. But the problem is that when ajax received the response and update the container, the entire page is wrapped in the container instead just the jsp output, why is this
Ok, this is how I used ajax with Spring 2.5
First of all you need controller to respond on ajax calls
public class AjaxController extends MultiActionController {
// injected services, daos here
public ModelAndView getAjaxData(HttpServletRequest request, HttpServletResponse response) throws Exception {
String data = // construct your ajax response here - string, json, xml etc
model.put("data", data);
return new ModelAndView("ajax_foo", model);
}
public ModelAndView anotherMethod(HttpServletRequest request, HttpServletResponse response) throws Exception {
String data = // construct your ajax response here - string, json, xml etc
model.put("data", data);
return new ModelAndView("ajax_foo", model);
}
}
Then you need ajaxView to write ajax data to response
public class AjaxView extends AbstractView {
#Override
protected void renderMergedOutputModel(Map map, HttpServletRequest request, HttpServletResponse response) throws Exception {
String ajaxResponse = map.get("data");
response.setContentType("text/plain; charset=UTF-8");
response.getOutputStream().write(ajaxResponse.getBytes());
}
View resolver to resolve ajax calls
public class AjaxViewResolver extends AbstractCachingViewResolver {
private String ajaxPrefix;
private View ajaxView;
#Override
protected View loadView(String viewName, Locale locale) throws Exception {
View view = null;
if (viewName.startsWith(this.ajaxPrefix)) {
view = ajaxView;
} else {
}
return view;
}
public void setAjaxPrefix(String ajaxPrefix) {
this.ajaxPrefix = ajaxPrefix;
}
public void setAjaxView(View ajaxView) {
this.ajaxView = ajaxView;
}
}
Url mapping, map ajax url to ajax controller
<bean id="simpleUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/getAjaxData.htm">ajaxController</prop>
<prop key="/anotherMethod.htm">ajaxController</prop>
</props>
</property>
</bean>
Controller has bean ajaxResolver as methodNameResolver, controller has some services or daos for example
<bean name="ajaxController" class="my.test.web.ajax.AjaxController">
<property name="service" ref="service"/>
<property name="dao" ref="dao"/>
<property name="methodNameResolver" ref="ajaxResolver"/>
</bean>
Method name resolver
<bean id="ajaxResolver"
class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/getAjaxData.htm">getAjaxData</prop>
<prop key="/anotherMethod.htm">anotherMethod</prop>
</props>
</property>
</bean>
Ajax View resolver to call your ajax view when you return modelAndView from AjaxController
<bean id="ajaxViewResolver" class="my.test.web.ajax.AjaxViewResolver">
<property name="ajaxView">
<bean class="my.test.web.ajax.AjaxView"/>
</property>
<property name="ajaxPrefix" value="ajax_"/>
</bean>

How can I log the JSON response of Spring 3 controllers with #ResponseBody in a HandlerInterceptorAdapter?

I have controllers that return JSON to the client. The controllers methods are marked using mvc annotation such as:
#RequestMapping("/delete.me")
public #ResponseBody Map<String, Object> delete(HttpServletRequest request, #RequestParam("ids[]") Integer[] ids) {
Spring knows to return JSON since Jackson is on the class path and the client is requesting a JSON response. I would like to log the response of these requests and all other controllers. In the past I have used an interceptor to do this. However, I got the response body from the ModelAndView. How can I get the response body in the inteceptor now that I'm using #ResponseBody? Specifically, how can I get the response body in this method?
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
You can log everything by using CustomizableTraceInterceptor
you can either set it in your application context xml config and use AOP: (log level Trace)
<bean id="customizableTraceInterceptor"
class="org.springframework.aop.interceptor.CustomizableTraceInterceptor">
<property name="exitMessage" value="Leaving $[methodName](): $[returnValue]" />
</bean>
or you can completly customize it by implementing it in Java and use the method setExitMessage():
public class TraceInterceptor extends CustomizableTraceInterceptor {
private Logger log = LoggerFactory.getLogger("blabla");
#Override
protected void writeToLog(Log logger, String message, Throwable ex) {
//Write debug info when exception is thrown
if (ex != null) {
log.debug(message, ex);
}
....
}
#Override
protected boolean isInterceptorEnabled(MethodInvocation invocation, Log logger) {
return true;
}
#Override
public void setExitMessage(String exitMessage) {
.... //Use PlaceHolders
}
}
and use the placeholders such as '$[returnValue]'. You can find the complete list in the spring api documentation.
EDIT: Also, if you want to get the value of your #ResponseBody in another interceptor, I think it's not possible until version > 3.1.1. Check this issue: https://jira.springsource.org/browse/SPR-9226

Spring MVC 3.1 without annotations?

I'm starting a new project with Spring 3.1, and have been eyeball deep in all the documentation and forum opinions about how to use the #Controller annotation.
I personally dislike using annotations for MVC; I much prefer having all the URLs of a webapp available in one place, using SimpleUrlHandlerMapping.
Also, from much previous work using Spring 2.x, I'm very used to the BaseCommandController heirarchy.
I've always loved Spring because it's empowering without being restricting. Now I find Spring MVC is forcing me to put URLs into the java source, meaning (a) I can't map a controller to several URLs, and (b) to discover what URLs are in use in a webapp, I have to scan through different java source files, which I find impractical.
What is the recommended way of combining #Controller with SimpleUrlHandlerMapping, please ?
Update:
Hi Dave, are you saying you can map multiple URLs like this (altered from petclini.web.ClinicController)?
#RequestMapping({"/vets", "/another"})
public ModelMap vetsHandler() {
If this works then good.
My question still stands though:
If I don't want URLs in my java source, how best to map them with #Controller classes?
Regards,
Here is a simple set up to support annotation and non-annotated controllers.
Dispatcher servlet configuration xml
<mvc:annotation-driven/>
<bean id="testController" class="com.test.web.TestController"/>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/test=testController
</value>
</property>
<property name="order" value="0"/>
</bean>
A simple URL mapped controller
public class TestController implements Controller {
#Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
PrintWriter responseWriter = response.getWriter();
responseWriter.write("test");
responseWriter.flush();
responseWriter.close();
return null;
}
}
The controller for mvc annotation-config
#Controller
#RequestMapping("/home")
public class HomeController {
#RequestMapping(method = RequestMethod.GET)
#ResponseBody
public String dashboard(Model model, HttpServletRequest request) {
return "home";
}
}
If you want to use your own handlers for #Controller annotation. you can probably look into ClassPathBeanDefinitionScanner and DefaultAnnotationHandlerMapping.determineUrlsForHandlerMethods.

Resources