Showing posts with label groovy. Show all posts
Showing posts with label groovy. Show all posts

Thursday, July 30, 2009

Detect an AJAX request

Many web applications use AJAX nowadays. In a typical scenario, one fills out a form, which is then submitted to the server. If you don't use AJAX or JavaScript is disabled, your form should still submit with no problems. And you receive a new page. If you use unobtrusive enhancement via JavaScript, the form is submitted to the server and the page is updated with the result without a full page reload.

While developing with Grails writing Java and Groovy code, I noticed that a typical pattern is to create two actions in a controller. One to handle normal HTTP POST (e.g. save action) and one to handle HTTP POST coming from an AJAX request (e.g. saveAjax action). The two actions are almost identical. They perform the same business logic. The only difference is what is returned from each action. A normal action renders a new page. An AJAX one returns whatever your flavor is: XML, JSON, HTML, plain text.

So is there a way to tell the requests (ordinary and AJAX) apart?

You guessed it, there is. AJAX request comes with a special header - X-Requested-With. I usually have my controllers to extend my BaseController, which has a couple of useful methods that I use. isAjax(request) is one of them. And this is what it looks like.


public static boolean isAjax(request) {
return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
}

I hope you'll find it useful. The all you need to do in your action is this:


def save = {

// business logic
// ...

if (isAjax(request)) {
render([ /* data */ ] as JSON)
}
else {
// render or redirect here
render(view: 'save', model: [ /* model data */ ])
}
}

Friday, December 05, 2008

Easy Groovy Iteration

The problem

Let's say we want to check the correct mimetype and file extension of the file being uploaded. In a typical Java way I would write something like this:

boolean isRightType = "image/jpeg".equals(contentType)
|| "image/png".equals(contentType)
|| "image/x-png".equals(contentType);

boolean isRightFileExt = filename.endsWith(".png")
|| filename.endsWith(".jpg")
|| filename.endsWith(".jpeg");

Groovy solution

The Groovy way is much simpler and more elegant.

private static CONTENT_TYPES = ["image/jpeg", "image/png", "image/x-png"]
private static FILE_EXTENTIONS = [".png", ".jpg", ".jpeg"]
...
boolean isRightType = CONTENT_TYPES.any { it.equals(contentType) }
boolean isRightFileExt = FILE_EXTENTIONS.any { filename.endsWith(it) }

This was just a small example. What I really find useful are some of the following constructs that make my programming life really pleasant

Groovy Iteration

each

Simple collection iteration

def fibList = [1, 1, 2, 3, 5, 8, 13]
fibList.each { println it } // prints all of the numbers in the list

any

If you need to find out if any element of the collection meets the condition.

def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.any { it == 3 }
assert fibList.any { it - 2 > 10 }

This is pretty much equivalent to a Java construct

boolean any(List list, Condition cond)
for (E e : list) {
if (cond.meets(e)) {
return true;
}
}
return false;
}

every

If you need to find out if any element of the collection meets the condition.

def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.every { it > 0 }

This is pretty much equivalent to a Java construct

boolean every(List list, Condition cond)
for (E e : list) {
if (!cond.meets(e)) {
return false;
}
}
return true;
}

collect

If you need to create a new collection that contains each element of the original collection transformed in some way.

def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.collect { it - 1 } == [0, 0, 1, 2, 4, 7, 12]

This is pretty much equivalent to a Java construct

List every(List list, Command command)
List result = new ArrayList(list.size());
for (E e : list) {
result.add(command(e));
}
return result;
}

findAll

If you need to create a new collection that contains all elements that meet the condition.

def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.findAll { it > 1 && it < 5 } == [2, 3]

This is pretty much equivalent to a Java construct

List findAll(List list, Condition cond)
List result = new ArrayList(list.size());
for (E e : list) {
if (!cond.meets(e)) {
result.add(e);
}
}
return result;
}

find

If you need to find first element that matches the condition.

def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.find { it > 1 } == 2

This is pretty much equivalent to a Java construct

E findAll(List list, Condition cond)
for (E e : list) {
if (!cond.meets(e)) {
return e;
}
}
return null;
}

References

Wednesday, November 12, 2008

Grails Logging

Configuring logging in Grails is not as simple one would think. Grails uses Log4J as its logging framework. Log4J configuration is stored in the log4j.properties file. In Grails, this file is generated from Config.groovy source file.

The official Grails Logging documentation says that if you want to have a different logging levels for let's say a specific controller, all controllers and the rest of your application, you should define the logging levels as:

grails.'app.controller.YourOtherController'="off,stdout"
grails.'app.controller'="info,stdout"
grails.app="error,stdout"

Yes, those ticks are required, otherwise you get an error message (No such property: context for class: java.lang.String). Don't ask me why. What is also important is the order. Children need to go first.

So that is what the official documentation and few blogs say.

Grails allows you to configure your production, development and testing environments differently if required. I configured Log4J the way that common properties are grouped and placed outside the environment dependent ones. But no matter how I tweaked it, I could not make it to work. For some reason the parent's or child's definition overrides the other, or causes an error.

But there is a solution to this problem after all. Instead of dot notation, use curly braces. Like in the following example:

environments {
development {
...
log4j {
appender.stdout = ...
rootLogger="error,logfile,stdout"
logger {
grails {
app {
controller="debug"
}
}
}
}
}
production {
...
}
}

// log4j configuration
log4j {
appender.logfile=...
appender.stacktraceLog=...
rootLogger="debug,logfile"
logger {
grails="error"
StackTrace="error,stacktraceLog"
...
}
additivity.StackTrace=false
}

This works. Tested with Grails 1.0.3.

Related articles:


Creative Commons License This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.