Sunday, March 27, 2011

Grails to Coldfusion: Confusion?

I've recently been working on a big Coldfusion Project. The problem with switching from Grails to Coldfusion is that i tend to inherit my coding habits in Grails and use it for Coldfusion.

I found it to be a bit awkward at first, but i found this to be truly helpful in my project's development phase.

I just realized that when it comes to coding, it's really best to invest more time in ensuring good code is made. Good code for me would probably mean a structured, reusable, loosely-coupled code. This would help in bug fixing later, fixes would be so quick as compared to unstructured code.

Monday, July 20, 2009

Saving the Java Exception Stack Trace into a file

If we want to get the Stack Trace of a Java Exception, we can't simply use exception.printStackTrace() because that method returns nothing and just prints the stack trace into the console.

To get the Stack Trace and store it into a file, you can do this:


StringBuilder sb = new StringBuilder();
StackTraceElement[] stackTrace = exception.getStackTrace();
for(int i=0;i<stackTrace.length;i++){
sb.append(stackTrace[i]);
sb.append("\n");
}


Given the StringBuilder sb above, you can proceed to write the string in a file. This is how i would do it:

FileOutputStream fos = new FileOutputStream(filename);
try{
OutputStreamWriter osw = new OutputStreamWriter(fos);
try{
BufferedWriter bw = new BufferedWriter(osw);
try{
bw.write(sb.toString());
}finally{
bw.close();
}
}finally{
osw.close();
}
}finally{
fos.close();
}


Similarly, you can merge the 2 codes above like below:

FileOutputStream fos = new FileOutputStream(filename);
try{
OutputStreamWriter osw = new OutputStreamWriter(fos);
try{
BufferedWriter bw = new BufferedWriter(osw);
try{
StackTraceElement[] stackTrace = exception.getStackTrace();
for(int i=0;i<stackTrace.length;i++){
bw.write(stackTrace[i]);
bw.newLine();
}
}finally{
bw.close();
}
}finally{
osw.close();
}
}finally{
fos.close();
}

Problem with Tiles + Grails 1.1 (beta2)

In my last post i've mentioned that i was able to successfully integrate Tiles with Grails. It seems i spoke too soon. I found out that the current release of Grails 1.1 beta version still have problems rendering with custom JSP tags. Specifically, i found out that you Grails can't process nested custom JSP tags correctly.

To illustrate, I've created a new grails app, and tried to create a very simple page using the jstl core tag libs, with the ff. content:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>test</title>
</head>
<body>
<c:choose>
<c:when test="${1==1}">
hello
</c:when>
</c:choose>
</body>
</html>

A grails runtime exception is encountered:
javax.servlet.jsp.JspTagException: Illegal use of <when>-style tag without <choose> as its direct parent

There may be more problems to be encountered later, so i think we're opting not to integrate tiles with grails, and use the old-fashioned-but-reliable struts instead. Sadly, the estimates we gave to the client are based on Grails, not Struts! =P

Integrating Tiles with Grails

One of our projects is required to use Tiles as its templating mechanism. Since we plan to use Grails for this project, we needed to find out if we can integrate Tiles with Grails (since Grails has its own templating mechanism, SiteMesh).

Didn't really find much info from googling, so i tried to download Tiles and manually integrate with a sample Grails app that i created. After some time, we were able to integrate Tiles successfully with my Grails app.

Here are the steps on how i did it:

1. Download Tiles 2.0 from http://tiles.apache.org/. Unzip the files.
2. Get the ff. files from the unzipped Tiles package, and place it in the lib folder of my webapp (note: not /web-app/WEB-INF/lib folder, but /lib folder directly).
3. We need to edit web.xml. Since it's auto-generated by grails, there's no web.xml in a new project. But you can make grails create the web.xml template for you to edit. Open console and type "grails install-templates" in your app folder. This will create a folder src/templates/war, where you can find the web.xml.
4. Edit web.xml and add the ff. entries:

<context-param>
<param-name>
org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG
</param-name>
<param-value>
/WEB-INF/tiles-defs.xml
</param-value>
</context-param>

<filter>
<filter-name>Tiles Filter</filter-name>
<filter-class>org.apache.tiles.web.startup.TilesFilter</filter-class>
<init-param>
<param-name>
org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG
</param-name>
<param-value>
/WEB-INF/tiles-defs.xml
</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>Tiles Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>

<listener>
<listener-class>org.apache.tiles.web.startup.TilesListener</listener-class>
</listener>

<!-- Tiles servlet -->
<servlet>
<servlet-name>tiles</servlet-name>
<servlet-class>org.apache.tiles.web.startup.TilesServlet</servlet-class>
<init-param>
<param-name>
org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG
</param-name>
<param-value>
/WEB-INF/tiles-defs.xml
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

We have added the ff: context-param, tiles filter, tiles listener, and tiles servlet.

5. Create a file WEB-INF/tiles-defs.xml (as defined in the web.xml entries above); this is where we will store the tiles definitions. E.g.:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
<--tiles definitions here-->
</tiles-definitions>


After doing this, you should be able to use tiles normally as you would in any application. Note that you should specify jsp/gsp files in the tile def instead of just the url.
e.g. use
<definition name="myapp.homepage" template="/layouts/tiles.gsp">
instead of
<definition name="myapp.homepage" template="/layouts/tiles">
even if accessing /layouts/tiles will open tiles.gsp as convention by Grails.

Hope this helps. Note that this will only work for Grails 1.1 (beta version as of now), as Grails 1.0 does not support imported JSP tag libraries. I have only tried this with Tiles 2.0, though. I have heard that earlier version of Tiles is integrated in Struts, so not sure if we can use directly. Unfortunately for us, we will be using Tiles 1.1, hopefully we can integrate it later.

Try it out! Let me know if it works.

Displaying images from database records in Grails pages

Displaying images from database records in Grails is fairly simple, and is far easier than doing it in Java.

First, prepare a definition in your controller for the image display, e.g.:

def showImage = {
def record = Record.get( params.id ) // get the record
response.outputStream << record.screenshot // write the image to the outputstream
response.outputStream.flush()
}


Once you define the above, you should be able to access the url /(context-name)/record/showImage/(id) which will display the image of that record id.

In your gsp file, you can then display the image by simply specifying the source of the img file as the url above.

<img src="/(context-name)/record/showImage/${record.id}">


The image should be displayed by that code. You can adjust the height and width accordingly.

Saving images as blob in the database using Grails

Handling images is not as easy as handling simple http parameters. This is because images are received as binary objects that you can't directly put in the database field. Here's how i handled saving images to the database:

First, the form containing the image file input field should be declared as multipart:

As i understand it, we need to specify multipart because you can't mix the text parameters with the binary parameters, so we should have it as multipart.

Of course, the file field inside the form should exist, for user to input the image file, e.g.:

<input id="screenshot" name="screenshot" type="file" />

Ok. now, in the controller, say ImageController, we can process the binary image this way:

def record = new Record()
record.properties = params
if(request instanceof MultipartHttpServletRequest) {
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;
CommonsMultipartFile file = (CommonsMultipartFile)multiRequest.getFile("screenshot");
record.screenshot = file.bytes // screenshot is the image blob field of the record
}
record.save() // create the record


On save, the record should be created with the image stored as blob.
You might encounter some problem with the image field in the groovy file. So i suggest that you change the field into byte[] instead of Blob. i.e. in Record.groovy above,:

class Record {
// ..
// some fields
// ..
byte[] screenshot // declare the image as byte[] instead of blob
// ..
static constraints = {
// ..
screenshot(maxSize:1073741824) // max 4GB file
}
}


If you don't do the procedure above to your groovy domain class, there might be a problem with saving the image to the blob field in the database.

Next post: how to display an image file from the database to the web page.

First Grails Project: BugTracker

My first Grails Project is a system that enables users to log and keep track of bugs reported -- it's for internal use in our company and hopefully Grails will be able to finish the job :)

So far so good. Some features i've found quite useful are:

- the g:render tag, which allowed me to create a forum type of plugin.

- the g:forEach tag. I love how we don't need to perform typecasting for each element iterated.

- the Acegi plugin. quite good, though i spent quite some time to figure things out (i still am..). But if you understand it well, you'll find it very useful as all you possibly need is already included in it.

I still haven't utilized the CSS powers in grails, so the webapp looks boring as heck. Maybe later.