Spring MVC – 12 – Form Validation – 01

Merhaba Arkadaslar
Bu bolumde Validation kavraminin Spring MVC uzerinde uygulanisini incelemeye baslayacagiz.
Validation , dogrulama onaylama gibi anlamlara gelmektedir. Bu kavram sadece Spring MVC’ye hatta Java’ya ozgu bir kavram degildir.
Sonucta disaridan/kullanicidan aldigimiz verileri kontrol etmek isteriz.
Validation icin Spring MVC de 3 farkli yaklasim kullanabiliriz. Hemen ilk yontem ile baslayalim.

NOT : Onceki 2 bolumde urun ekleme sayfasini gelistirmeye basladik , bu bolumde ayni sayfayi kullanacagiz. Tabi ornekler birbirinden bagimsiz olmasi acisindan yeni bir package ve folder olusturuyorum.

ProductValidator.java

  • org.springframework.validation.Validator arabirimini uyguluyoruz.
  • target paremetresini kullandigimiz/validation yapacagimiz ilgili model sinifina cast ediyoruz.
  • Daha sonrasinda ilgili business logic ‘ e gore kontrol yapabilirz. Ornegin product id bilgisinin en az 5 karakter olmasini istiyoruz. Bu sarti saglamiyorsa bu durumda error mesajini ekliyoruz. Bunun icin errors parametresi uzerinden rejectValue metodunu kullanabiliriz.
  • rejectValue metodunun overloaded versiyonlari bulunmaktadir. Arguman olarak “productId” ve “required.productId” String literal degerlerini veriyoruz.
    productId , Product sinifindaki property alanina karsilik gelmektedir , required.productId ise kullanacagimiz mesaj ismine karsilik gelmektedir.
  • errors.rejectValue("productId", "required.productId");
  • Eger sadece bos ve whitespace’e karsilik bir validation yapmak istiyorsak bu durumda org.springframework.validation.ValidationUtils sinifinda tanimli metotlari kullanabiliriz.
    Yine benzer sekilde bir yaklasimla “name” ve “required.name” String degerlerini arguman olarak verdik , bununla birlikte errors’u da arguman olarak veriyoruz.
package _11.validation.validator;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import _11.validation.domain.Product;

@Component
public class ProductValidator implements Validator {

	@Override
	public void validate(Object target, Errors errors) {

		Product product = (Product) target;

		if (product.getProductId() == null || product.getProductId().trim().length() < 5) {
			errors.rejectValue("productId", "required.productId");
		}

		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required.name");

		if (product.getUnitPrice() <= 0) {
			errors.rejectValue("unitPrice", "required.unitPrice");
		}

		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "description", "required.description");

		if (product.getUnitsInStock() <= 0) {
			errors.rejectValue("unitsInStock", "required.unitsInStock");
		}
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return false;
	}

}

Formu submit ettigimizde ilgili validate metodumuzu kullanalim sinifimizi kullanalim ;

ProductManagementController.java

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

	@Autowired
	private ProductService productService;

	@Autowired
	private ProductValidator productValidator;

	//....

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public String processAddNewProductForm(@ModelAttribute("newProduct") Product productToBeAdded, BindingResult bindingResult) {

		productValidator.validate(productToBeAdded, bindingResult);

		if (bindingResult.hasErrors()) {
			return "11.validation.view/productAdd";
		}
		
		productService.addProduct(productToBeAdded);
		return "redirect:/products";
	}

	//....

}

productAdd.jsp
JSP dosyamizda dikkat etmemiz gereken nokta  <form:errors> tagidir. path attribute , validation yaptigimiz property bilgisini veriyoruz. Boylece ilgili error mesaji input alaninin yanina ekliyoruz. cssClass attribute ile css class bilgisi veriyoruz.

<div class="col-lg-10">
	<form:input id="productId" path="productId" type="text" class="form:input-large"/>
	<form:errors path="productId" cssClass="text-danger"/>
</div>


<div class="col-lg-10">
	<form:input id="name" path="name" type="text" class="form:input-large"/>
	<form:errors path="name" cssClass="text-danger"/>
</div>

<div class="form:input-prepend">
	<form:input id="unitPrice" path="unitPrice" type="text" class="form:input-large"/>
	<form:errors path="unitPrice" cssClass="text-danger" cssStyle="display: inline-flex;"/>							
</div>


<div class="col-lg-10">
	<form:textarea id="description" path="description" rows = "2"/>
	<form:errors path="description" cssClass="text-danger"/>
</div>

<div class="col-lg-10">
	<form:input id="unitsInStock" path="unitsInStock" type="text" class="form:input-large"/>
	<form:errors path="unitsInStock" cssClass="text-danger" cssStyle="display: inline-flex;"/>
</div>


Onceki bolumde message source kullanimini incelemistik. springMessages_XX.dosyalarimiza error mesajlarini ekleyelim.

springMessages_en.properties

##Error messages
required.productId= Invalid product id. It should be minimum 5 characters
required.name= The product name cannot be empty.
required.unitPrice= Invalid price.
required.unitsInStock=Invalid stock.
required.description=The product description cannot be empty.

springMessages_tr.properties

## Error messages
required.productId= Ürün kodu en az 5 karekter girilmelidir.
required.name= Ürün ismi boş bırakılamaz.
required.unitPrice= Geçersiz ürün fiyatı.
required.unitsInStock=Geçersiz stok.
required.description=Ürün tanımı boş bırakılamaz.

Bu asamadan sonra test etmeye haziriz ;

http://localhost:8080/injavawetrust.springmvc/products/add?language=tr

Ilgili linke gidip default gelen degerleri de temizledikten sonra ekle dedigimizde ;

spring validation

Burada dikkat edecek olursak beklemedigimiz sekilde su hata mesajlarini da ekledi. Bunun nedeni unitPrice i double olarak , unitsInStock ‘u long olarak tanimladik. Dolayisiyla “” degeri numerik degere donusturulemez ve java.lang.NumberFormatException ‘a neden olmaktadir. Burada cozum olarak Spring MVC uygulamalarinda form modeli olarak kullanilan siniftaki property’leri String olarak tanimlayabiliriz validation sonrasinda ilgili model sinifina set edilebilir.

Failed to convert property value of type [java.lang.String] to required type [double] for property unitPrice; nested exception is java.lang.NumberFormatException: empty String
Failed to convert property value of type [java.lang.String] to required type [long] for property unitsInStock; nested exception is java.lang.NumberFormatException: For input string: ""

Bir diger cozum olarak springMessages dosyalarimiza ekstra mesajlar ekleyebiliriz.
typeMismatch.double ve typeMismatch.long gibi tanimlamalar Spring icin yukaridaki problemler ortaya ciktiginda kullanilacak ozel mesajlardir.
property’ler double ve long oldugu icin bu sekilde tanimliyoruz , eger int olsaydi typeMismatch.int olarak tanimlamamiz gereklidir.

springMessages_en.properties

typeMismatch.double=Invalid number entered
typeMismatch.long=Invalid number entered

springMessages_tr.properties

typeMismatch.double=Nümerik değer giriniz.
typeMismatch.long=Nümerik değer giriniz.

Tekrar test ettigimizde ;

spring validation2

web.xml

Ilgili konfigurasyon dosyamizi aktif edelim;

....
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>

<init-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
	<!-- 
	 /WEB-INF/01.appContext.xml			 
	 /WEB-INF/02.00.appContext.xml			
	-->		
	 /WEB-INF/11.validation.xml
	</param-value> 
 </init-param>

<load-on-startup>1</load-on-startup>
</servlet>
....

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. Required fields are marked *