Grails : Rest Service with JAXB parsing – PART 2
May 9, 2012 Leave a comment
- Collection mapping in JAXB
- Exception Handling
- Returning response in XML
- URLMappings for Grails Controller
My learnings and findings
May 9, 2012 Leave a comment
May 4, 2012 Leave a comment
<?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
February 20, 2012 Leave a comment
Suppose we have a DateUtil class as mentioned below with some utility methods for playing with dates.
package com.test.util
class DateUtil{
private static final log = LogFactory.getLog(this)
static Date parse(String format, String strDate){
Date date = null
try {
date = Date.parse(format, strDate)
} catch (Exception e) {
}
date
}
}
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 log variable above with red color since the problem I am going to mention is related to this variable.
Now suppose we have another class UserService as mentioned below
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)
}
}
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 “log“. 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.
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 “log” variable. If you look into log file and locate for log statement “Searching for users created after : 01/01/2012“, you will be shocked to see prefix “com.test.util.DateUtil” instead of “com.test.service.UserService” 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.
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 bug 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.
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.
January 14, 2012 Leave a comment
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.
def criteria = Person.createCriteria()
def result = criteria.list{
like("name","%XYZ%")
eq("gender","male")
gt("age",30)
}
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 like, eq and gt are very intuitive and anybody reading the code can tell what code is expected to do just by looking at it.
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.
*Note : This implementation is similar to one provided by MailService plugin in grails.
emailService.sendMail{
from admin@xyz.com
to to@xyz.com
cc cc@xyz.com
bcc bcc@xyz.com
subject Test
}
Behind the scene in EmailService I assign delegate of closure as EmailData instance. With this it is now possible to map to,cc,bcc,subject to methods like
void to(String to)
void cc(String cc)
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.
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
}
}
}
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.
I have personally started liking DSL and will be using more and more going forward. Do let me know your thoughts/comments on this.
January 6, 2012 Leave a comment
Accordingly I have created ThreadCompetionTracker as mentioned below.
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
}
}
This class has mainly two important public methods.
1. WaitToComplete – Will wait for the closure to complete.
2. WithTracking – Enables tracking for service.
Here is the test case written using this class.
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)
}
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.
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
}
}
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.
December 26, 2011 Leave a comment
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.
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.