Dealing with Ajax requests is quite simple when using the CAE together with Spring MVC features. The main difference of Ajax in comparison to "standard" request handling is the format of incoming and outgoing data. While standard requests typically provide an output format for end users such as HTML, Ajax requests mainly deal with machine readable formats like JSON and XML. The same applies to input formats: HTML based application have to deal with form input while Ajax request again make use of JSON/XML instead.
Spring MVC provides inbuilt converters for translating plain java beans ("POJOs") from/to XML or
JSON. These converters can be easily used from within the CAE. When implementing an Ajax based
handler, then no ModelAndView
needs to be passed to the view engine but it is
sufficient to provide the bean itself in conjunction with the @ResponseBody
annotation.
Example
@RequestMapping(value = "/json/{id}", produces="application/json") @ResponseBody public MyPojo renderBeanAsJson(@PathVariable("id") String id) { MyPojo bean = getPojo(id); return bean; }
In this example for an Ajax handler, a model bean is computed and simply returned as a "response
body" rather than wrapping it into a ModelAndView
. Due to the
produces="application/json"
attribute, the rendering engine knows that this bean
should be automatically converted to JSON. This is internally done by recursively writing a JSON
entry for all bean properties. When using produces="text/xml"
instead, then the
bean will be converted to XML as long as the bean's class is annotated with
@javax.xml.bind.annotation.XmlRootElement
.
The automatic conversion is done by instances of
org.springframework.http.converter.HttpMessageConverters
that need to be registered
before usage:
<customize:append id="registerHttpMessageConverters" bean="httpMessageConverters"> <list> <!-- converts request/response bodies from/to XML --> <bean class="org.springframework.http.converter.xml. Jaxb2RootElementHttpMessageConverter"/> <!-- converts request/response bodies from/to JSON --> <bean class="org.springframework.http.converter.json. MappingJacksonHttpMessageConverter"/> </list> </customize:append>
The JSON converter MappingJacksonHttpMessageConverter
requires the library
jackson-mapper-asl
which can be added to a Maven project like
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> </dependency>
Handling POST Data
Writing a handler that handles incoming data (typically sent with a HTTP POST request and
formatted as JSON or XML) can be implemented nearly the same way. The only thing that has to be
done is to pass an @RequestBody
annotated parameter to the handler method like
@RequestMapping(value="/json/{id}", method=RequestMethod.POST, consumes="application/json", produces="application/json") @ResponseBody public MyResultPojo renderBeanAsJson( @PathVariable("id") String id, @RequestBody MyIncomingPojo data) { MyResultPojo bean = processData(id, data); return bean; }
Building Links
Implementing and buildings links for Ajax handlers works the same way as for all other resources. An example link scheme implementation:
@Link(type=MyPojo.class, view="json", uri="/json/{id}") public UriComponents buildJsonLink(MyPojo bean, UriComponentsBuilder uri) { return uri.buildAndExpand(bean.getId()); }
A JavaScript snippet that can be embedded into a JSP might look like
<cm:link target="${myPojo}" view="json" var="pojoUrl"/> <script type="text/javascript"> var req = new XMLHttpRequest(); req.open('GET', '${pojoUrl}', true); req.onreadystatechange = function() { // handle response ... }; req.send(); </script>