Spring MVC – 10 – Form Handling | @ModelAttribute

Merhaba Arkadaslar.
Bu bolumde Spring MVC ile basit bir form uygulamasi yapacagiz. Sonraki bolumlerde ,Validation , Error Message gibi konularla ilgili ornegimizi gelistirecegiz. Buradaki ornegimiz en temel sekilde olacaktir.

Simdiye kadar olan orneklerimizde hep Controller’dan data ekledik. Yani ;

model.addAttribute(message,"Welcome")

ve bu ekledigimiz data’ya JSTL yardimiyla JSP sayfamizdan ulastik ;

${message}

Peki data’yi view’de eklemek istersek. Bu durumda Controller’dan nasil bu veriye ulasabiliriz.
Yani disaridan HTML forma girilen verilere Controller uzerinden nasil erisim saglariz ?
Iste bu noktada Spring bizim icin bir cozum saglamaktadir.

@ModelAttribute

Spring tag library , HTML <form> ve <input> taglarina benzer sekilde ozel taglara sahiptir.
Spring tag library kullanabilmek icin @taglib directive’ini JSP sayfamiza eklememiz gereklidir.

<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

Burada ornegimiz icerisinde kullanacagimiz Spring tag library ;

  • <form:form>
  • <form:input>
  • <form:textarea>
  • <form:select>
  • <form:option>
  • <form:radiobutton>
  • <form:radiobuttons>

productAdd.jsp
Onceki ornegimizde hatirlayacagimiz gibi JSP sayfamizda Bootstrap kullanmistik. Burada onemli olan kisimlari paylasiyorum. Oncelikle @taglib directive tanimlarini yapalim.
Sonrasinda <form:form> tagini kullaniyoruz burada dikkat etmemiz gereken nokta ; modelAttribute attribute’u olacaktir.

Bununla birlikte modelAttribute yerine bazi orneklerde commandName attribute’unun kullanildigini gorebiliriz. Bu attribute’ler ayni isi yapmaktadir.

org.springframework.web.servlet.tags.form.FormTag

public void setModelAttribute(String modelAttribute) {
    this.modelAttribute = modelAttribute;
}

protected String getModelAttribute() {
    return this.modelAttribute;
}

public void setCommandName(String commandName) {
    this.modelAttribute = commandName;
}

protected String getCommandName() {
    return this.modelAttribute;
}

Daha sonrasinda yukarida listeledigimiz Spring tag’larini kullaniyoruz. Bu taglarin HTML olarak karsiliklari text , text area , radiobutton vs olacaktir.

Bu taglarda dikkat edecegimiz nokta path attribute’u olacaktir. Spring tag library HTML elemenleri ile form-backing bean modelini bind edecektir.
Bu ornegimizde modelimiz Product sinifimiz olacaktir , bu sinifta yer alan property/instance variable’lari path attribute’te kullaniyoruz. Boylece Spring bizim icin bind islemini gerceklestirecektir.

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

	<form:form  modelAttribute="newProduct" class="form-horizontal" method="post">

	...
	<form:input id="productId" path="productId" type="text" class="form:input-large"/>
	
	...

	<form:input id="name" path="name" type="text" class="form:input-large"/>

	...
	
	<form:input id="unitPrice" path="unitPrice" type="text" class="form:input-large"/>
	...

	<form:textarea id="description" path="description" rows = "2"/>
	...
        <form:select id="manufacturer" path="manufacturer" type="text" class="form:input-large">
            <form:option value="Apple">Apple</form:option>
            <form:option value="Google">Google</form:option>
            <form:option value="Samsung">Samsung</form:option>
        </form:select>
	...

	...
	<form:select id="category" path="category" type="text" class="form:input-large">
	    <form:option value="Laptop">Laptop</form:option>
	    <form:option value="Tablet">Tablet</form:option>
	    <form:option value="Smart Phone">Smart Phone</form:option>
	</form:select>
	..

	<form:input id="unitsInStock" path="unitsInStock" type="text" class="form:input-large"/>

	...
	<form:radiobutton path="condition" value="New" />New 
	<form:radiobutton path="condition" value="Old" />Old 
	<form:radiobutton path="condition" value="Refurbished" />Refurbished
	...

	<input type="submit" id="btnAdd" class="btn btn-primary" value ="Add"/>

	...


	</form:form>

Simdi de Controller tarafini yapalim. Dusundugumuzde , oncelikle HTTP GET istegi ile form sayfamiza istekte bulunmayiz daha sonrasinda HTTP POST ile submit islemini gerceklestirmemiz gerekir.

ProductManagementController.java

Kodu inceleyecek olursak onceki ornegimizde  @PathVariable  , @RequestParam annotation’larini kullanmistik , burada da benzer sekilde @ModelAttribute annotation’ini kullaniyoruz. Dikkat edecek olursak attribute olarak JSP sayfamizda kullandigimiz “newProduct” degerini kullaniyoruz.

Dikkat edecek olursak getNewProductForm metodumuzda RequestMethod.GET degerini kullandik. Boylece /add URL’i icin HTTP GET istekleri bu metot icin karsilanacaktir.
Geriye addProduct.jsp sayfasini donuyoruz ve @ModelAttribute annotation ile form-backing bean bilgisini veriyoruz.

Ikinci metodumuz da HTTP POST istegini karsilayacaktir  , yani formu submit ettigimizde bu metot istegi karsilayacaktir.

Daha sonrasinda /products url adresine redirect islemi yapiyoruz. Boylece istek tekrar karsilanacak ve tum urunlerin listesi getirilecektir. Tabi ekledigimiz urun de gelecektir.

package _09.form.handling.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import _09.form.handling.domain.Product;
import _09.form.handling.service.ProductService;

@Controller
@RequestMapping("/products/management")
public class ProductManagementController {

	@Autowired
	private ProductService productService;

	@RequestMapping(value = "/add", method = RequestMethod.GET)
        // http://localhost:8080/injavawetrust.springmvc/products/management/add
	public String getNewProductForm(@ModelAttribute("newProduct") Product newProduct) {
		return "09.form.handling.view/productAdd";
	}

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public String processAddNewProductForm(@ModelAttribute("newProduct") Product productToBeAdded) {
		productService.addProduct(productToBeAdded);
		return "redirect:/products";
	}
}

Controller , form-backing beanden verileri cekebilir @ModelAttribute annotation’ini kullaniriz. Form-backing bean ya da form bean , form datalarini store etmek icin kullanilir.

http://localhost:8080/injavawetrust.springmvc/products/management/add

Ilgili URL adresine gidip formu dolduralim  , submit ettigimizde basariyla ekleme islemi gerceklesecektir.

Reference Data

JSP dosyamizi inceleyecek olursak icerisinde hard-coded olarak kullandik ya da radiobuttonlari benzer sekilde hard-coded olarak yazdik.
Peki bu alanlar dinamik olarak gelecekse ozaman ne yapmamiz gerekir ? Iste bunun icin yine @ModelAttribute annotation’indan yararlanacagiz.

Kodumuzu inceleyecek olursak metotlarin basinda @ModelAttribute annotation’ini kullandik.
Bu metotlar istek karsilanmadan once calisacaktir. Boylece form sayfamiz acildiginda eklemis oldugumuz bu degerleri gorebiliriz. Tabi bunun icin JSP sayfamizda da degisiklik yapmamiz gereklidir.

// referenceData
@ModelAttribute("manufacturerList")
public List<String> prepareManufacturerList() {
	return Arrays.asList("Apple", "Google", "Samsung");
}

// referenceData
@ModelAttribute("categoryList")
public List<String> prepareCategoryList() {
	return Arrays.asList("Laptop", "Tablet", "SmartPhone");
}

// referenceData
@ModelAttribute("conditionMap")
public Map<String, String> prepareConditionMap() {
	Map<String, String> conditions = new HashMap<String, String>();
	conditions.put("new", "New");
	conditions.put("old", "Old");
	conditions.put("refurbished", "Refurbished");
	return conditions;
}
//

JSP sayfamizda hardcoded olarak ekledigimiz kisimlari yorum satiri haline getirdim , ilgili Spring tag’lari su sekilde olacaktir. Dikkat edecek olursak burada <form:select> ve <form:radiobuttons> taglari icin items attribute’unu ekledik ve ilgili model attributuler ile bind etmesini sagladik. Bir diger nokta olarak  <form:radiobutton> degil <form:radibuttons> tagini kullaniyoruz.

<form:select id="manufacturer" path="category" type="text" class="form:input-large" items="${manufacturerList}"/>

...

<form:select id="category" path="manufacturer" type="text" class="form:input-large" items="${categoryList}"/>

...

<form:radiobuttons path="condition" items="${conditionMap}"/>

Initialize Model

Bir diger nokta olarak formdaki alanlari initialize edebiliriz ya da diledigimiz option’ini secili olarak gelmesini isteyebiliriz. Bunun icin HTTP GET istegini karsiladigimiz metotta set metotlarini kullanmamiz yeterli olacaktir.

@RequestMapping(value = "/add", method = RequestMethod.GET)
// http://localhost:8080/injavawetrust.springmvc/products/management/add
public String getNewProductForm(@ModelAttribute("newProduct") Product newProduct) {
	newProduct.setDescription("default description");
	newProduct.setCondition("new");
	newProduct.setCategory("Tablet");
	newProduct.setManufacturer("Samsung");
	return "09.form.handling.view/productAdd";
}

Ornegimizi tekrar calistiralim ;

Ornek bir urun ekleyelim ;

Github kaynak kodlar / source folder
Injavawetrust-springmvc-tutorial

Yazimi burada sonlandiriyorum.
Herkese Bol Javali Gunler dilerim.
Be an oracle man , import java.*;
Levent Erguder
OCP, Java SE 6 Programmer
OCE, Java EE 6 Web Component Developer

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published.