0

In a spring-mvc application, I am getting the following error:

HTTP Status 400 - Required String parameter 'ownerID' is not present

When I try to load the following url:

http://localhost:8080/petclinic/owners

It is expecting

http://localhost:8080/petclinic/owners?ownerID=1 or some other valid number.  

How can I change the code so that it loads the expected content when an ownerID is specified, but also loads some other specified content when there is no ownerID specified, or when the ownerID is not valid? Is this something I need to change in jstl in the jsp or in the controller class?

Here is the part of OwnerController.java that handles the /owners url pattern:

@RequestMapping(value = "/owners", method = RequestMethod.GET)
public String processFindForm(@RequestParam("ownerID") String ownerId, Owner owner, BindingResult result, Map<String, Object> model) {
    Collection<Owner> results = this.clinicService.findOwnerByLastName("");
    model.put("selections", results);
    int ownrId = Integer.parseInt(ownerId);
    Owner sel_owner = this.clinicService.findOwnerById(ownrId);//jim added this
    model.put("sel_owner",sel_owner);
    return "owners/ownersList";
}

And here is the code for ownersList.jsp. Note that it is not accepting the choose...when block that I tried to use to solve this problem:

<body>
<div class="container">
<table>
    <tr>
        <td></td>
        <td>
            <spring:url value="/owners/new" var="owner_newUrl"></spring:url>
            <a href="${fn:escapeXml(owner_newUrl)}" class="btn btn-info" >Add New Owner</a>
        </td>
    </tr>
    <tr>
    <td width=160 valign="top">
        <datatables:table id="owners" data="${selections}" cdn="true" row="owner" theme="bootstrap2" 
                  cssClass="table table-striped" paginate="true" info="false" 
                  cssStyle="width: 150px;" align="left" >
            <datatables:column title="Name" cssStyle="width: 150px;" display="html">
                <spring:url value="/owners?ownerID={ownerId}" var="ownerUrl">
                    <spring:param name="ownerId" value="${owner.id}"/>
                </spring:url>
                <a href="${fn:escapeXml(ownerUrl)}"><c:out value="${owner.firstName} ${owner.lastName}"/></a>
            </datatables:column>
        </datatables:table>
    </td>

<c:choose>
<c:when test="${!empty sel_owner}">
    <td valign="top">
        <table class="table table-striped" style="width:600px;">
            <tr>
                <td><b><c:out value="${sel_owner.firstName} ${sel_owner.lastName}"/></b></td>
                <td></td>
            </tr>
            <tr>
                <td><c:out value="${sel_owner.address}"/></td>
                <td><c:out value="${sel_owner.city}"/></td>
            </tr>
            <tr>
                <td><c:out value="${sel_owner.telephone}"/></td>
                <td></td>
            </tr>
            <tr>
                <td colspan=2> 

                    <spring:url value="/owners/{ownerId}/edit" var="owner_editUrl">
                        <spring:param name="ownerId" value="${sel_owner.id}"/>
                    </spring:url>
                    <a href="${fn:escapeXml(owner_editUrl)}" class="btn btn-info" >Edit This Owner</a>

                    <spring:url value="/owners/{ownerId}/pets/new" var="owner_newpetUrl">
                        <spring:param name="ownerId" value="${sel_owner.id}"/>
                    </spring:url>
                    <a href="${fn:escapeXml(owner_newpetUrl)}" class="btn btn-info" >Add New Pet</a>

                    <spring:url value="/owners?ownerID={ownerId}&type=cats" var="owner_catsUrl">
                        <spring:param name="ownerId" value="${sel_owner.id}"/>
                    </spring:url>
                    <a href="${fn:escapeXml(owner_catsUrl)}" class="btn btn-info" >Show Cats</a>

                    <spring:url value="/owners?ownerID={ownerId}&type=dogs" var="owner_dogsUrl">
                        <spring:param name="ownerId" value="${sel_owner.id}"/>
                    </spring:url>
                    <a href="${fn:escapeXml(owner_dogsUrl)}" class="btn btn-info" >Show Dogs</a>

                    <spring:url value="/owners?ownerID={ownerId}&type=all" var="owner_allUrl">
                        <spring:param name="ownerId" value="${sel_owner.id}"/>
                    </spring:url>
                    <a href="${fn:escapeXml(owner_allUrl)}" class="btn btn-info" >Show All Pets</a>
                 </td>
            </tr>
        <c:if test="${fn:endsWith(requestScope['javax.servlet.forward.query_string'], 'all')}">
            <tr>
            <td colspan=2>
                <p>Pets</p>
                    <datatables:table id="pets" data="${sel_owner.pets}" cdn="true" row="pet" theme="bootstrap2" 
                              cssClass="table table-striped" paginate="false" info="false"  filter="false"
                              cssStyle="width: 350px;" align="left" >
                        <datatables:column title="Name" cssStyle="width: 200px;" display="html">
                            <c:out value="${pet.name}"/>
                        </datatables:column>
                        <datatables:column title="BirthDate" cssStyle="width: 300px;" display="html">
                            <joda:format value="${pet.birthDate}" pattern="yyyy-MM-dd"/>
                        </datatables:column>
                        <datatables:column title="Type" cssStyle="width: 200px;" display="html">
                            <c:out value="${pet.type.name}"/>
                        </datatables:column>
                    </datatables:table>
            </td>
            </tr>
        </c:if>
        <c:if test="${fn:endsWith(requestScope['javax.servlet.forward.query_string'], 'cats')}">
            <tr>
                <td colspan=2>
                    <p>Cats</p>
                    <datatables:table id="cats" data="${sel_owner.cats}" cdn="true" row="cat" theme="bootstrap2" 
                              cssClass="table table-striped" paginate="false" info="false"  filter="false"
                              cssStyle="width: 350px;" align="left" >
                        <datatables:column title="Name" cssStyle="width: 200px;" display="html">
                            <c:out value="${cat.name}"/>
                        </datatables:column>
                        <datatables:column title="BirthDate" cssStyle="width: 300px;" display="html">
                            <joda:format value="${cat.birthDate}" pattern="yyyy-MM-dd"/>
                        </datatables:column>
                        <datatables:column title="Type" cssStyle="width: 200px;" display="html">
                            <c:out value="${cat.type.name}"/>
                        </datatables:column>
                    </datatables:table>
                </td>
            </tr>
        </c:if>
        <c:if test="${fn:endsWith(requestScope['javax.servlet.forward.query_string'], 'dogs')}">
            <tr>
                <td colspan=2>            
                <p>Dogs</p>
                    <datatables:table id="dogs" data="${sel_owner.dogs}" cdn="true" row="dog" theme="bootstrap2" 
                              cssClass="table table-striped" paginate="false" info="false"  filter="false"
                              cssStyle="width: 350px;" align="left" >
                        <datatables:column title="Name" cssStyle="width: 200px;" display="html">
                            <c:out value="${dog.name}"/>
                        </datatables:column>
                        <datatables:column title="BirthDate" cssStyle="width: 300px;" display="html">
                            <joda:format value="${dog.birthDate}" pattern="yyyy-MM-dd"/>
                        </datatables:column>
                        <datatables:column title="Type" cssStyle="width: 200px;" display="html">
                            <c:out value="${dog.type.name}"/>
                        </datatables:column>
                    </datatables:table>
                </td>
            </tr>
        </c:if>
        </table>        
    </td>
    </tr>

</c:when>
<c:otherwise>
    Print this content if there is no ownerID.
</c:otherwise>


EDIT:

As per advice from Sotirios and Loc, I changed my code to the following, but it is still throwing the same error. Can someone show me explicitly how to fix this so that the /owners url pattern can deliver "some text" along with the list of owners instead of either throwing an error or delivering a default owner's details?

Here is the relevant method in OwnerController.java:

public String processFindForm(@RequestParam(value="ownerID", required=false) String ownerId, Owner owner, BindingResult result, Map<String, Object> model) {
    Collection<Owner> results = this.clinicService.findOwnerByLastName("");
    model.put("selections", results);
    boolean ownerIDValid;
    if(ownerId==null){ownerIDValid = false;}
    else{//I added this if test
        ownerIDValid=true;
        Integer ownrId = null;
        try {
             ownrId = Integer.parseInt(ownerId);
             Owner sel_owner = this.clinicService.findOwnerById(ownrId);//jim added this
             if (sel_owner == null) ownerIDValid = false;
             model.put("sel_owner",sel_owner);
        catch( Exception ex) {
             ownerIDValid = false;              
        }
    }
    model.put("ownerIDValid", ownerIDValid);
    return "owners/ownersList";
}

And here is the ownersList.jsp:

<html><head>tags and stuff</head>
<body>
<div class="container">
    <table>
        <tr>
            <td></td>
            <td>
                <spring:url value="/owners/new" var="owner_newUrl"></spring:url>
                <a href="${fn:escapeXml(owner_newUrl)}" class="btn btn-info" >Add New Owner</a>
            </td>
        </tr>
        <tr>
        <td width=160 valign="top">
            <datatables:table id="owners" data="${selections}" cdn="true" row="owner" theme="bootstrap2" 
                      cssClass="table table-striped" paginate="true" info="false" 
                      cssStyle="width: 150px;" align="left" >
                <datatables:column title="Name" cssStyle="width: 150px;" display="html">
                    <spring:url value="/owners?ownerID={ownerId}" var="ownerUrl">
                        <spring:param name="ownerId" value="${owner.id}"/>
                    </spring:url>
                    <a href="${fn:escapeXml(ownerUrl)}"><c:out value="${owner.firstName} ${owner.lastName}"/></a>
                </datatables:column>
            </datatables:table>
        </td>

<c:if test="${ownerIDValid}">
        <td valign="top">
            <table class="table table-striped" style="width:600px;">
                <tr>
                    <td><b><c:out value="${sel_owner.firstName} ${sel_owner.lastName}"/></b></td>
                    <td></td>
                </tr>
                <tr>
                    <td><c:out value="${sel_owner.address}"/></td>
                    <td><c:out value="${sel_owner.city}"/></td>
                </tr>
                <tr>
                    <td><c:out value="${sel_owner.telephone}"/></td>
                    <td></td>
                </tr>
                <tr>
                    <td colspan=2> 

                        <spring:url value="/owners/{ownerId}/edit" var="owner_editUrl">
                            <spring:param name="ownerId" value="${sel_owner.id}"/>
                        </spring:url>
                        <a href="${fn:escapeXml(owner_editUrl)}" class="btn btn-info" >Edit This Owner</a>

                        <spring:url value="/owners/{ownerId}/pets/new" var="owner_newpetUrl">
                            <spring:param name="ownerId" value="${sel_owner.id}"/>
                        </spring:url>
                        <a href="${fn:escapeXml(owner_newpetUrl)}" class="btn btn-info" >Add New Pet</a>

                        <spring:url value="/owners?ownerID={ownerId}&type=cats" var="owner_catsUrl">
                            <spring:param name="ownerId" value="${sel_owner.id}"/>
                        </spring:url>
                        <a href="${fn:escapeXml(owner_catsUrl)}" class="btn btn-info" >Show Cats</a>

                        <spring:url value="/owners?ownerID={ownerId}&type=dogs" var="owner_dogsUrl">
                            <spring:param name="ownerId" value="${sel_owner.id}"/>
                        </spring:url>
                        <a href="${fn:escapeXml(owner_dogsUrl)}" class="btn btn-info" >Show Dogs</a>

                        <spring:url value="/owners?ownerID={ownerId}&type=all" var="owner_allUrl">
                            <spring:param name="ownerId" value="${sel_owner.id}"/>
                        </spring:url>
                        <a href="${fn:escapeXml(owner_allUrl)}" class="btn btn-info" >Show All Pets</a>
                     </td>
                </tr>
            <c:if test="${fn:endsWith(requestScope['javax.servlet.forward.query_string'], 'all')}">
                <tr>
                <td colspan=2>
                    <p>Pets</p>
                            <datatables:table id="pets" data="${sel_owner.pets}" cdn="true" row="pet" theme="bootstrap2" 
                                  cssClass="table table-striped" paginate="false" info="false"  filter="false"
                                  cssStyle="width: 350px;" align="left" >
                            <datatables:column title="Name" cssStyle="width: 200px;" display="html">
                                <c:out value="${pet.name}"/>
                            </datatables:column>
                            <datatables:column title="BirthDate" cssStyle="width: 300px;" display="html">
                                <joda:format value="${pet.birthDate}" pattern="yyyy-MM-dd"/>
                            </datatables:column>
                            <datatables:column title="Type" cssStyle="width: 200px;" display="html">
                                <c:out value="${pet.type.name}"/>
                            </datatables:column>
                        </datatables:table>
                </td>
                </tr>
            </c:if>
            <c:if test="${fn:endsWith(requestScope['javax.servlet.forward.query_string'], 'cats')}">
                <tr>
                    <td colspan=2>
                        <p>Cats</p>
                        <datatables:table id="cats" data="${sel_owner.cats}" cdn="true" row="cat" theme="bootstrap2" 
                                  cssClass="table table-striped" paginate="false" info="false"  filter="false"
                                  cssStyle="width: 350px;" align="left" >
                            <datatables:column title="Name" cssStyle="width: 200px;" display="html">
                                <c:out value="${cat.name}"/>
                            </datatables:column>
                            <datatables:column title="BirthDate" cssStyle="width: 300px;" display="html">
                                <joda:format value="${cat.birthDate}" pattern="yyyy-MM-dd"/>
                            </datatables:column>
                            <datatables:column title="Type" cssStyle="width: 200px;" display="html">
                                <c:out value="${cat.type.name}"/>
                            </datatables:column>
                        </datatables:table>
                    </td>
                </tr>
            </c:if>
            <c:if test="${fn:endsWith(requestScope['javax.servlet.forward.query_string'], 'dogs')}">
                <tr>
                    <td colspan=2>            
                    <p>Dogs</p>
                        <datatables:table id="dogs" data="${sel_owner.dogs}" cdn="true" row="dog" theme="bootstrap2" 
                                  cssClass="table table-striped" paginate="false" info="false"  filter="false"
                                  cssStyle="width: 350px;" align="left" >
                            <datatables:column title="Name" cssStyle="width: 200px;" display="html">
                                <c:out value="${dog.name}"/>
                            </datatables:column>
                            <datatables:column title="BirthDate" cssStyle="width: 300px;" display="html">
                                <joda:format value="${dog.birthDate}" pattern="yyyy-MM-dd"/>
                            </datatables:column>
                            <datatables:column title="Type" cssStyle="width: 200px;" display="html">
                                <c:out value="${dog.type.name}"/>
                            </datatables:column>
                        </datatables:table>
                    </td>
                </tr>
            </c:if>
            </table>        
        </td>
        </tr>

</c:if>
<c:if test="${!ownerIDValid}">
        Print this content if there is no ownerID.
</c:if>
    </table>
</div>
</body>
</html>
LHA
  • 9,398
  • 8
  • 46
  • 85
CodeMed
  • 9,527
  • 70
  • 212
  • 364
  • Note that `@RequestParam` has a `required` attribute which you can set to `null`. – Sotirios Delimanolis Dec 06 '13 at 02:41
  • @SotiriosDelimanolis Thank you! So then how to I refactor my code to do what I am requesting? – CodeMed Dec 06 '13 at 02:44
  • Sorry, I meant to say that you can set to false. If the parameter isn't false, your parameter will get a value of null. You can check for null and handle it. – Sotirios Delimanolis Dec 06 '13 at 03:09
  • @SotiriosDelimanolis Thank you. I added an edit to my original posting above showing code attempting to do what you suggested. It is still throwing the same error. Can you tell me more specifically how to fix it? – CodeMed Dec 06 '13 at 20:23

1 Answers1

1

WRITE 2 methods. Each method serves different mapping.

@RequestMapping(value = "/owners", method = RequestMethod.GET)
public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model)
{

    String ownerId = DEFAULT value;
}

@RequestMapping(value = "/owners/{ownerID}", method = RequestMethod.GET)
public String processFindForm(@RequestParam("ownerID") String ownerId, Owner owner, BindingResult result, Map<String, Object> model)
{

}
  • The first one serve: '/petclinic/owners'
  • The second one serve '/petclinic/owners/100'; //100 is ownerID

OR 1 Method like this:

@RequestMapping(value = { "/owners", "/owners/{ownerID}" }, method = RequestMethod.GET)
public String processFindForm(@RequestParam(value="ownerID", required=false) String ownerId, Owner owner, BindingResult result, Map<String, Object> model)
{

}
LHA
  • 9,398
  • 8
  • 46
  • 85
  • Thank you. but /petclinic/owners/100 is not a case I want to handle. /petclinic/owners?ownerID=100 would be a case to handle, but only when 100 is not a valid value for ownerID (i.e. there is know owner number 100 in the database). Also what would you suggest I put for DEFAULT value? It would be nice to just load some neutral text if there is know ownerID specified, versus loading the full owner profile if a valid ownerID is specified. – CodeMed Dec 06 '13 at 02:43
  • Thank you. But if that were to work, it would need more processing than just that. The method in OwnerController.java uses ownerID and the jsp uses sel_owner, so the absence of each is still causing errors that make it impossible for me to test your theory. I tried choose...when, but eclipse does not seem to be seeing it. How else do I change the jsp and the controller above? – CodeMed Dec 06 '13 at 02:53
  • Thank you. But for me to understand what you are saying, I need to see it in code. I am fiddling around with code approaches on my end, but they are not working. Can you post what you are suggesting in code, using what I posted above in my original posting? – CodeMed Dec 06 '13 at 03:01
  • I get the jsp/jstl part of your suggestion, but I don't understand where exactly you think ownerIDValid should be created and managed. I assume you mean that should happen in the processFindForm() method of OwnerController.java, but I do not understand how that value would be sent back to the jsp. Can you show explicitly what you would change in OwnerController.java? Do you create an instance variable? Or do you do a model.put? What does it look like? Then is the jsp/jstl as simple as the c:if test? – CodeMed Dec 06 '13 at 04:08
  • Thank you. +1 for all your help so far. But it still does not work. I think the problem is that eclipse is giving a warning that the c:if is not associated with a /c:if, and vice versa. If you look at my original posting above, you will see that the jsp contains numerous c:if blocks within the segment of code that would be surrounded by your new c:if block. Is the problem with nesting c:if blocks in a jsp? How do I fix this? – CodeMed Dec 06 '13 at 20:09
  • Sorry it took me until now to +1. I added an edit to my original posting above showing my exact code that is still throwing the same error despite trying to follow your advice. Can you show me exactly how to fix it? – CodeMed Dec 06 '13 at 20:25
  • Thank you. I put your exact changes in my code, stopped the tomcat instance, and then did run as...run on server again in eclipse. When I typed in the /owners url pattern, I then get the same error message as follows: HTTP Status 400 - Required String parameter 'ownerID' is not present. What else should I try? – CodeMed Dec 06 '13 at 20:41
  • I put a large bounty on a related question. Would you mind looking at the related question and submitting an answer? I will award the large bounty to the person who provides a working solution with an explanation. Here is the link: http://stackoverflow.com/questions/20586865/document-not-saving-in-spring-jpa-document-manager-application – CodeMed Dec 17 '13 at 00:25