Generic OGNL Controller without Spring WebFlow
Feb 6th, 2007 by robert
While working on various web projects many times I felt guilty for writing controllers that perform one-two rows of the code.
It must be easier way! And when I read and tried Spring WebFlow I really liked their approach for defining how to call methods on any exposed bean.
It is what I was looking for. Simple things made easy inside the xml config:
-
<bean-action bean="cartController" method="changeQuantities">
-
<method-arguments><argument expression="flowScope.viewCommand"/></method-arguments>
-
<method-result name="viewCommand" scope="flow"/>
-
</bean-action>
However Spring WebFlow has many aspects that would stop you from using it for entire site. Click-around navigation and SWF do not play well together.
So what I need is ability to define OGNL expression in Spring coonfig without using SWF. What looked scarry on first sight turned to be extremely easy task.
I did some prototyping of idea and here is what I got in spring config file:
-
<bean id="profileView" class="com.cochlear.mcc.web.GenericFormController">
-
<property name="formView" value="profileView"/>
-
<property name="manager"><ref bean="profileManager"/></property>
-
<property name="viewScript"><value>manager.getProfile()</value></property>
-
</bean>
-
-
<bean id="profileForm" class="com.cochlear.mcc.web.GenericFormController">
-
<property name="formView" value="profileForm"/>
-
<property name="manager"><ref bean="profileManager"/></property>
-
<property name="modelClass"><value>com.cochlear.mcc.profile.model.ProfileDTO</value></property>
-
<property name="viewScript"><value>manager.getProfile()</value></property>
-
<property name="postScript"><value>manager.updateProfile(#object)</value></property>
-
<property name="successView" value="redirect:profile.view"/>
-
</bean>
Not as clear as in SWF maybe but enough to prove the idea. It is concise, it does the job. You do not have to write FormActions for trivial things.
Here is what I have in GenericFormController:
-
public class GenericFormController extends SimpleFormController{
-
protected Object manager;
-
protected String viewScript;
-
protected String postScript;
-
-
protected Object formBackingObject(HttpServletRequest request) throws ServletException, InstantiationException, IllegalAccessException {
-
try {
-
if(StringUtils.hasText(viewScript)){
-
OgnlContext context= new OgnlContext();
-
populateOgnlContextCommon(context, request);
-
return res;
-
}else{
-
return getCommandClass().newInstance();
-
}
-
} catch (OgnlException e) {
-
e.printStackTrace();
-
throw new ServletException(e);
-
}
-
}
-
-
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object commandObject, BindException errors) throws Exception {
-
try {
-
if(StringUtils.hasText(postScript)){
-
OgnlContext context= new OgnlContext();
-
context.put("command", command);
-
populateOgnlContextCommon(context, request);
-
Ognl.getValue(expr, context, this);
-
}else{
-
throw new ServletException("No postScript specified");
-
}
-
errors.reject(null, "Error:"+e.getMessage());
-
return showForm(request, errors, getFormView());
-
}
-
return new ModelAndView(getSuccessView());
-
}
-
-
protected void populateOgnlContextCommon(OgnlContext context, HttpServletRequest request){
-
context.put("request", request);
-
context.put("session", request.getSession());
-
context.put("user", SecurityContextHolder.getContext().getAuthentication().getPrincipal());
-
}
-
-
// Getters and Setters here ..
-
// ...
-
-
}
When I have time I will do something more production grade. For now I just glad to know that it is achievable and quite simple actualy.
Nifty! I saw your blog link on the ajaxian forums… I’ll have to give this a try in my app. We have a few webflow systems and having an OGNL easy controller ability would definitely be a convenient addition.