Using Spring Integration to Create a Async Service in Grails

26th June 2012 by jt 3 Comments

A common action in a web application is to send an email based on a user some user action. This is a nice candidate for a async service to improve the response time to the end user. In this example, we’ll use Spring Integration to support sending a an email via Amazon’s Simple Mail Service.

Setup

You will need the following:

  • A Grails 2.0+ project
  • AWS Plugin (Using 1.2.12.2 in this example)
  • Spring Security Core Plugin
Spring Integration

There is no plugin for Spring Integration.  We can add it as a dependency to the project.  Add the following to your BuildConfig.Groovy file (under /conf)

    dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
        compile('org.springframework.integration:spring-integration-mail:2.1.2.RELEASE')  {
            excludes "spring-aop", "spring-beans", "spring-context", "spring-context-support", "spring-core", "spring-tx"
        }
    }

In my example, I’ve setup a simple form and controller to handle the form post.  I’m going to assume you already have a working knowledge of Grails and not cover this area.

Spring Integration supports using an interface for a messaging gateway.

My gateway is defined as:

public interface SendMailGateway {
@Gateway(requestChannel='mailChannel')
void asyncMailSender(Map emailParams)
}

I want this to call a service to send an mail via AWS.  I’ll be using the AWS plugin for this, which has excellent documentation you can refer to for configuration. In my example, I want to send an HTML email.  The best way to do this is through the use of a GSP template.  Grails 2.0 added a PageRender service you can use to generate HTML from templates in services.  My service class is as follows:

class AwsEmailService {
 
    PageRenderer groovyPageRenderer
 
    def sendMail(Map params) {
 
        log.info('Mail Request Received by AWS Service')
        log.debug(params?.dump())
 
        try {
            String htmlBody = groovyPageRenderer.render(template:params.template, model: params.model)
            //call to AWS Mail Plugin
            def mailId = sesMail {
                to params.user.username
                subject params.subject
                html htmlBody
            }
 
            log.info("Mail Sent.  ID: ${mailId}")
        } catch(e) {
            log.error('Sending Mail Failed')
            log.error(e.message)
            e.stackTrace.each{log.error(it)}
        }
    }
}

This class is in the Grails services folder, thus will be automatically wired up as a Spring service and the @Service annotation is not required.

We want to use Spring Integration to provide a service using the gateway to call the AwsEmailService asynchronously.  While you can use the Grails bean builder DSL to wire this up, its easier to just use the XML config so you have IDE support for the syntax.  Getting the Groovy code correct for the DSL can be a little tricky.

The following XML defines the gateway interface and assigns it to a channel called ‘mailChannel’.  The mail channel is defined as a queue, with a depth of 10.  We configure the AwsEmailService with a poller to poll the mailChannel once every second.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:int="http://www.springframework.org/schema/integration"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/integration
              http://www.springframework.org/schema/integration/spring-integration.xsd">
 
    <int:gateway id="sendMailGateway" service-interface="mailsender.SendMailGateway" default-request-channel="mailChannel"/>
 
    <int:channel id="mailChannel">
        <int:queue capacity="10"/>
    </int:channel>
 
    <int:service-activator id="mailer" ref="awsEmailService" method="sendMail" input-channel="mailChannel">
        <int:poller fixed-rate="1000"/>
    </int:service-activator>
 
</beans:beans>

To bring this XML Spring config into your application, add the following to /conf/spring/config.groovy

beans = {
    importBeans('file:grails-app/conf/spring/integration.xml')
}

My use case in this example is to create a new user from a signup form, and send a verification email.  I’m using the Spring Security Core plugin and its default domain objects to create the user.  My Grails Service class is as follows:

class SignUpService {
 
    def springSecurityService
    def sendMailGateway
 
    def signUp(def params) {
 
        log.debug(params?.dump())
        // check for user
        def user = User.findByUsername(params?.email)
 
        if (user) {
            throw new Exception('User Already Exists')
        }
 
        user = new User(username: params?.email,
                password: springSecurityService.encodePassword(RandomStringUtils.randomAlphanumeric(30)),
                validationPhrase: RandomStringUtils.randomAlphanumeric(30)).save(failOnError : true, flush: true)
 
        if (user && !user?.hasErrors()) {
            def role = Role.findByAuthority('ROLE_USER')
 
            new UserRole(role: role, user:  user).save(failOnError: true, flush: true)
 
            user.save(failOnError : true, flush: true)
 
            // send verification email
            sendVerificationEmail(user)
 
            // log user into application - this creates a session
            springSecurityService.reauthenticate(user.username, user.password)
 
        }
    }
 
    def sendVerificationEmail(User user) {
 
        def map = [:]
 
        map.user = user
        map.subject = "Welcome to JTs Mail Sender App"
        map.template = "/email-templates/verifyAccount"
        map.model = [validationPhrase: user.validationPhrase, now: new Date()]
 
        log.info('Sending Mail Request to SI Gateway')
 
        sendMailGateway.asyncMailSender(map)
    }
}

You can see that I’m autowiring the SpringSecurityService in at the top.  I’m doing the same thing for the sendMailGateway. The SI gateway we configured is registered with Spring and will autowire just like any other bean in Grails.

The source code for this example is on google code.  You can get a copy with:

svn checkout http://jts-blog.googlecode.com/svn/trunk/june26Post/mailSender/ jts-blog-read-only

 

 

Share

For Start Ups Running in the Cloud

24th January 2012 by jt No Comments

Yesterday, I wrote a blog post about the impact of Cloud Computing for startups.

Share

Unit Testing Grails Controllers with Spock

25th November 2011 by jt 3 Comments

The Spock testing framework has been creating a buzz in the Grails/Groovy community. And after attending a session on Spock at Spring One a couple weeks ago, I understand why. If Spock isn’t on your radar already, it should be.

Controllers have always been a pain to test; there’s just a lot of moving parts in a http request/response cycle to test. The Grails framework comes out of the box with some great mocks to support unit testing of controllers. The Spock plugin builds upon these to make your controller unit tests feel – well, more ‘unit-y’.

This week I wrote a controller method to provide a JSON response for a logged in user’s profile.

Here is the controller we are dealing with:

class ProfileController {
 
    def userService
 
    // return a json object of the users data
    def getUserProfile() {
        def returnMap = [:] 
        returnMap.success = false 
 
        def user = userService.getLoggedinUser()
 
        if (user) { 
            try {
                returnMap.username = user.username   
                returnMap.firstName = user.firstName
                returnMap.lastName = user.lastName
                returnMap.fbUrl = user.fbUrl
                returnMap.fbPhotoUrl = user.fbPhotoUrl
                returnMap.primaryEmail = user.primaryEmail?.email
                returnMap.primaryPhone = user.primaryPhone?.phoneNumber
                returnMap.sms = user.sms?.phoneNumber
 
                if (user?.emails) {
                    returnMap.emails = [] 
 
                    user.emails.each { 
                        returnMap.emails << [id: it.id, email: it.email] 
                    }
                }
 
                if (user?.phoneNumbers) {
                    returnMap.phoneNumbers = []
 
                    user.phoneNumbers.each {
                        returnMap.phoneNumbers << [id: it.id, phoneNumber: it.phoneNumber, phoneType: it.phoneType]
                    }
                }
 
                returnMap.success = true
 
            } catch (e) {
                log.error(e)  
                log.error(e.message)
                returnMap.message = e.message
            }
        } else {
            returnMap.success = false
            returnMap.message = 'User Not Found'
        }
        render returnMap as JSON  // return the map as a JSON object to the web request
    }
}

The controller method calls an injected service (userService) to get the user object, then builds a response map & renders it as JSON. Yes, I could have just rendered the user object as JSON, but in this case I did not want to. There are a number of properties I did not want to expose through the API. Also, I wanted to set a success and message property for the API consumer.

Now to test this guy, I need to mock out the userService to return a user object, build the controller, inject the mock into the controller, call the controller method, and finally verify the JSON response. Piece of cake, right?

One of the things I like about Spock is its given, when, then DSL. I’ve found when writing unit tests it helps me organize what I want to do. Ok, given is the stuff I need to setup. When is the do something part. And then is what I want to check.

Ok for the given part, the first thing I need to do is create a user account for the mock to return. In this example, I’m creating the properties I want to verify later as final variables which I’ll use in the assert later.

        //user object for testing
        def final USERNAME = "billyjoejimbob"
 
        //user object for testing
        def user = new User()
        user.username = USERNAME

Next step is to make a mock object for the userService. While Spock comes out of the box with some really nice mocking capabilities, I don’t need anything too complex here. I’m just going to use a little applied Groovage for my mock object. Here in this snippet, I create a map & assign a closure to a map property using the same name as the method my controller will invoke. This will function nicely as my mock to return the user object I want to use for testing.

        //build mock user service
        def userService = [:]
        userService.getLoggedinUser = {return user}

One of the nice things about testing controllers with the Spock pluggin for Grails is it follows a convention to automatically wire up your controller for testing. A Spock class with the name of SomeControllerSpec, will automatically have a ‘controller’ property wired up as a SomeController using the typical Grails mocks. I like this little feature since it helps keep the ceremonial fluff out of your code. Thus, injecting the mock into the controller becomes easy as:

        //inject into controller
        controller.userService = userService

For the when part of the test, I need to call the controller method, then get the response. The response is automagically captured to a ‘mockReponse’ object. In this case, I know my response is JSON. Now, one might be tempted to test the JSON string, but that would have a really bad code smell. I’m more interested in the properties of the JSON object, than I am in the overall string value. So I’m going to slurp that JSON response into a Groovy object.

        //execute controller method
        controller.getUserProfile()
 
        //parse controller response to object
        def jsonSlurper = new JsonSlurper()
        def responseObj = jsonSlurper.parseText(mockResponse.contentAsString)

Now to check the values. One of the cool things about Spock, the then clause of the DSL just looks for statements that evaluate to true. No need to write a bunch of ‘assert’ statements. In this case, I want to test the success property and that my username was set correctly.

        responseObj.success
        responseObj.username == USERNAME

One Spock feature that I didn’t point out was the naming of the test methods. You can write your method names in actual text, which works out nicely for your test reports. Makes the reports FAR more readable than using names like ThisIsSomeUnitTestForWhateverIWantedToTest.

Putting it all together, my test looks like:

    def "Test JSON response of Get User Profile with minimal user object"() {
 
        given:
        //user object for testing
        def final USERNAME = "billyjoejimbob"
 
        //user object for testing
        def user = new User()
        user.username = USERNAME
 
        //build mock user service
        def userService = [:]
        userService.getLoggedinUser = {return user}
 
        //inject into controller
        controller.userService = userService
 
        when:
        //execute controller method
        controller.getUserProfile()
 
        //parse controller response to object
        def jsonSlurper = new JsonSlurper()
        def responseObj = jsonSlurper.parseText(mockResponse.contentAsString)
 
        then:
 
        responseObj.success
        responseObj.username == USERNAME
    }

Since SpringOne, Spock has become my testing drug of choice. Although, I’m still learning its features, I found I was quickly up to speed and productive on the tool.

Share

Jira Studio

11th May 2011 by jt No Comments

I’ve been a big fan of Atlassian and their products for years. I signed up my previous employer onto Jira studio & it worked great. Now I’m on a major project with hundreds of folks using Jira Studio.

The last few days this has been our user experience:

Very unstable. I’ve lost hours of work & its killing the team. I sure hope they get it resolved! And soon!

Share

Gotchas with Groovy Exceptions

8th March 2011 by jt 6 Comments

I ran into a little gotcha with Groovy exceptions today. I seemed like my catch block was not catching the exception type I was throwing in my code.

Lets say I’ve defined my own exception as

class NotFoundException extends Exception {
}

And I have a method call as:

    def getApplication(def params)  {
        def application = Application.get(params?.id)
 
        if (!application) {
            throw new NotFoundException()
        }
        application
    }

In my case this the above is a method in a service which is injected into a Grails controller. In my controller, I want to handle any exceptions that pop, rather than going boom to the web tier. My controller code looks something like this:

    def approve = {
 
        def returnMap = [:]
 
        returnMap.success = true
 
        try {
            def application = applicationService.approve(params)
 
            returnMap.message = "Application for ${application.firstName} ${application.lastName} has been approved."
 
        } catch (NotFoundException e) {
            returnMap.success = false
            returnMap.message = 'Application not found.'
 
            log.error("Failed to find application")
            log.error(params.dump())
 
        } catch (e) {
            returnMap.success = false
            returnMap.message = 'Error updating application. See logs for details'
 
            log.error("Failed to find application")
            log.error(e)
            log.error(e.cause)
 
            e.stackTrace.each {
                log.error(it)
            }
        }
 
        render returnMap as JSON
    }

I want the above code catch the error and provide sometime of informational message to the client by setting the returnMap.message property.

The problem I encountered in my catch block was that it was always falling through to the final catch block. The catch block for the NotFoundExcpetion was getting skipped.

Turns out, the exception was getting thrown as a “UndeclaredThrowableException” and not a NotFoundException. Since the types did not match, my catch block was getting skipped.

The solution to this is to declare the exception on your method. Then the exception will propagate properly. I guess its the price you have to pay for the Groovyness of Groovy.

The corrected code (note the throws declaration) :

    def getApplication(def params) throws NotFoundException {
        def application = Application.get(params?.id)
 
        if (!application) {
            throw new NotFoundException()
        }
        application
    }
Share

Grails Validation Gotcha on Dates

2nd March 2011 by jt 3 Comments

I ran into a little gotcha with Grails and validation today. I was parsing a date from a web post and kept getting a validation error.

I have a ExtJS web form posting a date value as a string:

	02/23/2011	

This format does not get automagically converted to a date.

My original code was as follows:

       def application = new Application(params)
 
        if (params?.accidentDate) {
            application.accidentDate = new Date().parse("MM/dd/yyyy", params.accidentDate)
        } else {
            application.accidentDate = null
        }
 
        application.validate()
 
        if (!application.hasErrors()){
            application.save(failOnError:true)
        }

Fairly simple code. I’m using the parameters map to create a new object. When I got the validation errors, I realized the date format was wrong and added the new date logic.

Seemed simple enough. But I kept getting validation errors on the date.

Field error in object 'com.asf.Application' on field 'accidentDate': rejected value [Wed Feb 23 00:00:00 EST 2011]; codes [typeMismatch.com.asf.Application.accidentDate,typeMismatch.accidentDate,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [com.asf.Application.accidentDate,accidentDate]; arguments []; default message [accidentDate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'accidentDate'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "02/23/2011"]

I banged my head on the desk a few times thinking there was some kind of type mismatch. My domain clearly had a Date property, a I was creating a valid date and setting it. WTF!?! What is not happy about it!

Answer nothing was wrong with with the value I parsed and set. Problem was in creating the application object in the first place. This chunk of code:

def application = new Application(params)

is implicitly calling validate and populating the errors object. Even though I was setting a valid value and calling validate later, the errors object had already been set and was not getting cleared.

Solution:

application.clearErrors()

ta-dah! Works like a champ now!

Full code:

    def submitApplication(def params) {
 
        def application = new Application(params)
 
        application.clearErrors()
 
        if (params?.accidentDate) {
            application.accidentDate = new Date().parse("MM/dd/yyyy", params.accidentDate)
        } else {
            application.accidentDate = null
        }
 
        if (!application.hasErrors()){
            application.save(failOnError:true)
        }
 
        application
    }
Share

ExtJS Combo boxes & Grails

1st March 2011 by jt 3 Comments

The combo boxes in ExtJs are a great web 2.0 component which can be used to create user friendly forms.  In this tutorial, I’m going to show you how to create a combo box drop down in ExtJS using Grails for the backend code.

Here is a screen shot of the component.  You can click on the drop down and get a list, or start typing for a AJAX list of values from the server.

In ExtJS I created the combo box with this code:

{
           xtype: 'combo',
           name: 'state',
           width: 110,
           displayField: 'stateName',
           hiddenValue: 'stateCode',
           store: 'StateStore',
           allowBlank: false,
           forceSelection: true,
           triggerAction: 'all'
      }

The trick to this code is the ExtJS store. The store is defined as:

StateStore = Ext.extend(Ext.data.JsonStore, {
    constructor: function(cfg) {
        cfg = cfg || {};
        StateStore.superclass.constructor.call(this, Ext.apply({
            storeId: 'StateStore',
            root: 'records',
            url: '/state/list',
            idProperty: 'stateCode',
            messageProperty: 'message',
            fields: [
                {
                    name: 'stateName'
                },
                {
                    name: 'stateCode'
                }
            ]
        }, cfg));
    }
});
Ext.reg('stateStore', StateStore);new StateStore();

Notice how I’ve used a relative URL in the code. Also important for my example, I’m using ‘stateCode’ for the id property. This will default to ‘id’ if you do not set it here.

The ExtJS code will expect a JSON string something like this from the server:

{"sucess":true,
 "records":[{"stateName":"North Carolina", "stateCode":"NC"},
                {"stateName":"North Dakota","stateCode":"ND"}
]}

Using Grails makes it incredibly easy to render this response for ExtJS. First off, I recommend setting your application name to a slash in application.properties (not a slash with quotes). This will setup grails to run in the root context of tomcat (8080:/ vs 8080:/yourappname). This will save you some trouble if you’re going to deploy behind Apache in your production env.

My domain class in Grails is pretty simple:

class State {
    String stateCode
    String stateName
 
    static constraints = {
        stateCode(unique:true, blank:false, nullable:false)
        stateName(blank:false, nullable:false)
    }
 
    static mapping = { id column: 'stateCode'}
 
    String toString() {
        return stateCode
    }
}

I like to load my data in the bootstrap as follows:

        if (State.count() == 0) {
            loadStates()
        }
. . .
 
def loadStates() {
 
        println "loading state codes"
 
        new State(stateCode: 'AL', stateName: 'Alabama').save()
        new State(stateCode: 'AK', stateName: 'Alaska').save()
        new State(stateCode: 'AR', stateName: 'Arkansas').save()
        new State(stateCode: 'AZ', stateName: 'Arizona').save()
        new State(stateCode: 'CA', stateName: 'California').save()
        new State(stateCode: 'CO', stateName: 'Colorado').save()
        new State(stateCode: 'CT', stateName: 'Connecticut').save()
        new State(stateCode: 'DC', stateName: 'D.C.').save()
        new State(stateCode: 'DE', stateName: 'Delaware').save()
        new State(stateCode: 'FL', stateName: 'Florida').save()
        new State(stateCode: 'GA', stateName: 'Georgia').save()
        new State(stateCode: 'HI', stateName: 'Hawaii').save()
        new State(stateCode: 'IA', stateName: 'Iowa').save()
        new State(stateCode: 'ID', stateName: 'Idaho').save()
        new State(stateCode: 'IL', stateName: 'Illinois').save()
        new State(stateCode: 'IN', stateName: 'Indiana').save()
        new State(stateCode: 'KS', stateName: 'Kansas').save()
        new State(stateCode: 'KY', stateName: 'Kentucky').save()
        new State(stateCode: 'LA', stateName: 'Louisiana').save()
        new State(stateCode: 'MA', stateName: 'Massachusetts').save()
        new State(stateCode: 'MD', stateName: 'Maryland').save()
        new State(stateCode: 'ME', stateName: 'Maine').save()
        new State(stateCode: 'MI', stateName: 'Michigan').save()
        new State(stateCode: 'MN', stateName: 'Minnesota').save()
        new State(stateCode: 'MO', stateName: 'Missouri').save()
        new State(stateCode: 'MS', stateName: 'Mississippi').save()
        new State(stateCode: 'MT', stateName: 'Montana').save()
        new State(stateCode: 'NC', stateName: 'North Carolina').save()
        new State(stateCode: 'ND', stateName: 'North Dakota').save()
        new State(stateCode: 'NE', stateName: 'Nebraska').save()
        new State(stateCode: 'NH', stateName: 'New Hampshire').save()
        new State(stateCode: 'NJ', stateName: 'New Jersey').save()
        new State(stateCode: 'NM', stateName: 'New Mexico').save()
        new State(stateCode: 'NV', stateName: 'Nevada').save()
        new State(stateCode: 'NY', stateName: 'New York').save()
        new State(stateCode: 'OK', stateName: 'Oklahoma').save()
        new State(stateCode: 'OH', stateName: 'Ohio').save()
        new State(stateCode: 'OR', stateName: 'Oregon').save()
        new State(stateCode: 'PA', stateName: 'Pennsylvania').save()
        new State(stateCode: 'RI', stateName: 'Rhode Island').save()
        new State(stateCode: 'SC', stateName: 'South Carolina').save()
        new State(stateCode: 'SD', stateName: 'South Dakota').save()
        new State(stateCode: 'TN', stateName: 'Tennessee').save()
        new State(stateCode: 'TX', stateName: 'Texas').save()
        new State(stateCode: 'UT', stateName: 'Utah').save()
        new State(stateCode: 'VA', stateName: 'Virginia').save()
        new State(stateCode: 'VT', stateName: 'Vermont').save()
        new State(stateCode: 'WA', stateName: 'Washington').save()
        new State(stateCode: 'WI', stateName: 'Wisconsin').save()
        new State(stateCode: 'WV', stateName: 'West Virginia').save()
        new State(stateCode: 'WY', stateName: 'Wyoming').save(flush: true)
 
    }

Here is the closure code for my StateController class. This will get invoked for requests to /state/list.

    def list = {
        def returnMap = [:]
 
        def recordList = []
 
        returnMap.sucess = true
 
        try {
 
            if (params.query) {
                State.findAllByStateNameIlike("%${params.query}%").each {
                    recordList << [stateName: it.stateName, stateCode: it.stateCode]
                }
            } else {
                State.list().each {
                    recordList << [stateName: it.stateName, stateCode: it.stateCode]
                }
            }
 
            returnMap.records = recordList
        } catch (e) {
            returnMap.sucess = false
            returnMap.message = 'Error getting state list'
 
            log.error("Failed to get state list")
            log.error(e)
        }
 
        render returnMap as JSON
    }

In this, I create a map for my return and set the success property = true. Later you will see that is it trivial to convert a map into a JSON string.

I also create a list variable which I will load with records from my database query, which will get assigned as a property in my return map object.

From ExtJS, I can get either no query value, or a value called query, which is what the user typed. In my example if I do receive a query value (params.query), I use a dynamic finder to find all records in a case insensitive search (State.findAllByStateNameIlike(“%${params.query}%”) ) Otherwise, I just use the .list() method to get all the state records. In either case, I walk the result set and assign map values for each record to the list using the shift operator.

The last part of the magic is using render returnMap as JSON. This converts my map into a JSON object for ExtJS.

Cheers,

JT

Share

Batch SQL Operations in Groovy

15th February 2011 by jt 5 Comments

Over the last few weeks I’ve been playing with the SQL capabilities in Groovy. Compared to hand rolling JDBC, Groovy is wonderful. Its simple, easy and straight forward.

This week I had a loop running over a SQL update statement. The performance rather disappointing for large operations. I was seeing about 1000 updates per minute. This was code executing off my local iMac, hitting a dev database a remote data center.

My code looked something like this:

records.each {
        conn.executeUpdate("UPDATE my_table set my_column = false where id = ?", [it[0]])
  }

This code was forcing a round trip to the server with each execution. The slow performance was mostly network overhead.

The 1.7 release of Groovy added batch updates. This allows the SQL statements to be sent to the database server in batches.

I can refactor my code as follows:

conn.withBatch { stmt -&gt;
      records.each {
          stmt.addBatch "UPDATE my_table set my_column = false where id = ${it[0]}"
          }
      }

The results? This will update about 25,000 records per minute (vs 1,000). I’d call that a significant difference!

A couple quick notes:

  • You do not need to call execute on this; it is done automatically.
  • All the statements in the closure ‘withBatch’ will be assigned a transaction.  If any go boom, the transaction will get rolled back.
  • You can adjust the batch size via “conn.withBatch (2000) { stmt ->” (where 2000 is the batch size).  In my testing a batch size of 10 was slow, 100 reasonable, 200 was about the same as the default (I could not find documentation on what the default value actually is)
  • Your mileage WILL vary.
Share

Building a Grails App – Session 1

6th February 2011 by jt 13 Comments

I recently wrote a small Grails application for a local legal firm to help them track their time and expenses on clients.  I’ve decided to re-create the application in a video tutorial series.  It was a fun little app to write.  I was able to a number of different plugins, like Spring Security Core, jQuery UI, and Blue Print CSS.

Below is the first installment in the series. This is my first shot at creating a video tutorial.  Please let me know what you think!

Also – code for this series is on Google code:  http://code.google.com/p/jts-blog/

Share

Patching 11g

14th October 2010 by jt No Comments

I was patching an 11g database today. You’d think Oracle would have cleaned this up by now…

SQL> -- The following is a kludge, because the servlet.jar and xdb.jar files
SQL> -- are part of the XDB component, and they shouldn't get loaded
SQL> -- by the XML component (aka XDK).
SQL> -- But the problem is that XSU (part of XDK)
SQL> -- depends on the XMLType, and that is part of XDB.
SQL> -- Ideally what we want is a separate jar file
SQL> -- to load the XMLType and nothing else,
SQL> -- so that we don't have to load the entire XDB here.
SQL> -- As of rdbms version 10.1.0.2, this bit of the XDB
SQL> -- will _not_ get loaded again when catjava.sql calls catxdbj.sql
SQL> -- (it has been commented out).
SQL> -- Please note that in rdbms version 9.2.0,
SQL> -- we loaded servlet.jar and xdb.jar in file initxml.sql,
SQL> -- so it _is_ a proven method.
SQL> -- xmlparserv2.jar depends on XMLType.jar from xdb.jar
SQL>
Share