October 31, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Integrating Advanced Spring Framework Features with Magnolia CMS

  • December 13, 2010
  • By Vikram Vaswani
  • Send Email »
  • More Articles »

Magnolia CMS, an open-source, enterprise-grade CMS written entirely in Java, has recently added Spring support, allowing Spring developers to easily extend the base CMS with custom functionality using their existing knowledge of the Spring Framework. In my previous article, Spring Framework and Magnolia CMS: Creating Complex Java-based Websites I introduced Blossom, the Magnolia CMS module for Spring, and illustrated how to use it to integrate Spring controllers and views into the Magnolia architecture.

The instructions in that tutorial were just the tip of the iceberg, however. With Blossom bridging the Spring Framework and Magnolia CMS, all manner of interesting Java-based Web development options become available. For example, Spring developers can validate form input, incorporate the Spring Form Tag Library, and create dialogs. In this tutorial, I dive into these more advanced examples.

Note: To learn the basics of Blossom, read my previous Spring Framework and Magnolia CMS article.

Validating Form Input with the Spring Framework and Magnolia CMS

A common requirement of complex Java-based websites is to apply custom validation to the input submitted through a Web form. With Magnolia's Spring support, this is a snap to implement because Spring already provides all the components needed for Web form input validation and error display.

The typical way to validate form input with Spring is to create a separate class that implements the Validator interface, and bind this to a POJO that represents the form input. If the form is created using Spring's form tab library, input errors detected by the validator class can be automatically displayed in the form using the tag. In case you've never done this before, take a look at this introductory material to understand the process before proceeding with the rest of this tutorial.

To begin, define a POJO with setter and getter methods for the form fields, as shown in the pizza design form below.

package info.magnolia.module.example;
/**
* Bean representing the pizza design form
*/
public class PizzaForm {
private String name;
private String email;
private String message;
private Integer size;
private String[] toppings;
private String crust;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}

public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}

public String getCrust() {
return crust;
}
public void setCrust(String crust) {
this.crust = crust;
}
public String[] getToppings() {
return toppings;
}
public void setToppings(String[] toppings) {
this.toppings = toppings;
}
}

Save this file as src/main/java/info/magnolia/module/example/PizzaForm.java.

Next, create a validator class that implements the Validator interface and contains the validation rules for your form, which will perform email address validation using regular expressions.

package info.magnolia.module.example;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* Validator for validating forms
*/
public class PizzaFormValidator implements Validator {
public boolean supports(Class clazz) {
return clazz.equals(PizzaForm.class);
}
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required", "Name is required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "required", "Email address is required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "message", "required", "Message is required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "crust", "required", "Crust type is required");
if (((PizzaForm)target).getToppings().length < 1) errors.rejectValue("toppings", "invalid", "At least one topping must be selected");
if (!isValidEmailAddress(((PizzaForm)target).getEmail())) errors.rejectValue("email", "invalid", "Email address is invalid");
}

public boolean isValidEmailAddress(String emailAddress){
String expression="^[\w\-]([\.\w])+[\w]+@([\w\-]+\.)+[A-Z]{2,4}$";
CharSequence inputStr = emailAddress;
Pattern pattern = Pattern.compile(expression,Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(inputStr);
return matcher.matches();
}
}

As explained in the Spring reference guide, this class implements the supports() and validate() methods of the Validator interface.

The validate() method is the real workhorse here; it uses various methods from the ValidationUtils class to validate and reject invalid form input. In particular, note the rejectIfEmptyOrWhitespace() method, which can be used to ensure that required fields are not empty, and the rejectValue() method, which can be used to reject fields that fail to satisfy specified criteria. The rejectValue() method is particularly handy for custom validation tasks, such as email address validation using regular expressions (as shown in the example above).

So now we have a validator and a POJO, all that's left is to link them together. To do this, update the PizzaFormParagraph object and bind the validator to the POJO, as shown below:

package info.magnolia.module.example;
import info.magnolia.module.blossom.annotation.Paragraph;
import info.magnolia.module.blossom.annotation.ParagraphDescription;
import info.magnolia.module.blossom.annotation.TabFactory;
import info.magnolia.module.blossom.dialog.TabBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import java.util.List;
import java.util.ArrayList;
import info.magnolia.cms.core.Content;
import info.magnolia.context.WebContext;
import info.magnolia.context.MgnlContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* Displays a pizza order form and a confirmation page after the form is submitted.
*/
@Controller
@Paragraph(value="Pizza Form", name="pizzaForm")
@ParagraphDescription("A form for users to order a pizza")
public class PizzaFormParagraph {
private static final String[] toppings = new String[] {"Cheese", "Tomato", "Onion", "Ham", "Bacon", "Anchovies"};
@RequestMapping("/pizza/new")

public String handleRequest(ModelMap model, @ModelAttribute PizzaForm pizzaForm, BindingResult result, HttpServletRequest request) {
Content content = MgnlContext.getWebContext().getAggregationState().getCurrentContent();
List x = new ArrayList();
for (String t : toppings) {
x.add(t);
model.addAttribute("availableToppings", x);
}
if ("POST".equals(request.getMethod())) {
new PizzaFormValidator().validate(pizzaForm, result);
if (result.hasErrors()) {
return "pizzaForm";
}
return "pizzaFormResult";
}
return "pizzaForm";
}

@TabFactory("Content")
public void contentTab(TabBuilder tab) {
tab.addStatic("This paragraph requires no configuration");
tab.addHidden("bogus", "");
}
}

Notice that the controller now specifies the list of toppings as an array, and makes this array available to the template script as an attribute named availableToppings. Why? Keep reading.


Tags: CMS, Spring, Magnolia

Originally published on http://www.developer.com.

Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel