Spicefactory - Part 2: Add Pimento to your Grails dish!

Maarten Winkels

This second part on Spicefactory will delve into the details of writing a Grails plug-in for this framework. Be prepared to read a lot of code!

Let's try to gel it together with Grails.

JPA

To start with, Pimento relies on an EntityManager exposed through Cinnamon Servlet. Grails doesn't usually have an EntityManager, but it uses Hibernate, which comes with an implementation. Pimento configuration is based on spring on the server-side, so I assumed that adapting the configuration to use the SessionFactory configured by Grails should not be to difficult.

Pimento ships with the file pimento-spring.xml, which configures the backend for pimento. This file uses a cinnamon specific namespace for spring to define which services to expose. Furthermore it relies on springs annotation configuration to inject the EntityManagerFactory into some beans. This makes it all the harder to integrate into Grails. Most of the configuration in this file, we want to leave as-is, especially the cinnamon related stuff. What we want to change is the definition of the EntityManagerFactory. The pimento configuration uses springs implementation for LocalEntityManager lookup, that will search persistence.xml on the classpath. Now in a Grails application, persistence is configured by the core plugins and we don't want to interfere with that. Luckily hibernate contains another implementation of EntityManagerFactory, that can be injected with a pre-configures SessionFactory. Thus, we replace the EntityManager configuration with the following XML snippet:


  
  
    
  
  
  

This configuration will take Grails' preconfigured SessionFactory and wrap it in an EntityManagerFactory, that can be used by Pimento.

Runtime Web Application Configuration

Now we need to make some changes to the configuration of our web application. The easiest way to accomplish this with Grails is to package the functionality in a plug-in and use the runtime configuration extensions point to make the changes. So, using grails create-plugin spicefactory a grails plug-in project is created, to which we can add the necessary functionality.

First we need to configure the CinnamonServlet. For that we need some SpiceFactory jars on the classpath, so we copy those to the lib folder. This will put them on the grails classpath of any project using this plug-in. Now we need to change the web.xml. This can be done from the main plug-in file, SpicefactoryGrailsPlugin.groovy:

  def doWithWebDescriptor = { xml ->
    // servlets
    def servlets = xml.servlet
    servlets[servlets.size() - 1] + {
      servlet {
        'servlet-name'("Cinnamon")
        'servlet-class'("org.spicefactory.cinnamon.web.CinnamonServlet")
        'init-param' {
          'param-name'("configLocation")
          'param-value'("spring")
        }
        'load-on-startup'("1")
      }
    }

    // servlet mappings
    def servletMappings = xml.'servlet-mapping'
    servletMappings[servletMappings.size() - 1] + {
      'servlet-mapping' {
        'servlet-name'("Cinnamon")
        'url-pattern'("/service/*")
      }
    }
  }

This will add the CinnamonServlet to the web.xml.

ApplicationContext manipulation

In a similar fashion, we would like to load the spring configuration file that we have adapted from pimento-spring.xml. By putting the file in grails-app/conf, it will be loadable from the classpath. But how do you add these beans to the grails application context?

The first concern is to load the context at the right moment: We are depending on the SessionFactory to be configured before we can initialize our ow beans. This can be indicated in the main plug-in file:

  def dependsOn = [hibernate:GrailsPluginUtils.grailsVersion]

Now our plug-in will be loaded and configured after the hibernate plug-in, which will configure the SessionFactory.

The second concern is loading the XML configuration. The SpicefactoryGrailsPlugin.groovy has a similar section for ApplicationContext interception. In that part a BeanBuilder is available. This is very useful if you want to load beans fro a .groovy file. Unfortunately, loading beans from an XML file is not as well supported. We have a cinnamon namespace in the XML, which allows for easy configuration of the exposed services. Similarly, the <context:annotation-configuration/> is used to inject the EntityManagerFactory. Converting this to Grails' BeanBuilder style configuration would be rather hard. After searching around for a few hours, I found this solution, which seems to work:

  def doWithSpring = {
    new XmlBeanDefinitionReader(
      getSpringConfig().getUnrefreshedApplicationContext()
    ).loadBeanDefinitions("classpath:pimentoSpringBeans.xml");
  }

Since we have a BeanPostProcessor in the XML, we need an ApplicationContext to load it. Also you have to be careful not to refresh the ApplicationContext: The implementation that is being used can only be refreshed once and the Grails framework will do it when the application is fully configured.

SWC files

When using Pimento, you need the frameworks SWC files available to the flex compiler. There are several ways to compile SWF. I prefer using the web-tier compiler with grails, since this allows for easy recompilation and integration with your grails application. The web-tier compiler is also included in the Flex plug-in for Grails, but this plug-in contains a lot of other features as well and the version of the compiler is pretty old. Therefor I've first created a Grails plug-in that will only install the web-tier compiler. This plug-in is attached to this blog.

Now the spicefactory plug-i can be used without the web-tier plug-in, if you put the compiled SWFs in the web-app folder. Nevertheless, to enable using it with the web-tier compiler, the necesssary SWC files are copied to the /web-app/WEB-INF/flex/user_classes directory, so the web-tier compiler will pick them up when compiling your MXML files.

Conclusion

The resulting grails-spicefactory plug-in is attached to this blog. Applications that use it will have to add spicefactory annotations to the groovy domain classes they want to expose and write AS copies of those classes as described in this blog. With this in place, the AS3 EntityManager can be used from the Flex application to manipulate the database.

Happy AS3 coding!

Comments (0)

    Add a Comment