Saturday, May 11, 2013

Spring MVC - FlashAttributes

One of the common problem in a web based application, involving form submission is mutilple form submission, re-entering submitting the form on browser refresh, pop-up alert asking for re-submission of the form, if we press the back button. To overcome the above problem, we will be doing a redirect after a form submission instead of the forward. Doing a redirect causes the browser to do a new GET request and load the page, and provides a solution to the above mentioned problem, but comes with one serious problem, where we will be missing the vital data of request parameters and attributes.

To overcome this problem, Spring MVC comes with FlasAttributes. Flash attributes provide a way for one request to store attributes intended for use in another. This is most commonly needed when redirecting — for example, the Post/Redirect/Get pattern. Flash attributes are saved temporarily before the redirect (typically in the session) to be made available to the request after the redirect and removed immediately.

Spring MVC has two main abstractions in support of flash attributes. FlashMap is used to hold flash attributes while FlashMapManager is used to store, retrieve, and manage FlashMap instances.

Flash attribute support is always "on" and does not need to enabled explicitly although if not used, it never causes HTTP session creation. On each request there is an "input" FlashMap with attributes passed from a previous request (if any) and an "output" FlashMap with attributes to save for a subsequent request. Both FlashMap instances are accessible from anywhere in Spring MVC through static methods in RequestContextUtils.

Here in the below sample code, we are adding the expense details to the DB and redirecting back to the form, with the message saying the following expense have been added to the list.




Flash attributes added via RedirectAttributes are automatically propagated to the "output" FlashMap. Here we have added RedirectAttributes redirectAttrs to your Spring controller’s method addExpense. The addFlashAttribute method automatically add the given parameter to the output flash map and pass it to the subsequent requests.

Before your handler method will be called, Spring Framework will populate the Model with the available Flash Attributes – at this point value passed from addExpense will become a model attribute for the expenselist method, and the same can be added to the map, to return it to the presentation layer, to get it displayed. Here the from the redirect,it comes to the expenselist method, where it will reach as a ModelAttribute and the same have been defined in the method signature with the respective type.

@RequestMapping("/expenselist")
public String expenselist(Map map, @ModelAttribute("ExpenseName") String expenseName)
{
 List expenseTypeList = expenseTypeService.fetchAll();
 
 map.put("expense", new Expense()); 
 map.put("expenseTypeList", expenseTypeList);
 map.put("expenseList", expenseService.fetchAll()); 
 map.put("expenseName", expenseName);
 return "expenselist";
}

@RequestMapping(value="/addexpense", method=RequestMethod.POST)
public String addExpense(@ModelAttribute("expense") 
  Expense expense, BindingResult result, RedirectAttributes redirectAttrs)
{
 //System.out.println(expense.getExpenseTypeId());
 //System.out.println(expense.getName());
 expenseService.add(expense);
 redirectAttrs.addFlashAttribute("ExpenseName", expense.getName());
 return "redirect:/expenselist.html";
}

Happy Programming...!!!

Saturday, May 4, 2013

Integrate ExtJs DataGrid with Spring MVC

Sencha ExtJs is one of the rapidly growing standard for business-grade web application development, which have been used widely as presentation layer. Lets see, how we can intergrate the ExtJs with Spring MVC.

You can download ExtJs from here - Download Extjs

In this example, we are going to populate the list of medicine name available in ExtJS DataGrid.

Below is the Medicine Business clas, Simple POJO. For this example forget about the dealers in the class.
public class Medicine extends BaseObject 
{ 
 private String company;
 private String code;
 private String description; 
 private Set dealers;

        //Relevant Setters and Getters

}

Since the JSON is the most popular way of providing input to ExtJs DataGrid, we are going define the DataStore first, which reads the data from the server through the HttpProxy call, and we use the JsonReader to read a server response that is sent back in JSON format

var store = new Ext.data.Store({
  proxy: new Ext.data.HttpProxy({
   url: '/getmedicine.htm'
  }),
  reader: new Ext.data.JsonReader({
   root:'medicineJson'
  },
  [{name: 'id'}, 
   {name: 'name'}, 
   {name: 'description'},
   {name: 'company'}
  ])
 }); 

And our controller, which return the relevant Medicine data in JSON Format. To return the output from the controller in JSON format, we will be using the classes net.sf api's. Make sure that you have the below jars files in your classpath

json-lib-2.4-jdk15.jar
json-lib-ext-spring-1.0.2.jar
ezmorph-0.8.1.jar

public class DataServiceController implements Controller
{
 private MedicineDao medicineDao;
 
 
 public MedicineDao getMedicineDao() {
  return medicineDao;
 }

 public void setMedicineDao(MedicineDao medicineDao) {
  this.medicineDao = medicineDao;
 }

 public ModelAndView handleRequest(HttpServletRequest request,
   HttpServletResponse response) throws Exception 
 {
  List medicineList = this.getMedicineDao().getAll();
  
  JsonConfig config = new JsonConfig();
  config.setExcludes(new String[] {"dealers" });
  config.setIgnoreDefaultExcludes(false);
  config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
  
  //JSONObject obj = JSONObject.fromObject(medicineList, config);
  JSONArray obj = JSONArray.fromObject(medicineList, config);
  
  ModelMap modelMap = new ModelMap();
  //modelMap.addAttribute("medicineList" , obj);  
  //return new ModelAndView("jsonView", modelMap);
  modelMap.addAttribute("medicineJson", obj);
  //modelMap.addAttribute("medicineList" , medicineList);
  return new ModelAndView("jsonView", modelMap);
 }

}

Below is the entire content of medicinelist.js file defined in jsp, which includes the definition of the DataGrid.

Ext.onReady(function(){ 

 var store = new Ext.data.Store({
  proxy: new Ext.data.HttpProxy({
   url: '/getmedicine.htm'
  }),
  reader: new Ext.data.JsonReader({
   root:'medicineJson'
  },
  [{name: 'id'}, 
   {name: 'name'}, 
   {name: 'description'},
   {name: 'company'}
  ])
 }); 

 // row expander
  
    
    var gridBooks = new Ext.grid.GridPanel({
        store: store,
        width: 500,
        height: 500,        
        title: 'Medicine List',
        renderTo: 'medlist',
        cm: new Ext.grid.ColumnModel({
            defaults: {
                sortable: true
            },
            columns: [               
                {header: "Id", dataIndex: 'id'},
                {header: "Medicine Name", dataIndex: 'name'},
                {header: "Description", dataIndex: 'description'},
                {header: "Company" , dataIndex: 'company', renderer:renderCompany}
            ]
        }),       
        listeners: {
      rowClick: function(grid, rowI, event) {
       //alert("You Clicked Row " + rowI);
       //alert("Medicine Name" + grid.getStore().getAt(rowI).get('name'));
      }
     }
    });

    store.load();
});

Make sure that you have relevant extjs .js and .css file in your relevant, which can be downloaded from You can download ExtJs from here - Download Extjs










Happy programming ...!!!

Saturday, April 13, 2013

Spring Tiles Integration

Suppose if your web page has a standard header, footer and only center content will be changed, it is very difficult to hardcode in each and every webpage and if later if any changes is needed then all pages needs to be updated with the relevant details. Here comes Tiles which helps you to templatize the common items and include it in each and every page.

Lets see how we are going to integrate the Titles in our Spring MVC. Our application layout will have the standard header and footer across all web pages, where only the center content will be changed.

Make sure that you have the following jars files included in your lib

commons.beanutils.jar
commons-digester-2.1.jar
commons-logging-1.1.jar
tiles-api-2.0.4.jar
tiles-core-2.0.4.jar
tiles-jsp-2.0.4.jar

Configuring titles framework in Spring MVC

 
    
    


   
       
          /WEB-INF/tiles-def.xml
        
   
	

Using the definitions attribute, we need to specify the tiles definition file. The tiles-def.xml definitions are below, the file should be located under WEB-INF directory in your application. In the tiles-def.xml we need to define our base layout structure. The base layout we are building contatins the attributes title, header, body and footer. We need to create the baseLayout.jsp and place it under /WEB-INF/titles, the template baseLayout.jsp, will contain the different segments of a web page, header, body and footer.


   
      
          
      
      		
   
   
      
      			
   	
   
      	
      	
   	


BaseLayout.jsp - View Template
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
..
..
<tiles:insertAttribute name="title" ignore="true"/>






..

To display the views, we use the ResourceBundleViewResolver. By default the view.properties will be used to store
the key value pairs

hello.(class)=org.springframework.web.servlet.view.tiles2.TilesView
hello.url=base

dealerlist.(class)=org.springframework.web.servlet.view.tiles2.TilesView
dealerlist.url=dealer

Controller File
ModelMap modelMap = new ModelMap();
modelMap.addAttribute("dealerList" , dealerList);		
return new ModelAndView("dealerlist", modelMap);

The base, delear in view.properties refers to the definition name in the tiles-def.xml file. The hello and dealerlist refers to the modelview name sent by your controller.

That's all you have integrated the Tiles with Spring MVC

Happy Programming...!!!

Thursday, April 4, 2013

Spring MVC - Bind an input field to a Date property

For request parameters representing string, number, and boolean values, the Spring MVC container can bind them to typed properties out of the box. Suppose you have the Date Input field, and the bean property is defined as Date Type, when container tries to bind it will throw exception

Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date'

So we need to create a binding between your input field and your bean's Date property. Spring provides a PropertyEditor named CustomDateEditor which you can configure to convert an String to respective date format. You typically have to register it in a @InitBinder method of your controller

@InitBinder
public void initBinder(WebDataBinder binder)
{
    //binder.registerCustomEditor(ExpenseType.class, new ExpenseTypePropertyEditor());
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    dateFormat.setLenient(false);
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}

Happy Programming..!!!

Saturday, March 23, 2013

Eclipse Maven Build Fail - use -source 5 or higher to enable annotations

When you are using Maven package option in eclipse for generating a war file of a java web project which has the annotation in it,you will encounter the Build Fail error, below is the sample error which you will encounter, if the JRE and Annotation compiler wasn't configured properly in Eclipse
FAILED for project: 
    ExpenseReporting:ExpenseReporting:war:0.0.1-SNAPSHOT
Reason:
C:\Documents and Settings\MRamanujam\workspace\ExpenseReporting\src\main\java\com\expense\domain\Base.java:[9,2] annotations are not supported in -source 1.3
(use -source 5 or higher to enable annotations)
 @Id
To resolve the issue first you need to make sure that, Java compiler version you are using is greater than 5

javac -version

Next go to your project properties, select the Java Compiler in the tree menu.

Make sure the Compiler Compliance level is more than 1.5

Next click Annotation Processing and enable project specific settings, and apply the settings.


Then do the Maven package, your build will be successful, and the war wil be generated.

Happy Programming...!!!

Friday, March 1, 2013

Different ways of accessing a Zend View Helper

A Zend View Helper is simply a class, which follows a certain convention.When attached to a view object, you can call the helper as if it were a method of the view object itself. The View object retains helper instances,which means that they retain states between calls.
By convention we should use these view helpers in the View Layer only, but there are some circumstances we end up breaking this convention, start using these helpers in Controller, Helpers and Models. Lets see, how we can access the View Helpers from the differnt parts
//In Action Controller, you can access the view helper like below
$this->view->helpername();
or
$this->view->getHelper('helpername');

//In Action Helper, you can access the view helper like below
$view = $this->getActionController()->view;
$view->helpername();

//Suppose if you are in the Model, where you don't have any 
//reference to Zend, this is how you have to access
$viewObject = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer')->view;
$viewObject->helpername();


Happy Programming ...!!!

Sunday, January 27, 2013

InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode

If you have enabled the filter OpenSessionInViewFilter, for fetching the lazily loaded data, you can typically see the below error message, when trying to do a persistence operation outside of Spring-managed transaction.

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1186)
org.springframework.orm.hibernate3.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:696)
org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:694)

OpenSessionInViewFilter has an alternative "deferred close mode", to resolve the issue. This can be activated through setting the singleSession=false. This will use one Session per transaction, but keep each of those open until view rendering has been completed. As no Session will be reused for another transaction in this case, there is no risk of accidentally flushing inconsistent state


  OpenSessionInViewFilter
  org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
  
     singleSession     false  


Happy Programming !!!