Announcement Announcement Module
Collapse
No announcement yet.
Custom tag library for generating DRY urls Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Custom tag library for generating DRY urls

    Hello,

    I looked at the output of roo and notices that urls (or parts thereof) is being duplicated in the views and controllers. What I did was create a few final strings on the controller, so that the controller effectively looks as follows:

    Code:
    @RooWebScaffold(path = "posts", automaticallyMaintainView = true, formBackingObject = Post.class)
    @RequestMapping(PostController.POSTS_PATH + "/**")
    @Controller
    public class PostController {
    
    	public static final String POSTS_PATH = "/posts";
    	public static final String NEW_POST_PATH = POSTS_PATH + "/form";
    	public static final String POST_PATH = POSTS_PATH + "/{id}";
    	public static final String CREATE_POST_PATH = POSTS_PATH;
    	public static final String UPDATE_POST_PATH = POSTS_PATH + "/{id}/form";
    	public static final String EDIT_POST_PATH = POSTS_PATH + "/{id}";
    
    	@RequestMapping(value = CREATE_POST_PATH, method = RequestMethod.POST)
    	public String create(@Valid Post post, BindingResult result,
    			ModelMap modelMap) {
    		// stuff
    	}
    
    	@RequestMapping(value = NEW_POST_PATH, method = RequestMethod.GET)
    	public String createForm(ModelMap modelMap) {
    		// stuff
    	}
    
    	@RequestMapping(value = POST_PATH, method = RequestMethod.GET)
    	public String show(@PathVariable("id") Long id, ModelMap modelMap) {
    		// stuff
    	}
    
    	@RequestMapping(value = POSTS_PATH, method = RequestMethod.GET)
    	public String list(
    			@RequestParam(value = "page", required = false) Integer page,
    			@RequestParam(value = "size", required = false) Integer size,
    			ModelMap modelMap) {
    				// stuff
    	}
    
    	@RequestMapping(method = RequestMethod.PUT)
    	public String update(@Valid Post post, BindingResult result,
    			ModelMap modelMap) {
                 // stuff
    	}
    
    	@RequestMapping(value = UPDATE_POST_PATH, method = RequestMethod.GET)
    	public String updateForm(@PathVariable("id") Long id, ModelMap modelMap) {
               // stuff
    	}
    
    	@RequestMapping(value = POST_PATH, method = RequestMethod.DELETE)
    	public String delete(@PathVariable("id") Long id,
    			@RequestParam(value = "page", required = false) Integer page,
    			@RequestParam(value = "size", required = false) Integer size) {
                 // stuff
    	}
    
    }
    So if I manually manage the controller, I can change the request mapping in one place. It still doesn't help much, since I need to manually update the views. I tried to generate additional tags using the tagx scheme, however I am not sure how to reference the final strings in the controllers. Is this possible?

    The other thought I had was to simply generate a custom tag library and use them in the views. The tags can then simply reference the constants in the controller. The tags I am think of creating tags for an entity like "Post" are:

    posts_url - the url to view a list of posts
    new_post_url - the url to display a new post form
    post_url - takes an instance of post and generates a url to view that post
    update_post_url - takes an instance of post and generates a url to modify that post

    So instead of doing the following in menu.jspx:

    Code:
     <li id="web_mvc_jsp_create_posts_menu_item">
         <spring:url value="/posts/form" var="web_mvc_jsp_create_posts_menu_item_url"/>
         <a href="${web_mvc_jsp_create_posts_menu_item_url}">
             <spring:message code="label.post" var="label_post"/>
             <spring:message arguments="${label_post}" code="global.menu.new"/>
         </a>
     </li>
    One can write code as follows:

    Code:
     <li id="web_mvc_jsp_create_posts_menu_item">
         <mytaglib:new_post_url>
             <spring:message code="label.post" var="label_post"/>
             <spring:message arguments="${label_post}" code="global.menu.new"/>
         </mytaglib:new_post_url>
     </li>
    which generates effectively the same code. It means a designer can use this tag throughout the application to generate a link to the page that displays the form to create a new post.

    These tags can also take additional logic into account such that if the resulting url points to the current page, then the link will not be generated; just the inner body. Additionally, security may dictate that the link shouldn't be generated if the user doesn't have access to the resource and the tag library can take care of that. This can increase productivity when manually changing the design of the application.

    What is the best way to approach this? I can't seem to find any decent resources on how to develop your own tag library with STS and Spring MVC. I can however write a generic tag library.

    The ultimate goal may be for roo to generate the tag library as part of scaffolding.

    Thanks,
    Werner

  • #2
    Hi Werner,

    Thanks for sharing your ideas here. In fact the second idea w/r to the menu.jspx is somewhat close to the changes I have been working on and off in the recent days. My current solution goes beyond what you are suggesting but the general idea remains the same. We will be releasing Roo 1.0 very soon and I will start committing my changes around mid Jan. I would be very interested in your feedback when we (hopefully) cut an early milestone release for Roo 1.1 in late January.

    Your first suggestion to have the request mappings in one place does not seem to add too much value from my perspective since the URIs all unique to the different methods, so your code would just become a little more verbose. Since most modern IDEs offer code collapsing it would not be too hard to keep the URI definitions in the method level annotation. This way it is also always clear which URI this method handles. So I think the current code is not that bad with regards to the URIs. I am however happy to be convinced otherwise.

    Comment

    Working...
    X