TroubleM TroubleM - 3 years ago 211
Java Question

Spring mvc - How to use or send the same object in different controller?

Problem solved, thanks guys ;) I EDITED THE CODE, LOOK AT THE BOTTOM

I am a Spring newbie and I am a little bit confused about using an object I already created through different controller in Spring MVC. I wrote a simple project that allow user to insert some car's details(brand, model and license plate number) and to see the list of submitted records (plus a reset all action and a selective delete of a single record). Now I also want to edit the values of a record but things get tough for me..

VeicoloController.java

@Controller
@RequestMapping("/veicolo")
@SessionAttributes("veicoli")

public class VeicoloController {

@Autowired VeicoloValidator veicoloValidator;


@GetMapping({"", "lista"})
public String lista() {
return "/veicolo/lista_veicoli";
}

@GetMapping("inserisci_veicolo")
public ModelAndView inserisci(){
return new ModelAndView("veicolo/inserisci_veicolo", "modelVeicolo", new Veicolo());
}

@PostMapping("save")
public ModelAndView salvaVeicolo(@ModelAttribute("modelVeicolo") Veicolo veicolo, BindingResult bindingResult,Model model)
{

System.out.println("Veicolo = " + veicolo);

veicoloValidator.validate(veicolo, bindingResult);

if (bindingResult.hasErrors()){
return new ModelAndView("veicolo/inserisci_veicolo");
}
else{
Set<Veicolo> veicoli;
if (!model.containsAttribute("veicoli")){
veicoli = new HashSet<>();
model.addAttribute("veicoli", veicoli);
}
else{
veicoli = (Set<Veicolo>) model.asMap().get("veicoli");
}
veicoli.add(veicolo);
return new ModelAndView("veicolo/lista_veicoli");
}
}


Now, here there are my problematic Controllers:

I use this controller to edit the row, using the license plate number as unique element to retrieve that particular vehicle object and passing it by querystring from the jsp(i'll show it later). In this way i can show the vehicle attribute in the edit forms (and hiding the license plate number form that cannot be modified)

@GetMapping("modifica")
public ModelAndView modificaVeicolo(@RequestParam("targa")String targa, Model model){

Set<Veicolo> veicoli = (Set<Veicolo>)model.asMap().get("veicoli");
Veicolo veicoloMod = null;
for(Veicolo v:veicoli){
if(v.getTarga().equalsIgnoreCase(targa)){
veicoloMod = v;
break;
}
model.addAttribute(veicoloMod);
}
return new ModelAndView("veicolo/modifica_veicolo", "modelVeicolo", veicoloMod);
}


This is how I tried to do the update Controller, I really don't know how to use the object I got in the previous controller that give me (i suppose) all the information I need of the car

@PostMapping("update")
public ModelAndView updateVeicolo(@ModelAttribute("modelVeicolo")Veicolo veicolo, BindingResult bindingResult,Model model)
{

// Veicolo veicoloToUpdate = (Veicolo)model.asMap().get("veicoli");


veicoloValidator.validate(veicolo, bindingResult);

if (bindingResult.hasErrors())
{
return new ModelAndView("veicolo/modifica_veicolo");
}
else
{
Set<Veicolo> veicoli =(Set<Veicolo>)model.asMap().get("veicoli");
veicoli.add(veicolo);

}
return new ModelAndView("veicolo/lista_veicoli");
}


modifica_veicolo.jsp



<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Modifica il veicolo</title>
</head>

<body>

<h1>Modifica il veicolo</h1>
<br>
<br>
<form:form method="POST" action="${pageContext.request.contextPath}/veicolo/update" commandName="modelVeicolo" ModelAttribute="modelVeicolo">
<table>
<tr>
<p class="errorLine">
<form:errors path="marca" cssStyle="color: #ff0000"/>
</p>
<td><form:label path="marca">Marca</form:label></td>
<td><form:input path="marca" /></td>

</tr>
<tr>
<p class="errorLine">
<form:errors path="modello" cssStyle="color: #ff0000"/>
</p>
<td><form:label path="modello">Modello</form:label></td>
<td><form:input path="modello"/></td>

</tr>
<td><form:input type="hidden" path="targa" value="${veicolo.targa}" /></td>
<tr>
<td colspan="3">
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form:form>
<br>
<br>
<a href="${pageContext.request.contextPath}/">Torna alla Home</a>

</body>
</html>





and lista_veicoli.jsp (from the list you can edit the record)



<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Lista veicoli</title>
</head>

<body>

<h1>Lista Veicoli</h1>
<br>
<br>

<c:if test="${veicoli == null || veicoli.isEmpty()}">
Nessun veicolo registrato.
</c:if>

<div>&nbsp;</div>

<table>
<thead>
<tr>
<th>| Marca </th>
<th>| Modello |</th>
<th> Targa |</th>
&nbsp;
&nbsp;

</tr>
</thead>
<c:forEach var="veicolo" items="${veicoli}">
<tr>
<td>
${veicolo.marca}
</td>
<td>
${veicolo.modello}
</td>
<td>
${veicolo.targa}
</td>
<td>
<a href="${pageContext.request.contextPath}/veicolo/modifica?targa=${veicolo.targa}" > modifica </a>
</td>
<td>
<a href="${pageContext.request.contextPath}/veicolo/rimuovi?targa=${veicolo.targa}" > elimina </a>
</td>
</tr>
</c:forEach>

</table>
<br>
<br>
<p><a href="${pageContext.request.contextPath}/">Torna alla Home</a> |</p>

<p><a href="${pageContext.request.contextPath}/veicolo/reset">Cancella Lista</a> |</p>

<p><a href="${pageContext.request.contextPath}/veicolo/inserisci_veicolo">Inserisci un altro veicolo</a> |</p>

</body>
</html>





I am stuck now, if I click on the update button nothing happen and I doubt that things can be done way too better than this. I need your help :'(

Also, sorry for the long post!

EDIT:
ok, i changed this controller and it seems to work, but only for the first record inserted!

@PostMapping("update")
public ModelAndView updateVeicolo(@ModelAttribute("modelVeicolo")Veicolo veicolo,
BindingResult bindingResult,Model model)
{

veicoloValidatorNoTarga.validate(veicolo, bindingResult);

if (bindingResult.hasErrors())
{
return new ModelAndView("veicolo/modifica_veicolo");
}
else
{
Set<Veicolo> veicoli =(Set<Veicolo>)model.asMap().get("veicoli");

Veicolo daInserire = veicolo;
Veicolo daRimuovere = null;
for(Veicolo v : veicoli)
{
if(v.getTarga().equalsIgnoreCase(veicolo.getTarga())){
daRimuovere = v;
break;
}
}
veicoli.remove(daRimuovere);
veicoli.add(daInserire);

}
return new ModelAndView("veicolo/lista_veicoli");
}


If i want to edit the second or more element of the set an exception occurs. It says "HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalArgumentException: Model object must not be null".
In fact in the modificaVeicolo Controller at the line

for(Veicolo v:veicoli){
if(v.getTarga().equalsIgnoreCase(targa)){
veicoloMod = v;
break;
}


targa value is the correct value of the second or third(etc) car, but v has the value of the first car's license plate! In theory it should have the value of the selected car
...any suggestions?

Answer Source

Key Point::If you choose to use HashSet storing Objects,the Class has to override equals and hashcode!

1.Veicolo.java

Override equlas and hashcode

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Veicolo veicolo = (Veicolo) o;
    return targa.equals(veicolo.getTarga());
}

@Override
public int hashCode() {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getTarga().hashCode();
    return result;
}

2.VeicoloController.updateVeicolo()

Update object By deleting and adding

@PostMapping("update")
public ModelAndView updateVeicolo(@ModelAttribute("modelVeicolo") Veicolo veicolo, BindingResult bindingResult,
                                  Model model) {

//        Veicolo veicoloToUpdate = (Veicolo)model.asMap().get("veicoli");


    veicoloValidator.validate(veicolo, bindingResult);

    if (bindingResult.hasErrors()) {
        return new ModelAndView("veicolo/modifica_veicolo");
    } else {
        Set<Veicolo> veicoli = (Set<Veicolo>) model.asMap().get("veicoli");

        if (veicoli.contains(veicolo)) {
            veicoli.remove(veicolo);
            veicoli.add(veicolo);
        }

    }
    return new ModelAndView("veicolo/lista_veicoli");
}

3.VeicoloController.modificaVeicolo()

Move the model.addAttribute into the loop

@GetMapping("modifica")
public ModelAndView modificaVeicolo(@RequestParam("targa") String targa, Model model) {

    Set<Veicolo> veicoli = (Set<Veicolo>) model.asMap().get("veicoli");
    Veicolo veicoloMod = null;
    for (Veicolo v : veicoli) {
        if (v.getTarga().equalsIgnoreCase(targa)) {
            veicoloMod = v;
            model.addAttribute(veicoloMod);
            break;
        }
    }
    return new ModelAndView("veicolo/modifica_veicolo", "modelVeicolo", veicoloMod);
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download