Jason
Jason

Reputation: 406

CRUD with Spring MVC - DRY Suggestions

I'm new to Spring MVC. I am writing a small app to learn. I am working on some basic CRUD. I am writing the same code more than once to edit/display a domain class. What would be a better/proper way to implement the edit and save method?

Thanks

The controller:

@RequestMapping(value="/userInfo/create/{id}")
public ModelAndView edit(@PathVariable Integer id, Model model)
{
    logger.info("UserInfo edit {}", id);

    UserInfo userInfo = userInfoService.get(id);

    model.addAttribute("userInfo", userInfo);
    model.addAttribute("parent" , userInfoService.get(userInfo.getParentId()));
    model.addAttribute("allUsers", userInfoService.list());
    model.addAttribute("affInfos", affInfoService.findAllByUserInfo(userInfo));

    ModelAndView mv = new ModelAndView("userInfo/create", "command", model);

    return mv;
}


@RequestMapping(value="/userInfo/save", method=RequestMethod.POST)
public ModelAndView save(@Valid @ModelAttribute("userInfo")UserInfo userInfo, BindingResult result, Model model)
{
    logger.info("UserInfo save");

    model.addAttribute("userInfo", userInfo);
    model.addAttribute("parent" , userInfoService.get(userInfo.getParentId()));
    model.addAttribute("allUsers", userInfoService.list());
    model.addAttribute("affInfos", affInfoService.findAllByUserInfo(userInfo));

    ModelAndView mv = new ModelAndView("userInfo/create", "command", model);

    if(!result.hasErrors())
    {
        userInfoService.saveOrUpdate(userInfo);
        model.addAttribute("flashMsg", "UserInfo saved!");
    }
    else
    {
        model.addAttribute("flashMsg", "Could not save.");
    }

    return mv;
}

The View:

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<html>
<head>
    <title>Create/Edit UserInfo</title>
</head>
<body>

<div style="margin-left:100px;font-weight: bold;font-size:16px;margin-bottom:20px;margin-top: 10px;">User Information</div>

<c:if test="${flashMsg != null}">
    <div>${flashMsg }</div>
</c:if>

<form:form  modelAttribute="userInfo" action="${pageContext.request.contextPath}/userInfo/save" method="post" >

<form:hidden path="id"/>

<div style="width:200px;margin-left:100px;margin-bottom:10px;">
    <div style="margin-bottom:4px;font-weight: bold;">Name</div>
    <div><form:input path="name"/></div>
</div>

<div style="width:200px;margin-left:100px;margin-bottom:10px;">
    <div style="margin-bottom:4px;font-weight: bold;">Parent</div>
    <div>
        <form:select path="parentId" itemLabel="name" itemValue="id" >
            <form:option value="-1">Choose Parent</form:option>
            <form:options items="${allUsers}" itemLabel="name" itemValue="id"/>
        </form:select>
    </div>
</div>

<c:if test="${affInfos != null }">
<div>
    <table style="width:600px;border:1px solid #ccc;" class="center ui-corner-all shadow zebra-striped">
        <thead>
            <tr>
                <th>Macro</th>
                <th>AffID</th>
                <th><button type="button" class="btn shadow">New</button></th>
            </tr>
        </thead>
        <tbody>
             <c:forEach var="affInfo" varStatus="i" items="${affInfos }">
                <tr>
                    <td><input type="text" name="macro_${affInfo.id}" id="macro_${affInfo.id}" value="${affInfo.macro}"></td>
                    <td><input type="text" name="affid_${affInfo.id}" id="affid_${affInfo.id}" value="${affInfo.affid}"></td>
                    <td><button class="btn shadow" type="button">Delete</button></td>
                </tr>
             </c:forEach>
         </tbody>
    </table>
</div>
</c:if>

<div style="margin-left:100px;margin-top:10px;" >
    <form:button class="btn shadow">Submit</form:button>
</div>

</form:form>


</body>
</html>

Upvotes: 0

Views: 694

Answers (1)

sam
sam

Reputation: 3511

First you could of course create a method like this one :

private method init(){
    model.addAttribute("userInfo", userInfo);
    model.addAttribute("parent" , userInfoService.get(userInfo.getParentId()));
    model.addAttribute("allUsers", userInfoService.list());
    model.addAttribute("affInfos", affInfoService.findAllByUserInfo(userInfo));
}

But, if your controller is used for only one JSP page (JSPX is the recommend page type), you can use something like that for each attribute on your JSP Page :

@ModelAttribute("allUsers")
public List<User> populateUserInfoList() {
    return userInfoService.list();
}

It will automatically add to the ModelAndView the attribute wich name is in the @ModelAttribute annotation. But be careful , this will be called each time you use your controller, wich could create useless called to the database if your controller do more than calling always the same kind of JSP which need the same data.

With this you don't need anymore this line :

model.addAttribute("allUsers", userInfoService.list());

Hope it helps you

Upvotes: 2

Related Questions