While working with one of my application, I had a simple requirement to grab customer data as they key-in their customer Id. First thought which came to my mind was to simply use AJAX however in the past we had to write lot of stuff and workarounds to make it work.
However, Spring 3.0 now officially support AJAX remoting with JSON as discussed in Keith Donald's article.
So, after reading this article the first step was to get jQuery and JSON javascript files which can be downloaded from their sites. This was easy!
Next, write the javascript code in the JSP page which activates on users input (to be specific on key up event). Here is how I did it:
First I veified that jQuery actually works on my page after adding following lines:
<script type="text/javascript" src="/travel-request/resources/js/jquery-1.4.min.js"></script>
<script type="text/javascript" src="/travel-request/resources/js/json.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
console.log("Welcome to jQuery.");
});
</script>
With the help of Firebug in FireFox I was able to verify using jQuery logging facility that it works!
So, half the job was done. Now comes the interesting part i.e. making an AJAX call to my customer information service and getting the response. Here is what I did:
Capture key up event and ignore any characters other than numbers i.e. 0-9
$('#customerId').keyup(function(event) {
var val = $(this).val();
var regex = /[a-zA-Z\!@#%&()+{}?*+.^$ ]/g;
if(val.match(regex)) {
val = val.replace(regex, "");
$(this).val(val);
}
if($('#customerId').val().length > 9 || $('#customerId').val().length == 8)
clearCustomerData();
else if ($('#customerId').val().length == 9) {
userid_length = $('#customerId').val().length;
if (userid_length > 9){
console.log('customer Id must be 9 numbers only...')
}else
{
getCustomerData();
}
}
});
Next define implementation for getCustomerData() and clearCustomerData() functions which makes an AJAX call:
function getCustomerData() {
$.getJSON("/customer/getInfo", { customerId: $('#customerId').val() }, function(customerAvailable) {
if(customerAvailable.available) {
$('#customerFirstName').val("customerAvailable.firstName");
$('#customerMiddleName').val("customerAvailable.middleName");
$('#customerLastName').val("customerAvailable.lastName");
});
}
function clearCustomerData(){
$('#customerFirstName').val("");
$('#customerMiddleName').val("");
$('#customerLastName').val("");
}
NOTE: $('#customerFirstName') above is linking the html label in the form.
At last, write a service using Spring magic which takes care of the rest as follows in your controller:
@RequestMapping(value="/customer/getInfo", method=RequestMethod.GET)
public @ResponseBody CustomerAvailable getCustomerName(@RequestParam String customerId){
CustomerAvailable customer = new CustomerAvailable();
customer.setAvailable(true);
Map<String,String> customerData = new HashMap<String,String>();
customerData.put("firstName", "FIRSTNAME");
customerData.put("middleName", "M");
customerData.put("lastName", "LASTNAME");
return customer;
}
Done! But, before I go don't forget to take a look at JSON formatter this is a nice tool to format unstructured JSON response and make it readable. I've added a link to this tool in references.
References:
https://src.springframework.org/svn/spring-samples/mvc-ajax/
http://blog.springsource.com/2010/01/25/ajax-simplifications-in-spring-3-0/
http://api.jquery.com/jQuery.getJSON/
http://ajaxian.com/archives/jquery-logging
http://stackoverflow.com/questions/3403574/no-results-message-on-jquery-autocomplete
http://stackoverflow.com/questions/2866108/jquery-keyup-illegal-characters
http://jetlogs.org/2007/09/14/jquery-textbox-validation-and-the-blur-event/
http://jsonformatter.curiousconcept.com/
Wednesday, May 25, 2011
Using AJAX with Spring MVC 3.x
Labels:
AJAX,
integrate,
javascript,
jQuery,
JSON,
json formatter,
jsonformatter,
jsp,
Spring,
Spring 3.x,
Spring MVC
Tuesday, May 24, 2011
Binding Boolean properties in Spring MVC forms
While designing Spring MVC forms you might often encounter bind errors such as follows:
Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property 'updateStamp'; nested exception is java.lang.IllegalArgumentException:xxxxxx
Usually these errors are the result of Spring not being able to bind java primitive Wrapper classes like Integer, Boolean, etc. or user defined types such as Customer, to <form:input> or other form fields.
However, this issue can be resolved simply by registering custom property editors with your spring controller. Spring by defaults provides you with set of built-in property editors, that you can use in your controller. For user defined types, you must create your own.
As you know, Spring 3.x makes writing your controller a lot easier and here is how you register customer property editor within your controller:
In the example below, I've added built in property editors for Date, String, and Boolean.
One important note: In some cases specifically for Boolean properties you may encounter following error even after you have registered custom property editor for it.
org.springframework.beans.NotReadablePropertyException: Invalid property 'newCustomer' of bean class [org.sample.domain.customer.Customer]: Bean property 'newCustomer' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
This error is coming from your Customer domain object. Most likely, newCustomer property is defined as follows:
If you change the method name from isNewCustomer() to getNewCustomer() the above mentioned error will disappear. This is because a standard java bean convention is to use set/get for property methods.
Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property 'updateStamp'; nested exception is java.lang.IllegalArgumentException:xxxxxx
Usually these errors are the result of Spring not being able to bind java primitive Wrapper classes like Integer, Boolean, etc. or user defined types such as Customer, to <form:input> or other form fields.
However, this issue can be resolved simply by registering custom property editors with your spring controller. Spring by defaults provides you with set of built-in property editors, that you can use in your controller. For user defined types, you must create your own.
As you know, Spring 3.x makes writing your controller a lot easier and here is how you register customer property editor within your controller:
In the example below, I've added built in property editors for Date, String, and Boolean.
@InitBinder
public void setPropertyBinder(WebDataBinder dataBinder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
dateFormat.setLenient(false);
dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
dataBinder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
dataBinder.registerCustomEditor(Boolean.class, new CustomBooleanEditor(false));
}
One important note: In some cases specifically for Boolean properties you may encounter following error even after you have registered custom property editor for it.
org.springframework.beans.NotReadablePropertyException: Invalid property 'newCustomer' of bean class [org.sample.domain.customer.Customer]: Bean property 'newCustomer' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
This error is coming from your Customer domain object. Most likely, newCustomer property is defined as follows:
public class Customer {
private Boolean newCustomer;
public Boolean getNewCustomer() {
return newCustomer;
}
public void isNewCustomer(Boolean newCustomer) {
this.newCustomer = newCustomer;
}
}
If you change the method name from isNewCustomer() to getNewCustomer() the above mentioned error will disappear. This is because a standard java bean convention is to use set/get for property methods.
Thursday, May 19, 2011
Securing Java Applications with Spring Security
Since there are so many post dedicated to the subject of this post. I will be collecting the articles and posting here as and when I come across them.
Java Web Application Security - Part I: Java EE 6 Login Demo
Java Web Application Security - Part II: Spring Security Login Demo
Java Web Application Security - Part I: Java EE 6 Login Demo
Java Web Application Security - Part II: Spring Security Login Demo
Friday, April 29, 2011
Using SQL IN clause with Prepared Statement
Using IN clause in prepared statements is not straight forward fortunately, there is a hack available for this scenario.
Example: Get list of customers who are in east cost states.
SQL could be: SELECT * FROM CUSTOMERS WHERE CUST_STATUS='ACTIVE' AND STATE IN('NJ','NY','MA','NH')
prepared statement - "SELECT * FROM CUSTOMERS WHERE CUST_STATUS=? AND STATE IN (LIST_STATES)"
List queryForList = jdbcTemplate.queryForList(
StringUtils.replace(sqlString, "LIST_STATES",
("'"+ StringUtils.replace(functions,",", "','") + "'")),new Object[] {});
Example: Get list of customers who are in east cost states.
SQL could be: SELECT * FROM CUSTOMERS WHERE CUST_STATUS='ACTIVE' AND STATE IN('NJ','NY','MA','NH')
prepared statement - "SELECT * FROM CUSTOMERS WHERE CUST_STATUS=? AND STATE IN (LIST_STATES)"
List queryForList = jdbcTemplate.queryForList(
StringUtils.replace(sqlString, "LIST_STATES",
("'"+ StringUtils.replace(functions,",", "','") + "'")),new Object[] {});
Tuesday, April 26, 2011
Configuring Tomcat to Use JNDI based Oracle Datasource
In this post, I will talk about configuring a JNDI based datasource (Oracle) on Tomcat server which is a common way to access your backend.
1. Copy required Oracle driver jar files to
3. Add data source resource link in
1. Copy required Oracle driver jar files to
$CATALINA_HOME/common/lib
2. Define your data source in Context
$CATALINA_HOME/conf/server.xml
<!-- Global JNDI resources --> <GlobalNamingResources> <Resource name="jdbc/myoracle" auth="Container" type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver" url="jdbc:oracle:thin:@127.0.0.1:1521:mysid" username="scott" password="tiger" maxActive="20"
maxIdle="10" maxWait="-1"/> </GlobalNamingResources>
3. Add data source resource link in
$CATALINA_HOME/conf/context.xml
<Context>
<Resource global="jdbc/myoracle" name="jdbc/myoracle"
type="javax.sql.DataSource"/>
</Context>
That's it, now you are ready to use data source configured above
from your application deployed on tomcat.
Subscribe to:
Posts (Atom)