tag:blogger.com,1999:blog-33955136926502311762024-02-08T03:14:34.345-08:00Learn something new and exciting in the world of technologyGagan Agrawalhttp://www.blogger.com/profile/02864388407613125097noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-3395513692650231176.post-9749164235159348482012-05-09T09:12:00.000-07:002012-05-14T21:33:07.113-07:00Grails : Rest Service with JAXB parsing - PART 2<div dir="ltr" style="text-align: left;" trbidi="on">
In my <a href="http://agrawalgagan.blogspot.in/2012/05/grails-rest-service-with-jaxb-parsing.html" target="_blank">last </a>post on Rest Service with JAXB parsing, I showed a very basic example of developing REST Service with Grails Controller and JAXB. In this blog I am going to cover little more advanced features and will mainly be covering following. <br />
<ul style="text-align: left;">
<li>Collection mapping in JAXB </li>
<li>Exception Handling</li>
<li>Returning response in XML</li>
<li>URLMappings for Grails Controller</li>
</ul>
<br />
<a name='more'></a><br />
<ul style="text-align: left;">
</ul>
The input XML that will be sent to REST Service is as follows. It's about storing order details via REST Service.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><?xml version="1.0" encoding="utf-8"?>
<Order_Details>
<order_number>1234</order_number>
<customer_name>XYZ</customer_name>
<items>
<item>
<name>Item1</name>
<quantity>4</quantity>
</item>
<item>
<name>Item2</name>
<quantity>2</quantity>
</item>
</items>
</Order_Details>
</code></pre>
<br />
Let's create domain class representing this XML. We have two domain classes here -<br />
Order - For storing Order Details<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>import javax.xml.bind.annotation.XmlRootElement
import javax.xml.bind.annotation.XmlElement
import javax.xml.bind.annotation.XmlElementWrapper
import javax.xml.bind.annotation.XmlAccessorType
import javax.xml.bind.annotation.XmlAccessType
@XmlRootElement(name="Order_Details")
@XmlAccessorType(XmlAccessType.FIELD)
class Order {
@XmlElement(name="order_number")
int orderNumber
@XmlElement(name="customer_name")
String custName
@XmlElementWrapper(name="items")
@XmlElement(name="item")
List<Item> items = new ArrayList<Item>()
}
</code></pre>
<br />
Item - For storing individual Item details<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>@XmlRootElement(name="item")
@XmlAccessorType(XmlAccessType.FIELD)
class Item {
String name
int quantity
}
</code></pre>
<br />
Let's first discuss about annotations in Order and Item classes.<br />
<ul style="text-align: left;">
<li>@XmlRootElement has been used to map classes with their respective XML elements. e.g Order class has name "Order_Details" which maps directly to root element of XML.</li>
<li>@XmlAccessorType is must for Groovy classes. Through this we tell JAXB parser to apply xml bindings at field level. If not defined, there is bright chance of getting exception related to metaClass since JAXB tries to do mapping for metaClass property.</li>
<li>@XmlElement annotation is used to map class property with XML element. e.g. In Order class, property orderNumber has been mapped with it's xml node via @XmlElement(name="order_number"). However there is no such annotation in Item class. That's because if no annotation has been applied, then element name is assumed to be same that of property name.</li>
<li>@XmlElementWrapper annotation is used to wrap collection of elements inside an element. In this case, "item" elements are wrapped inside "items" element.</li>
</ul>
So that was all about annotation for JAXB bindings. We also need to send back response in XML format. Again for this we will use JAXB. So let's create a class representing REST Service response and then we will convert instance of this class in XML using JAXB.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>@XmlRootElement(name="Order_Response")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = ['status','errorCode','errorMessage'])
class OrderResponse {
String status
String errorCode
String errorMessage
}
</code></pre>
<br />
So our response will have three elements.<br />
<ul style="text-align: left;">
<li>Status - SUCCESS/ERROR</li>
<li>ErrorCode - Error Code in case status is ERROR</li>
<li>ErrorMessage - Error Message corresponding to ErrorCode</li>
</ul>
So now it's time to write controller which will be exposed as a REST Service<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>class OrderRestController {
def messageSource
def save = {
String responseXml
try{
String xml = request.inputStream.text
Order order = XmlUtil.unMarshal(xml, Order.class)
println "items..${order.items*.quantity}"
order.save()
responseXml = XmlUtil.marshal(new OrderResponse(status: "SUCCESS"))
}catch(Exception e){
log.error("An error occurred while saving order details : $e")
String errorCode = "order.save.error"
OrderResponse orderResponse = new OrderResponse(status : "ERROR", errorCode: errorCode,
errorMessage: messageSource.getMessage(errorCode,null,"",Locale.ENGLISH))
responseXml = XmlUtil.marshal(orderResponse)
}
render (text : responseXml, contentType: "text/xml", encoding: "UTF-8")
}
}
</code></pre>
<br />
Here the save method of OrderRestController will be exposed as REST Service. We will see how to map this to a URL via URLMappings file in Grails. But for now just assume this method is exposed as a service. So first thing we do in this method is to get request XML in String format via "request.inputStream.text". Then we ask XMLUtil to convert this XML to Order object via it's unMarshal method. We have wrapped the logic of converting XML to Object in XMLUtil since there is some amount of boiler plate code which would be required to be written for every conversion. So it's generally good idea to move this logic in separate Utility file.(XmlUtil in this case).<br />
<br />
XmlUtil Class<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>class XmlUtil {
static String marshal(def source){
StringWriter writer = new StringWriter()
JAXBContext context = JAXBContext.newInstance(source.class)
Marshaller marshaller = context.createMarshaller()
marshaller.marshal(source, writer)
return writer.toString()
}
static def unMarshal(String strXml, Class targetClass){
JAXBContext context = JAXBContext.newInstance(targetClass)
def unMarshaller = context.createUnmarshaller()
return unMarshaller.unmarshal(new StringReader(strXml))
}
}
</code></pre>
<br />
Once we have got Order object from request XML, we can perform any business validation if required or can directly save in database. Once done, a success message needs to be sent back. For this we create OrderResponse object and set status as "SUCCESS". Then we again ask XmlUtil to convert this object in XML String via marshal method. After we have received XML String, we render it as XML by setting contentType : "text/xml".<br />
<br />
In case of any exception during XML parsing or performing business validation rules or saving Order instance in DB, catch block in OrderRestController will be executed. In this, we create OrderResponse object with status as "ERROR" and populate required errorCode and errorMessage fields. This instance is again converted into XML by XmlUtil.marshal method and rendered back.<br />
<br />
Sample success response XML<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order_Response>
<status>SUCCESS</status>
</Order_Response>
</code></pre>
<br />
Sample error response XML<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order_Response>
<status>FAILURE</status>
<errorCode>rawResponseData.batchId.blank</errorCode>
<errorMessage>Batch ID is mandatory</errorMessage>
</Order_Response>
</code></pre>
<br />
Finally we need to provide URL Mapping for OrderRestController. Under normal circumstances Grails convention URL i.e. http://<server>/<appName>/<controller>/<action> should suffice. But there is a chance that all REST services are grouped together and exposed under custom URL, something like http://<server>/<appName>/rest/ServiceName/action. For such customization we need to edit URLMappings.groovy placed under grails-app/conf. Following configuration should do the trick.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>class UrlMappings {
static mappings = {
"/rest/OrderService/$action" (controller : "orderRest"){
}
}
}
</code></pre>
<br />
So OrderService is now exposed at<br />
http://localhost:8080/RestExample/rest/OrderService/save<br />
<br />
So this was all about exposing OrderController as REST Service via JAXB and Grails Controller. Do let me know if you have any queries or comments.</div>Gagan Agrawalhttp://www.blogger.com/profile/02864388407613125097noreply@blogger.com0tag:blogger.com,1999:blog-3395513692650231176.post-22424741638121260852012-05-04T08:00:00.001-07:002012-05-14T21:34:01.525-07:00Grails : Rest Service with JAXB parsing - PART 1<div dir="ltr" style="text-align: left;" trbidi="on">
In this blog I will show how RESTful Web Service can be developed in Grails without the use of any plugins. I will just make use of Grails Controller and JAXB parser to marshal/unmarshal xml.I have divided this into 2 parts blog series. In this blog I will cover very basic usage. In <a href="http://agrawalgagan.blogspot.in/2012/05/grails-rest-service-with-jaxb-parsing_09.html" target="_blank">next </a>blog it will be little more advanced with Exception handling.<br />
<br />
So let's develop a REST service to create Employee Details. Suppose we have a xml in following format which represents Employee Details.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><?xml version="1.0" encoding="utf-8"?>
<Employee_Details>
<employee_name>Gagan</employee_name>
<employee_age>28</employee_age>
<employee_department>SOFTWARE</employee_department>
</Employee_Details
</code></pre>
<br />
<br />
<a name='more'></a><br /><br />
Suppose we created a Grails Project with name "RestExample". We then create following domain class which represents Employee details. <br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>class Employee {
String name
int age
String department
}
</code></pre>
<br />
I have intentionally kept Employee properties different than xml
elements so that we can see how they can be mapped via JAXB bindings.<br />
<br />
So let's now bind xml elements to Employee domain class properties with @XmlRootElement and @XmlElement annotations.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>import javax.xml.bind.annotation.XmlRootElement
import javax.xml.bind.annotation.XmlElement
@XmlRootElement(name="Employee_Details")
@XmlAccessorType(XmlAccessType.FIELD)
class Employee {
@XmlElement(name="employee_name")
String name
@XmlElement(name="employee_age")
int age
@XmlElement(name="employee_department")
String department
}
</code></pre>
<br />
Let's now create Grails Controller which will be exposed as REST Web Service.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>import javax.xml.bind.JAXBContext
import javax.xml.bind.Unmarshaller
class EmployeeController {
def create = {
def xmlStream = request.inputStream
JAXBContext context = JAXBContext.newInstance(Employee.class)
Unmarshaller unmarshaller = context.createUnmarshaller()
Employee employee = unmarshaller.unmarshal(xmlStream)
employee.save()
render "success"
}
}
</code></pre>
<br />
Here we get the xml from input stream. Then we pass this stream to JAXB api and get Employee object back. No need to do manual XML transformations.<br />
<br />
That's it. We can now hit the service at URL http://localhost:8080/restExample/employee/create and send Employee Details XML in request. In response we will get "success" message and Employee details will be saved in database.<br />
<br />
<a href="http://agrawalgagan.blogspot.in/2012/05/grails-rest-service-with-jaxb-parsing_09.html" target="_blank">Part-2</a> of this series covers more advance usage. Click <a href="http://agrawalgagan.blogspot.in/2012/05/grails-rest-service-with-jaxb-parsing_09.html" target="_blank">here</a> to read Part-2 of the blog.<br />
<br /></div>Gagan Agrawalhttp://www.blogger.com/profile/02864388407613125097noreply@blogger.com1tag:blogger.com,1999:blog-3395513692650231176.post-84981000309358243462012-04-10T02:27:00.001-07:002012-04-10T02:28:32.849-07:00Inheritance in Static Language vs Dynamic Language<div dir="ltr" style="text-align: left;" trbidi="on">
Click <a href="http://xebee.xebia.in/2012/04/09/inheritance-in-static-language-vs-dynamic-language/" target="_blank">here</a> to view the <a href="http://xebee.xebia.in/2012/04/09/inheritance-in-static-language-vs-dynamic-language/" target="_blank">blog</a>.</div>Gagan Agrawalhttp://www.blogger.com/profile/02864388407613125097noreply@blogger.com0tag:blogger.com,1999:blog-3395513692650231176.post-50574112147580504522012-02-20T08:40:00.000-08:002012-02-20T08:55:06.429-08:00Do not use static imports in Groovy/Grails<div dir="ltr" style="text-align: left;" trbidi="on">
As per Groovy's <a href="http://groovy.codehaus.org/Static+Import+Usage" target="_blank">documentation</a>, static import is supported and can be used as in java. However static import usage in Groovy can lead to unpredictable issues. I have been happily using static imports for some time until today when I found very strange issue. Let me demonstrate it with an example of what issue I am talking about.<br />
<a name='more'></a><br />
<br />
Suppose we have a DateUtil class as mentioned below with some utility methods for playing with dates.<br />
<br />
<pre style="background-color: #eeeeee; border-bottom-color: rgb(153, 153, 153); border-bottom-style: dashed; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(153, 153, 153); border-left-style: dashed; border-left-width: 1px; border-right-color: rgb(153, 153, 153); border-right-style: dashed; border-right-width: 1px; border-top-color: rgb(153, 153, 153); border-top-style: dashed; border-top-width: 1px; font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px; width: 100%;"><code>package com.test.util
class DateUtil{
private static final <b><span style="color: red;">log </span></b>= LogFactory.getLog(this)
static Date parse(String format, String strDate){
Date date = null
try {
date = Date.parse(format, strDate)
} catch (Exception e) {
}
date
}
}
</code></pre>
<br />
For the sake of simplicity to understand the actual problem, I have not added many methods in DateUtil class and have added just one i.e parse, which parses the given date in String format to actual Date object as per supplied format. I have intentionally marked <span style="color: red;"><b>log </b></span>variable above with red color since the problem I am going to mention is related to this variable.<br />
<br />
Now suppose we have another class UserService as mentioned below<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>package com.test.service
import static com.test.util.DateUtil.*
class UserService{
def searchUsersCreatedAfter(String strDate){
log.info("Searching for users created after : ${strDate}")
Date date = parse("MM/DD/YYYY",strDate)
Users.findAllByCreatedDateGreaterThan(date)
}
}
</code></pre>
<br />
UserService is a Grails Service class and hence will have all the required dependencies auto injected. One of the variables that all service classes in Gails have access to is "<b><span style="color: red;">log</span></b>". So as per this understanding we have written a method in UserService "searchUsersCreatedAfter" which finds all users which were created after the supplied date. This method accepts date in String format, and depends on DateUtils parse method to convert date from String to Date object. As can be seen in UserService, we have statically imported DateUtil's static methods and so we no longer need to prefix DateUtil while using it's static methods.<br />
<br />
Now if "searchUserCreatedAfter" method is called from outside and given a date say "01/01/2012", it should work fine and should return results as expected. So what's the problem? Well problem is in "<b><span style="color: red;">log</span></b>" variable. If you look into log file and locate for log statement "<span style="color: blue;">Searching for users created after : 01/01/2012</span>", you will be shocked to see prefix "<span style="color: blue;">com.test.util.DateUtil</span>" instead of "<span style="color: blue;">com.test.service.UserService</span>" before the log statement. You must be wondering how come is that possible. "searchUsersCreatedAfter" method is written in UserService, so how come logs are showing DateUtil class.<br />
<br />
Let's discuss what has happened over here. Under normal circumstances, log variable referred in UserService should be the one injected by Grails which would have correctly prefixed "com.test.service.UserService" before log statement. But that's not the case over here. "log" variable in UserService is actually static variable defined in DateUtil. The reason being when we have statically imported DateUtil with "*" suffix, all of it's static variables and methods get imported. As a result "log" variable also get's imported. Wait a minute, "log" variable is private in DateUtil. So how come that is accessible by UserService. Well, that's because there is a <a href="http://jira.codehaus.org/browse/GROOVY-1875" target="_blank">bug</a> in Groovy which allows privately declared variables accessible from outside.Yes, it's hard to believe but that's the truth. So now since "log" variable used in UserService is actually referring to DateUtils "log" variable, we see "com.test.util.DateUtil" prefix in log statement.<br />
<br />
Well, incorrect prefix in log statements might not look very serious problem at first. But this can get serious and might give unpredictable results with other variables. Apart from this, few times I have observed static variables and methods are not visible even when correctly imported. Not sure why, but I have seen such problems. So on the whole my advice is not to use static imports in Groovy.</div>Gagan Agrawalhttp://www.blogger.com/profile/02864388407613125097noreply@blogger.com3tag:blogger.com,1999:blog-3395513692650231176.post-48599951147521207122012-02-20T06:01:00.000-08:002012-02-20T08:55:37.047-08:00Groovy/Grails : Hibernate Session Gotchas in multi-threaded code<div dir="ltr" style="text-align: left;" trbidi="on">
Click <a href="http://xebee.xebia.in/2012/02/16/groovygrails-hibernate-session-gotchas-in-multi-threaded-code/" target="_blank">here</a> to view the <a href="http://xebee.xebia.in/2012/02/16/groovygrails-hibernate-session-gotchas-in-multi-threaded-code/" target="_blank">blog</a></div>Gagan Agrawalhttp://www.blogger.com/profile/02864388407613125097noreply@blogger.com0tag:blogger.com,1999:blog-3395513692650231176.post-52548415473332409242012-01-14T09:47:00.000-08:002012-02-20T05:55:45.123-08:00With Groovy comes great power of DSL(Domain Specific Language)<div dir="ltr" style="text-align: left;" trbidi="on">
Slowly and steadily I have started realizing the power of DSL(Domain Specific Langauge) and I found Groovy a very powerful tool to write DSL. DSL takes programming to next level by allowing input to a program be given as set of actions than merely a function call.If you want to explore DSL in detail, I would recommend you to read Martin Fowler's <a href="http://martinfowler.com/bliki/DomainSpecificLanguage.html" target="_blank">book</a> on DSL.<br />
<a name='more'></a><br />
<br />
Closures play an important role while writing DSL in groovy. In Grails, DSL with closure has been used extensively. Take an example of GORM Criteria.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>def criteria = Person.createCriteria()
def result = criteria.list{
like("name","%XYZ%")
eq("gender","male")
gt("age",30)
}
</code></pre>
<br />
In above example we have passed closure to list method of criteria to get all Persons whose name matches "XYZ", gender is equal to male and age is greater than 30. Keywords <b>like</b>, <b>eq</b> and <b>gt</b> are very intuitive and anybody reading the code can tell what code is expected to do just by looking at it.<br />
<br />
In my project also I have started using DSL at various places which I think are ideal places for DSL. Take an example of Email Service. The sendMail method of emailService expects certain data to be provided as input e.g. from, to, cc, bcc, subject etc.<br />
<br />
*Note : This implementation is similar to one provided by MailService plugin in grails.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>emailService.sendMail{
from admin@xyz.com
to to@xyz.com
cc cc@xyz.com
bcc bcc@xyz.com
subject Test
}
</code></pre>
<br />
<br />
Behind the scene in EmailService I assign delegate of closure as EmailData instance. With this it is now possible to map <b>to</b>,<b>cc</b>,<b>bcc,subject </b>to methods like<br />
void to(String to)<br />
void cc(String cc)<br />
and so on...Within these methods, the data is assigned to instance variables like to, cc, bcc. This data can then be used in actual logic to send mail.<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>class EmailService{
void sendMail(Closure closure){
EmailData emailData = new EmailData()
closure.delegate = emailData
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure.call()
/*
Write the logic here to send email. Required data can be
accessed as ..
emailData.to
emailData.cc
emailData.bcc
emailData.subject
*/
}
class EmailData{
String to
String cc
String bcc
String subject
void to(String to){
this.to=to
}
void cc(String cc){
this.cc=cc
}
void bcc(String bcc){
this.bcc=bcc
}
void subject(String subject){
this.subject=subject
}
}
}
</code></pre>
<br />
<br />
This way, DSL makes code more readable and intuitive. Client of EmailService API do not need to create an instance of EmailData and set required variables. They can simply pass closure to sendMail method and can pass required data as action.<br />
<br />
I have personally started liking DSL and will be using more and more going forward. Do let me know your thoughts/comments on this.</div>Gagan Agrawalhttp://www.blogger.com/profile/02864388407613125097noreply@blogger.com0tag:blogger.com,1999:blog-3395513692650231176.post-87994835929970219372012-01-06T04:29:00.000-08:002012-02-20T05:56:27.647-08:00Groovy/Grails : Integration tests for multi-threaded application<div dir="ltr" style="text-align: left;" trbidi="on">
Recently I came across a situation in my project, where I had to write integration test for multi-threaded code. Basically I had a business method in service class which executed some portion of it's work in separate thread. Now in order to write integration test for such method, test method should ideally wait for the thread(s) created by service class to complete before asserting result. But there was no way I could figure out if the threads created by service class has completed. So then I thought to refactor my code in a way that I can figure from outside if the threads have got completed or not.<br />
<a name='more'></a><br />
<br />
Accordingly I have created ThreadCompetionTracker as mentioned below.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>package com.beachbody.pioneer.util
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.Executor
import java.util.concurrent.Callable
import java.util.concurrent.ExecutorService
import org.apache.commons.logging.LogFactory
class ThreadCompletionTracker {
private static def log = LogFactory.getLog(this)
private static ConcurrentHashMap<String, CountDownLatch> latchMap = new ConcurrentHashMap<String, CountDownLatch>()
private static ThreadLocal<String> latchKey = new LatchKey()
static void waitToComplete(Integer threadCount=1,Closure closure){
log.info("Inside wait to complete")
String key = latchKey.get()
try{
latchMap.put(key, new CountDownLatch(threadCount))
closure.call()
CountDownLatch countDownLatch = latchMap.get(latchKey.get())
countDownLatch.await(30, TimeUnit.SECONDS)
}finally {
log.info("Removing key from latch map : "+key)
latchMap.remove(latchKey.get())
}
}
static void withTracking(ExecutorService executor, Closure closure){
withTracking(executor,closure as Callable)
}
static void withTracking(ExecutorService executor, Callable callable){
String key = latchKey.get()
Closure task = {
runCallable(key,callable)
}
executor.submit(task)
}
private static void runCallable(String key, Callable callable){
log.info("Running callable inside runCallable")
try{
latchKey.set(key)
callable.call()
}finally {
if(latchMap.containsKey(key)){
log.info("latchMap contains key : ${key}")
CountDownLatch countDownLatch = latchMap.get(latchKey.get())
countDownLatch.countDown()
}
}
}
}
class LatchKey extends ThreadLocal{
protected synchronized String initialValue(){
String name = Thread.currentThread().name+System.currentTimeMillis()
return name
}
}
</code></pre>
<br />
This class has mainly two important public methods.<br />
1. WaitToComplete - Will wait for the closure to complete.<br />
2. WithTracking - Enables tracking for service.<br />
<br />
Here is the test case written using this class.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
void testSendEmail(){
assertEquals(0,greenMail.getReceivedMessages().length)
ThreadCompletionTracker.waitToComplete{
EmailRequest request = new EmailRequest()
//Write some code to populate EmailRequest object correctly
mailSender.sendEmail(request)
}
assertEquals(1,greenMail.getReceivedMessages().length)
}
</code></pre>
<br />
The above integration test case, sends a mail using a mailSender service class. Within the service, mail is being sent via separate thread as shown below. Since the mailSender.sendEmail has been wrapped by "waitToComplete" method, current thread of integration test will wait until mail sending thread has completed.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>class MailSender {
static transactional = true
def handlerMap
def final pool = Executors.newFixedThreadPool(10)
def sendEmail(EmailRequest emailRequest){
emailRequest.save(flush:true)
ThreadCompletionTracker.withTracking(pool, sendRequestToHandler(emailRequest) as Callable)
}
def sendRequestToHandler(EmailRequest emailRequest){
try{
handlerMap[emailRequest.type].handle(emailRequest)
}catch(PioneerException pe){
log.error(pe,pe)
}
return true
}
}
</code></pre>
<br />
Above is the MailSender service which sends email to handler for necessary processing in asynchronous way. It uses ThreadCompletionTracker's withTracking method. This way we can track if all the threads created by MailSender service have completed or not. Once the threads are completed then only we issue any assert statements in integration test. We also give default time to wait i.e. 30 seconds in waitToComplete method. This is necessary as we can not wait indefinitely for threads to complete.<br />
<br />
<br /></div>Gagan Agrawalhttp://www.blogger.com/profile/02864388407613125097noreply@blogger.com0tag:blogger.com,1999:blog-3395513692650231176.post-7197279942899384902011-12-26T06:24:00.000-08:002012-02-20T05:56:57.353-08:00Rapid Web Development with Groovy/Grails<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div style="background-color: white; border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 24px; margin-bottom: 1.625em; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: -webkit-auto; vertical-align: baseline;">
I have been working on Groovy/Grails for past 6 months and it’s being an amazing experience. In less than 4 months time we have been able to create a new web application from scratch and deploy in production.</div>
<div style="background-color: white; border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 24px; margin-bottom: 1.625em; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: -webkit-auto; vertical-align: baseline;">
First, it’s Groovy which makes coding so easy that anybody will fall in love with it. A piece of code that would have taken 10 lines of code in JAVA can be written in couple of lines in groovy. On top of it is a web framework i.e. Grails, which makes web development look like child’s play. Yes, believe me or not, it’s truth that I have experienced. Atleast after working purely in java with frameworks like JSF, Struts etc., I feel so.<br />
<a name='more'></a></div>
<div style="background-color: white; border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 24px; margin-bottom: 1.625em; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: -webkit-auto; vertical-align: baseline;">
Developing Web 2.0 application has never been easy before. Thanks to Grails plugins which makes almost everything possible in just few minutes of time. One can get started and develop sample application in just 5 mins as explained in this <a href="http://grails.org/screencast/show/15" target="_blank">video</a>, but it would not be sufficient enough to develop enterprise application. But it took me around 1 month to get comfort level on both Groovy and Grails which I believe is very less considering the fact that it's not just about learning a new tool, it's about learning a new language and a web framework which spawns across all layer i.e presentation, business and persistent.<br />
<br />
It's the simplicity of the language and web framework that makes it look so simple to learn and implement. When I started many people told me that it's not for enterprise development where heavy load is expected. But after working for 6 months I think that's not true. It's just that one should have sufficient experience so that not to use Grails in wrong way. There are various optimization techniques one need to understand and model their application accordingly.<br />
<br />
There is lot to learn and share in this space which I would be doing going forward. In this blog I just wanted to share my thoughts about Groovy and Grails and would definitely recommend for rapid development.</div>
</div>Gagan Agrawalhttp://www.blogger.com/profile/02864388407613125097noreply@blogger.com0Gurgaon, Delhi, India28.46385 77.017837999999983-8.1247479999999968 17.252212999999983 65.052448 136.78346299999998