XSS Sanitizer Plugin (v0.2) released

Well, after shamefully waiting over a year to do any kind of updates to this plugin, I've finally made some changes and merged in pull requests from others.

Next steps are going to be fix some of the issues. Some great suggestions have come up in the Issues area on Github. In fact, I plan on releasing a patch later today.

I chose version 0.2 after some long debate with myself (Hello, me). I don't really want to call this a 1.0 release quite yet. I think some things like not being able to override the ESAPI.properties file as well as not enough unit tests make this still a beta plugin. I'd love to know if others are using it, too. If so, and people are having success, then maybe a 1.0 release is in order. Until then, there's still some work left to do.

XSS Sanitizer Grails Plugin

Well, earlier this week I published my first Grails plugin. I'm hoping that people will find it useful to add a general security plugin to parse out, and prevent XSS attacks on their website. It's a long way from being done, but I think it's a good start.

It uses OWASP's ESAPI to strip out any unwanted script, iframe, and img tags that come in on the request. It also has the added benefit of doing this in a Java filter (in case you access the request via the HttpRequest) and the Grails "params" attribute.

Next steps are to write tests for each of the potential hacks on http://ha.ckers.org/xss.html to make sure they all pass. Plus, in my opinion, this is just a general replace of all values. There are potentially times when you might want to submit something that falls into one of these categories, and you feel that it's safe to not have to filter it. So, I'd like to allow users to be able to annotate methods to allow/disallow the filter to run give a certain action.

Here's a link to the source code:

https://github.com/tonyzampogna/XssSanitizer

If you would like to install it, just type:

grails install-plugin xss-sanitizer

If you are interested in contributing, please let me know. I'd love to have some collaboration.

How to inject two or more dependencies with the same name

Let's say you have two services named UserService and both are included in your Grails classpath. This can happen, for example if you have a "core" package, and an "application" package that extends services from "core".

Here's what that might look like in our case:

Well, if you try to use "UserService" in your Grails application like so, you will get an error saying that UserService cannot be found.

    def userService

That's because there was a name collision on UserService.

Spring accounts for this, and allows you to define your class for each bean name. In Grails, we can define our beans in the grails-app/conf/resources.groovy file.

Here's an example of what our resources.groovy file would look like:

beans = {
  // syntax is beanId(implementingClassName) { properties }
  // User Service
  coreUserService(com.company.core.UserService) {
    grailsApplication = ref("grailsApplication")
  }
  userService(com.company.usecase.UserService) {
    coreUserService = ref("coreUserService")
  }
}

Then, in your services, you can inject these services like so:


class UserController {
  def userService

  ...
}

// From your UserService, you can access the core UserService like this.
package com.company.core.UserService
class UserService {
  def coreUserService

  ...
}

Hopefully, that helps.

Grails resources plugin

I installed the Grails zipped-resources plugin on a new project the other day, and I noticed that by default it zips up everything it sends.

This is fine, but when I tried to make it ignore the image files being served up, it wasn't obvious at first how to do that. Finally, I figured out what I needed to do. Adding the following line to my Config.groovy excluded the image files from being zipped up.

grails.resources.mappers.zip.excludes = ['**/*.png','**/*.gif','**/*.jpg','**/*.jpeg','**/*.gz','**/*.zip']

Once I read more about defining a mapper, it was nice to see that even configuration of these resource files was taking on a convention.

That said, the suite of resources plugins that are coming out now for Grails are very useful. I would say that they really help make Grails a strong contender in platform choices for the future.

Grails CamelCase Sensitivity

I ran into an weird bug today that took awhile to figure out. Basically, I was getting the error when I deployed some grails code to a linux box.

In the error log, this is what showed up:

ERROR view.ScaffoldingViewResolver  - Error generating scaffolded view [/BNice/index]: /opt/grails-1.3.7/src/grails/templates/scaffolding/index.gsp (No such file or directory)
java.io.FileNotFoundException: /opt/grails-1.3.7/src/grails/templates/scaffolding/index.gsp (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<;init>;(FileInputStream.java:120)
at org.grails.plugin.resource.DevModeSanityFilter.doFilter(DevModeSanityFilter.groovy:44)
at java.lang.Thread.run(Thread.java:680)

And, in the HTML response, this is what showed up:

HTTP status 404 - /testapp/WEB-INF/grails-app/views/BNice/index.jsp
type: Status report
message: /testapp/WEB-INF/grails-app/views/BNice/index.jsp
description: The requested resource (/testapp/WEB-INF/grails-app/views/BNice/index.jsp) is not available.

It took a while, but I finally figured out that it had nothing to do with the server setup, but was in fact an issue with the code.

In the project, there was a controller called "BNiceController". When grails sees to capital letters in the beginning of a name, the CamelCasing of the controller and the views must be exactly like first part of the controller.

Here's how a normal reference would look for a controller called BeNiceController.

// In the gsp, the controller would be referenced like so:
${createLink(controller: 'beNice')}

// The view would be located in /grails-app/views/beNice/index.gsp

However, if the controller is called BNiceController, this is what you would have to do. Notice, the folder in the views directory is "BNice".

// In the gsp, the controller would be referenced like so:
${createLink(controller: 'BNice')}

// The view would be located in /grails-app/views/BNice/index.gsp

It's kind of annoying. I wish this wasn't the default behavoir.

How to setup a clustered Quartz scheduler in Grails 2.0.0

In my steps below, I'm using Grails 2.0.0 and Quartz 2.1.1. I'm also connecting to a local DB2 database.

1. Run "grails clean" on your application.

2. Add the "quartz-all-2.1.1.jar" and "c3p0-0.9.1.1.jar" (in the lib folder of your Quartz download) to your lib directory.

3. Right click on your Grails project and chose "Grails Tools -> Refresh Dependencies" (Alt+G, R)

* Note: You will need run steps 1 - 3 in order to get Grails to link the dependencies.

4. Add your Quartz.properties file to your "conf" directory (or somewhere else on your classpath). Here's the Quartz.properties file I used (you'll need to change the username and password).

#============================================================================
# Configure Main Scheduler Properties
#============================================================================

org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO

#============================================================================
# Configure ThreadPool
#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore
#============================================================================

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000

#============================================================================
# Configure Datasources
#============================================================================

org.quartz.dataSource.myDS.driver = com.ibm.db2.jcc.DB2Driver
org.quartz.dataSource.myDS.URL = jdbc:db2://localhost:50001/BATCH
org.quartz.dataSource.myDS.user = <some user>
org.quartz.dataSource.myDS.password = <some password>
org.quartz.dataSource.myDS.maxConnections = 5
org.quartz.dataSource.myDS.validationQuery=select 0 from dual

5. In your Config.groovy file, add or modify you "grails.config.locations" property. Here's what I added:


grails.config.locations = [
        "classpath:conf/Quartz.properties"
]

6. I added the JobScheduler and HelloJob java classes to my src/java directory. These could be groovy or whatever, but I just stole the example from Quartz to get it working correctly.

JobScheduler.java


package sample.quartz.scheduler;

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.CronScheduleBuilder.*;

import org.apache.log4j.Logger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;

public class JobScheduler {
	private static Logger log = Logger.getLogger(JobScheduler.class);

	private static JobScheduler JOB_SCHEDULER = new JobScheduler();
	private Scheduler scheduler = null;

	public JobScheduler() {
	}

	public static JobScheduler getInstance() {
		return JOB_SCHEDULER;
	}

	public void startup() {
		try {
			// and start it off
			scheduler = StdSchedulerFactory.getDefaultScheduler();
			System.out.println("NAME: " + scheduler.getSchedulerName());
			scheduler.start();

			// define the job and tie it to our HelloJob class
			JobDetail job = newJob(HelloJob.class)
					.withIdentity("job1", "group1")
					.build();

			// Trigger a job that repeats every 20 seconds
			Trigger trigger = newTrigger()
					.withIdentity("trigger1", "group1")
					.withSchedule(cronSchedule("0/20 * * * * ?"))
					.build();

			System.out.println("Starting Jobs");
			// Tell quartz to schedule the job using our trigger
			scheduler.scheduleJob(job, trigger);
			scheduler.start();

		} catch (SchedulerException se) {
			se.printStackTrace();
		}
	}

	public void shutdown() {
		try {
			scheduler.shutdown();
		} catch (SchedulerException se) {
			se.printStackTrace();
		}
	}
}

HelloJob.java


package sample.quartz.scheduler;

import java.util.Date;

import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloJob implements Job {
	private static Logger log = Logger.getLogger(HelloJob.class);

	public HelloJob() {
	}

	public void execute(JobExecutionContext context)
			throws JobExecutionException {
		System.out.println("Hello!  HelloJob is executing. " + new Date());
	}
}

7. In your BootStrap.groovy file, add...


import sample.quartz.scheduler.JobScheduler

class BootStrap {

        def init = { servletContext ->
                JobScheduler.getInstance().startup()
        }

        def destroy = {
                JobScheduler.getInstance().shutdown()
        }
}

That's it! Start your server. I tested it by running two servers. So,

grails -Dserver.port=8080 run-app

and then

grails -Dserver.port=8090 run-app

You will see that the first server to come up will run the HelloJob.java. I then tested the cluster by shutting off the first server. The second server picked up the scheduler (within 20 seconds, since that's what was specified in the property file) and started running with it.

One problem I ran into trying to set this up was the error below. I had forgotten to c3po-0.9.1.1.jar along with quartz-all-2.1.1jar to the lib directory. Once I did that (and refreshed the dependencies), this error went away.

Issue:

ERROR context.GrailsContextLoader  - Error executing bootstraps: java.lang.NoClassDefFoundError: com/mchange/v2/c3p0/ComboPooledDataSource

Hope that helps.

Grails 2.0.0 lib directory fix

I recently had a problem with Grails when I started a new project in Eclipse with Grails 2.0.0. I tried adding an external JAR file to my "lib" directory by dragging the JAR file over to the directory.

In Grails 1.3.7, the JAR file would then get added to the list of grails dependences (after refreshing the dependencies). However, that stopped working. After reading some user group posts, here's what I did to fix it.

1) run "grails clean"
2) drag the jar file to your "lib" directory.
3) right-click on the project and choose Groovy Tools -> Refresh Dependencies