Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

map subset of request params to an object in spring mvc

Tags:

spring-mvc

In our web app, using Spring MVC 3.2 we display many paginated lists of different objects, and the links to other pages in the list are constructed like this:

/servlet/path?pageNum=4&resultsPerPage=10&sortOrder=ASC&sortBy=name

although there might be additional request parameters in the URL as well (e.g., search filters).

So we have controller methods like this:

@RequestMapping(method = RequestMethod.GET, value="/ajax/admin/list")
public String ajaxlistGroups(Model model,
   @RequestParam(value="pageNumber",required=false,defaultValue="0") Long pageNumber,
   @RequestParam(value="resultsPerPage",required=false,defaultValue="10") int resultsPerPage,
   @RequestParam(value="sortOrder",required=false,defaultValue="DESC") String sortOrder,
 @RequestParam(value="orderBy",required=false,defaultValue="modificationDate")String orderBy)  {
// create a PaginationCriteria object to hold this information for passing to Service layer
// do Database search
// return a JSP view name

}

so we end up with this clumsy method signature, repeated several times in the app, and each method needs to create a PaginationCriteria object to hold the pagination information, and validate the input.

Is there a way to create our PaginationCriteria object automatically, if these request params are present? E.g., replace the above with:

@RequestMapping(method = RequestMethod.GET, value="/ajax/admin/list")
public String ajaxlistGroups(Model model, @SomeAnnotation? PaginationCriteria criteria,
  )  {
 ...
   }

I.e., is there a way in Spring to take a defined subset of requestParams from a regular GET request, and convert them to an object automatically, so it's available for use in the Controller handler method? I've only used @ModelAttribute before, and that doesn't seem the right thing here.

Thanks!

like image 989
otter606 Avatar asked Feb 07 '13 10:02

otter606


1 Answers

Spring 3.2 should automatically map request parameters to a custom java bean.

@RequestMapping(method = RequestMethod.GET, value="/ajax/admin/list")
public String ajaxlistGroups(Model model, PaginationCriteriaBean criteriaBean,
  )  {
 //if PaginationCriteriaBean should be populated as long as the field name is same as 
 //request parameter names.
}

I'm not sure how Spring magically achieve this(without @ModelAttribute), but the code above works for me.

There is another way to achieve the same goal, you can actually achieve more, that is spring AOP.

<bean id="aspectBean" class="au.net.test.aspect.MyAspect"></bean>
<aop:config>
    <aop:aspect id="myAspect" ref="aspectBean">
    <aop:pointcut id="myPointcut"
        expression="execution(* au.net.test.web.*.*(..)) and args(request,bean,..)" />
    <aop:before pointcut-ref="myPointcut" method="monitor" />
    </aop:aspect>
</aop:config>

in application context, we declare Aspect bean as well as Pointcut along with advice, which in your case is before advice

the following is source code

    public class PaginationCriteriaBean {

        private String id;
        private String name;

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
//custom Aspect
public class MyAspect {

    public void monitor( HttpServletRequest request,PaginationCriteriaBean bean){
        //populate your pagination bean
        bean.setId(request.getParameter("id"));
        bean.setName("my new name");
    }
}

    @RequestMapping(value="/app")
    public String appRoot(HttpServletRequest request,PaginationCriteriaBean bean){
        System.out.println(bean.getId());
        System.out.println(bean.getName());
        return "app";
    }

by doing so, the aspect will intercept spring controller and populate PaginationCriteriaBean based on request parameters, and you can even change the original value in request. With this AOP implementation you are empowered to apply more logic against Pagination, such as logging and validation and etc.

like image 185
spiritwalker Avatar answered Nov 18 '22 03:11

spiritwalker