9

I am new to Spring MVC. I am writing an app that uses Spring, Spring MVC and JPA/Hibernate I don't know how to make Spring MVC set a value coming from a dropdown into a model object. I can imagine this a very common scenario

Here is the code:

Invoice.java

@Entity
public class Invoice{    
    @Id
    @GeneratedValue
    private Integer id;

    private double amount;

    @ManyToOne(targetEntity=Customer.class, fetch=FetchType.EAGER)
    private Customer customer;

    //Getters and setters
}

Customer.java

@Entity
public class Customer {
    @Id
    @GeneratedValue
    private Integer id;

    private String name;
    private String address;
    private String phoneNumber;

    //Getters and setters
}

invoice.jsp

<form:form method="post" action="add" commandName="invoice">
    <form:label path="amount">amount</form:label>
    <form:input path="amount" />
    <form:label path="customer">Customer</form:label>
    <form:select path="customer" items="${customers}" required="true" itemLabel="name" itemValue="id"/>                
    <input type="submit" value="Add Invoice"/>
</form:form>

InvoiceController.java

@Controller
public class InvoiceController {

    @Autowired
    private InvoiceService InvoiceService;

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addInvoice(@ModelAttribute("invoice") Invoice invoice, BindingResult result) {
        invoiceService.addInvoice(invoice);
        return "invoiceAdded";
    }
}

When InvoiceControler.addInvoice() is invoked, an Invoice instance received as a parameter. The invoice has an amount as expected, but the customer instance attribute is null. This is because the http post submits the customer id and the Invoice class expects a Customer object. I don't know what is the standard way to convert that.

I have read about Controller.initBinder(), about Spring Type conversion (in http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html) but I don't know if that is the solution for this problem.

Any ideas?

рüффп
  • 5,172
  • 34
  • 67
  • 113

1 Answers1

7

The trick as you have already noted is to register a custom converter which will convert the id from the drop down into a Custom instance.

You can write a custom converter this way:

public class IdToCustomerConverter implements Converter<String, Customer>{
    @Autowired CustomerRepository customerRepository;
    public Customer convert(String id) {
        return this.customerRepository.findOne(Long.valueOf(id));
    }
}

Now register this converter with Spring MVC:

<mvc:annotation-driven conversion-service="conversionService"/>

<bean id="conversionService"
    class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
       <list>
          <bean class="IdToCustomerConverter"/>
       </list>
    </property>
</bean>
Biju Kunjummen
  • 49,138
  • 14
  • 112
  • 125
  • 2
    What i dislike about such approach is that you have already loaded data object with such Id from database. Now when you convert it back from string to object, you fetch it from db again. – Erik Kaju Oct 06 '14 at 09:41
  • @Biju Kunjummen: could you please update your answer with Annotation and Controller class code as well – Ghost Rider Mar 23 '17 at 16:53