Judging by the steady flow of traffic to this blog, there's a reasonable amount of interest in accessing Grails enhanced Groovy Objects in Java. The good news is, that since Grails 1.0, this has got significantly easier.

Precompilation makes it simpler

The Java on Grails series shows how to take full advantage of dynamic Grails functionality in Java. But for many cases it may be taking a sledge hammer to crack a nut. Since Grails 1.0 (or maybe slightly earlier), it's been possible to precompile Grails classes. This means you do not have to bridge the great classloader divide. Your Grails classes can be loaded and managed by the same Java classloaders as the rest of your app. Which of course means that you can make direct calls to your magic Gorm classes, but not take advantage of advanced Groovy features in the same way. But there are plenty of ways to skin the dynamic cat. E.g. You can hide your dynamic groovy code behind an interface and groovy implementation. Your Groovy impl class would do all the dynamic stuff (finders, closures, dsls etc). And if that solution is overkill for your needs you can even use Java directly to take advantage of the Groovy MetaClass. It's just a little less pretty.


Author author = new Author();
author.getMetaClass().invokeMethod("save",new Object[]{});

You can, and should, hide the MetaClass related code behind helper methods. Java static imports can help beautify this...


Author author = new Author();
save(author);

You don't even have to use Groovy (much)

There's a new version of the Groovy Eclipse plugin that has refactoring support that I'm really looking forward to using. But, if you're an eclipse user, thus far refactoring Groovy code has been a manual process (IDEA users have had Groovy refactoring support for some time). For this reason, or perhaps due to company policy, you may not be allowed to use Groovy. The good news you can still use Grails! A precompiled Java class is the same as a precompiled Groovy class. You just need to make sure that you add a Lond id and Long version property to your Gorm code manually. You're still better of making use of Groovy to define your constraints, but even that's just a case of...


static Closure constraints = constraintsFor(this.getClass());

You would then define the constraints for all your Gorm classes in a single (or a few Groovy files). This gives you all the advantages of Gorm configuration / finders & Grails plugins that use Gorm, in Java. Although, in terms of configuration, just Hibernate annotations directly (& Spring), is actually quite nice to use. But you've got the overhead of setting up the infrastructure for both Hibernate and Spring - which Grails manages for you. And indirectly configuring proxies for transactions in XML, is not as nice as have them managed transparently in Grails or demarcating them with Closures, imho..

*Vote for or against this entry on DZone*

One of the (unfounded) criticisms of my recent Method Missing post was the assertion that it wasn't possible to create a Groovy / Ruby style Markup Builder in Java. It may be difficult to see how from the original article, so we'll create one in this post step by step - while also addressing the performance issue raised by Murphee in the comments of the previous post.

Desired Usage

The goal is to create a Simple Markup Builder that could be extended, should you wish into something like the Groovy markup builder.

a = a.parent(); {
        a = a.nestedChild();{
                a.sibling1();
                a.sibling2("hello world");
        }
}

It should be possible for client code of the markup builder to look something like the above - which would correspond to the following markup :
<parent>
    <nestedChild>
       <sibling1></sibling1>
       <sibling2>hello world</sibling2>
    </nestedChild>
</parent>
Because it's Java each node must be defined in an interface - but because the markup nodes are unknown to us - the API developers, we must leave the specification of that node up to the API user. And yes, I know - Groovy and Ruby are _much_ more elegant!!

Slightly modified Proxy

In this example we'll use a slightly modified version of the proxy from MethodMissing. Instead of waiting for the desired method not to be found on our delegate (a relatively expensive operation that involves throwing and catching an exception) - we'll directly call a groovy style 'invoke' method.

public class Invoker implements java.lang.reflect.InvocationHandler  {

                DynamicMethod delegate;
                public Invoker(DynamicMethod delegate){
                        this.delegate=delegate;
                }
                
                /* (non-Javadoc)
                 * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
                 */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // TODO Auto-generated method stub
                        Object result = null;
                
                           
                         result = delegate.invoke(method, args);
                        
                        if(result==delegate)
                                result = proxy;
                        
                        return result;
                }

                public static T newInstance(DynamicMethod method) {
                        return (T)java.lang.reflect.Proxy.newProxyInstance(
                            method.getInterfaces()[0].getClassLoader(),
                            method.getInterfaces(),
                            new Invoker(method));
                    }
                
        }

We also define an interface DynamicMethod that facilitates this (defines the invoke method)

public interface DynamicMethod {

        public T invoke(Method method,E... args);
        public Class[] getInterfaces();
}

Note that in order for our Builder to return an Object that has the user defined methods available we need it to have access to the interfaces supplied by the user. Hence the getInterfaces method.

Now, let's write our Builder

Our builder will, very simply, use the method name supplied on invoke to create a new Node of that name. It also returns a new proxied Builder as the return type. Calls to this new Builder result in child nodes being appended as opposed to Siblings.

public class Builder implements DynamicMethod{

        Node node;
        Class[] interfaces;
        public Builder(String parentNodeName,Class... interfaces){
                node = new Node(parentNodeName);
                this.interfaces = interfaces;
        }
        
        public Builder(Class... interfaces) {
                this.node = new Node(null);
                this.interfaces = interfaces;
        }
        public Builder(Node n ,Class... interfaces) {
                this.node = n;
                this.interfaces = interfaces;
        }

        /* (non-Javadoc)
         * @see dyn.DynamicMethod#invoke(java.lang.reflect.Method, E[])
         */
        public Object invoke(Method method, Object... args) {
                // TODO Auto-generated method stub
                
                Node n = new Node(method.getName());
                node.children.add(n);
                if(args!=null && args.length>0){
                        String content = (String)args[0];
                        //could take attributes from later args..
                        n.setValue(content);
                }
                
                return Invoker.newInstance(new Builder(n,interfaces));
        }

        
        
        public String toString(){
                return node.toString();
        }
        class Node{
                
                List children = new ArrayList();
                String name;
                String value;
                public Node(String name) {
                        super();
                        this.name = name;
                }
                
                public String toString(){
                        StringBuilder builder = new StringBuilder();
                        if(name!=null){
                                builder.append("<" + name +">");
                                if(value==null){
                                for(Node n : children){
                                        builder.append(n.toString());
                                }
                                }else{
                                        builder.append(value);
                                }
                                builder.append("</" + name +  ">");
                        }else{
                                builder.append(children.get(0));
                        }
                        return builder.toString();
                }

                /**
                 * @param value the value to set
                 */
                public void setValue(String value) {
                        this.value = value;
                }
        }
        /**
         * @return the interfaces
         */
        public Class[] getInterfaces() {
                return interfaces;
        }
}

And that's the API done - now for the client!

Client / Application Code

The client code can be written completely independently of the API. The API does not need to know about the possible tags in advance. The only constraint on client developers is that for each method they call, they also generate an interface method (ctl-1 in Eclipse will do this for you automatically!). Our main method is like so, and this is all the code a client user would have to write (the API developer having jumped throught the proxy hoops for them).

public static void main(String[] args){
                Builder xml = new Builder(Markup.class);
                Markup a = Invoker.newInstance(xml) ;
                a = a.parent(); {
                        a = a.nestedChild();{
                                
                                                a.sibling1();
                                                a.sibling2("hello world");
                        }
                }
                System.out.println(xml.toString());
        }

In dynamic programming in Java, the programmer who writes the call to the dynamic method has the responsibilty for defining the interface - beyond that everything can be fixed with a layer of indirection & reflection in the Proxy and Delegate.

Markup is the interface in which we define the markup elements we want to use.

public interface Markup {

        Markup sibling1();
        Markup sibling2();
        Markup parent();
        Markup nestedChild();
        Markup sibling2(String string);

}

And the output

<parent><nestedChild><sibling1></sibling1><sibling2>hello world</sibling2>
</nestedChild></parent>

Please note this is a very simple demonstrative example, you could make this a lot more powerful and easier to use (e.g. xml.getMarkup() etc. ).

Update : A Simple Markup Builder in Java using these techniques

Java can be surprisingly dynamic if you're willing to push it a little, and put up with the fact that everything still needs to be defined in an interface. It is reasonably straightforward to get a Java class to handle a method that doesn't exist using dynamic proxies (this is how Java-On-Grails works). You just need to define an interface that represents the dynamic methods - ctl-1 in Eclipse is your friend here (simply write the call as you would in Groovy or Ruby - then get eclipse to generate the method stub in your interface automatically).

MethodMissing

The code below demonstrates how to implement MethodMissing in Java. The first step is to create Dynamic Proxy class. This will intercept all dynamic calls. If the method called does not exist on the delegate Object - MethodMissing will be called instead.

public class Dynamic implements java.lang.reflect.InvocationHandler  {

        Object delegate;
        public Dynamic(Object delegate){
                this.delegate=delegate;
        }
        
        
        public Object invoke(Object proxy, Method method, Object[] args) 
                           throws Throwable {
                Object result = null;
                try {
                   
                    result = method.invoke(delegate, args);
                } catch (InvocationTargetException e) {
                        result = 
                  ((MethodMissing)delegate).methodMissing(method,args);
                } catch (Exception e) {
                    result = 
             ((MethodMissing)delegate).methodMissing(method,args);

                } finally {
                    
                }
                if(result==delegate)
                        result = proxy;
                
                return result;
        }

        public static T newInstance(Object o,Class... interfaces) {
                return (T)java.lang.reflect.Proxy.newProxyInstance(
                    interfaces[0].getClassLoader(),
                    interfaces,
                    new Dynamic(o));
            }
        
}


Next we define a MethodMissing interface that any class that wants to handle missing methods can implement..

public interface MethodMissing {

        public T methodMissing(Method method,E... args);
        
}

A very simple example of a Dynamic class taking advantage of MethodMissing

public class Ruby implements MethodMissing{

        
        public Object methodMissing(Method method, Object... args) {
                System.out.println(method.getName());
                return this;
        }

        public static void main(String[] args){
                IDynamic dynamic = 
      Dynamic.newInstance(new Ruby(), IDynamic.class);
                
                dynamic.meow().woof();
                dynamic.woof();
                
        }
                
}
public interface IDynamic extends MethodMissing{

        public IDynamic woof();
        public IDynamic meow();
}

Output on the console will be...

meow
woof
woof

Improving existing APIs

We can use MethodMissing and delegation to enhance existing classes. E.g. to add a Groovy-like each method to our lists.

public class SuperList implements MethodMissing{

        List list;
        
        public SuperList(List list) {
                super();
                this.list = list;
        }

        public Object methodMissing(Method method, Object... args) {
                Object result = null;
                if(method.getName().equals("each")){
                        each((Callback)args[0]);
                }
                        else{
                 try { result = method.invoke(list, args); 
                    } catch (Exception e) { }
                                        
                        }
                        
                 return result;
        }
        
        public void each(Callback c){
                for(T next : list){
                        c.call(next);
                }
        }
        
        public static void main(String[] args){
        
                DynamicList dynamic = 
Dynamic.newInstance(new SuperList( new ArrayList()), DynamicList.class);
                dynamic.add("hello");
                dynamic.add("world");
                dynamic.each(new Callback(){
                        public void call(Object o) {
                                System.out.println(o);
                                
                        }       
                });
                
                
        }
}

public interface DynamicList extends List, MethodMissing{

        public void each(Callback c);
}

public interface Callback {

        public void call(T o);
}


Output on the console in this case will be...

hello
world

I've just started working on a simple groovy script to automate something we currently do by hand, and the realisation hit me - that everyone in the surrounding pods is also working with Groovy right now..

Who'd have thought a year ago...

An update to the lineup at the IJTC via Jakub. Joel Spolsky is to give the keynote at the opening of the inaugral Irish Java Technology Conference. Great stuff!

IrishDev.com in conjunction with DubJug (the Dublin JUG) have organised the inaugral IJTC conference. The action takes place Wednesday and Thursday two weeks from now (7th and 8th of November). I've been out of the country for last couple of months, so this looks like a great way to catch up on the latest IT developments.

There's an awesome array of speakers lined up including Open Source legend James Strachan, Groovy Project lead and entreprenuer Guillame Laforge, the David McWilliams of Irish tech Paul Browne as well as speakers from Interface 21, Apache, Sun, Microsoft, Iona, JBoss, Oracle and others.

I'm looking forward to Emmanuel Bernard's Hibernate Search talk, as well as Guillame Laforge's Groovy and Grails section. Actually there's a ton of stuff that looks unmissable including Kevin Noonan's Jabber and messaging talk, and of course beer in a Dublin hostellery!

You can check out the full event listing at the link below :-

Refreshingly, the whole conference is priced at a manager friendly €189. Which I'm led to believe may also include vouchers for beer - it just doesn't get any better than that!

P.S. Join DubJug for free for a discount on the €189 cost.

Short term contract from the mailing list : grails job

With entries from Andrew on Maven, Struts 2 and more..

Worth a look :- http://www.development.ie/blog/
I've fixed a couple of minor issues with the Java on Grails code base. You can download the latest version from here.

Example setup code

public abstract class GormConfig{

private String modelsPath = "classpath*:**grails-application/**/*.groovy";
private String daoName = "Access";
private Map dataSource; //your data source properties
private String modelsPackage = "com.my.model.interfaces";
private String staticsPackage = "com.my.static.interfaces";
private List process;
protected Logger logger = Logger.getLogger(this.getClass());
Grails grails;

public void setup() {



        GrailsApplication grailsApplication = null;
        SessionFactory sessionFactory = null;

        PathMatchingResourcePatternResolver resolver = 
                        new PathMatchingResourcePatternResolver();

        Resource[] groovyFiles;


        try {
                groovyFiles = resolver.getResources(modelsPath);
                grailsApplication = new DefaultGrailsApplication(
                                     groovyFiles, 
                                     new MyInjectionOperation());
                } catch (IOException e) {
                        
                        logger.error("Problem compiling Grails"+ 
                                        "resources");
                        logger.debug(e.getMessage(),e);
                }
        grailsApplication.initialise();
        DefaultGrailsDomainConfiguration config = 
                        new DefaultGrailsDomainConfiguration();
        config.setGrailsApplication(grailsApplication);

        Properties props = new Properties();
        
        for(String key : dataSource.keySet()){
                props.put(key, dataSource.get(key));
        }

        config.setProperties(props);
        sessionFactory = config.buildSessionFactory();
        HibernateInterceptor.setSessionFactory(sessionFactory);
        Collection dynamicMethods = 
               GrailsHibernateUtil.configureDynamicMethods(
                            sessionFactory, grailsApplication);

        for (Iterator i = dynamicMethods.iterator(); i.hasNext();) {
            DomainClassMethods methods = (DomainClassMethods) i.next();
            PlatformTransactionManager ptm = 
                   new HibernateTransactionManager(sessionFactory);
             methods.setTransactionManager(ptm);

        }
        

        GroovyClassLoader cl = grailsApplication.getClassLoader();
        IAccess access;
        try {

         access = (IAccess) cl.loadClass(daoName,false,true).newInstance();
         grails = new Grails(access,modelsPackage,
                                   staticsPackage);
         //run a script .e.g. Main
         Script main = (Script) cl.loadClass("Main",false,true).newInstance();
         main.run();


        } catch(Exception e){
           logger.error(e.getMessage(),e);
           logger.error("Problem instantiating domain models, exiting..");
           System.exit(1);
        }




}

Example model interface

package com.my.model.interfaces;
public interface IUser extends IModel{

        
         public String getUsername();
         public String getPassword();

        
}

Example static model interface

package com.my.static.interfaces;
public interface User extends IStaticInterface {
        public IUser findByUsername(String username);
}


Hibernate dynamic methods setup

You'll also need to call this Groovy code (from GORM outside Grails) somewhere. The easiest way is to drop the code in with your Groovy code and call it in your GormConfig class like so..


         IHibernateMethods methods = (IHibernateMethods)
                               cl.loadClass("GormLoader",
                               false,true).newInstance();
         methods.doDynamicMethods(grailsApplication);



   // from HibernateGrailsPlugin.doWithDynamicMethods
   void doDynamicMethods(application) {

      GrailsHibernateUtil.configureDynamicMethods( sessionFactory, application )

      application.domainClasses.each { dc ->

         dc.persistantProperties.each { prop ->

            if ( prop.oneToMany || prop.manyToMany ) {

               if ( dc.metaClass instanceof ExpandoMetaClass ) {

                  def collectionName   = 
                     "${prop.name[0].toUpperCase()}${prop.name[1..-1]}"

                  def otherDomainClass = prop.referencedDomainClass

                  dc.metaClass."addTo${collectionName}" = { Object arg ->

                     Object obj

                     if ( delegate[prop.name] == null ) {

                        delegate[prop.name] = 
                           GrailsClassUtils.createConcreteCollection( prop.type )
                     }

                     if ( arg instanceof Map ) {

                        obj = otherDomainClass.newInstance()

                        obj.properties = arg

                        delegate[prop.name].add(obj)
                     }
                     else if ( otherDomainClass.clazz.isInstance(arg) ) {

                        obj = arg
                        delegate[prop.name].add( obj )
                     }
                     else {

                        throw new MissingMethodException( 
                           dc.clazz, "addTo${collectionName}", [arg] as Object[] 
                        )
                     }

                     if ( prop.bidirectional ) {

                        if ( prop.manyToMany ) {

                           String name = prop.otherSide.name

                           if ( !obj[name] ) {

                              obj[name] = 
                                 GrailsClassUtils.createConcreteCollection( 
                                    prop.otherSide.type 
                                 )
                           }

                           obj[prop.otherSide.name].add( delegate )
                        }
                        else {

                           obj[prop.otherSide.name] = delegate
                        }
                     }
                     delegate
                  }

                  dc.metaClass."removeFrom${collectionName}" = { Object arg ->

                     if ( otherDomainClass.clazz.isInstance(arg) ) {

                        delegate[prop.name]?.remove( arg )

                        if ( prop.bidirectional ) {

                           if ( prop.manyToMany ) {

                              String name = prop.otherSide.name

                              arg[name]?.remove( delegate )
                           }
                           else {

                              arg[prop.otherSide.name] = null
                           }
                        }
                     }
                     else {

                        throw new MissingMethodException(
                           dc.clazz, "removeFrom${collectionName}", [arg] as Object[]
                        )
                     }
                     delegate
                  }
               }
            }
         }
      }

   }


Previously on Java on Grails, visionary Gorm Objects teleported from Grails into Javaland and learnt how to make use of their powerful static finder methods. Our heroes have other powers, more personal to them - such as the ability to perist themselves or even to disappear. We can help them use these powers directly from Java.

In order to access the Gorm dynamic finder methods in Java, we created a dynamic proxy that dynamically called the appropriate static method on the Groovy Metaclass for the Object. Instead of linking method calls to methods at compile time, like Java, Groovy provides an extra layer of indirection. The actual method to be called is looked up at run time. This allows developers - such as the Grails team - to add methods to Objects that do not exist at compile time. These new methods are stored in the Metaclass, In order to provide our Gorm objects with nice persistent helper methods such as save(), delete() or validate() we will proxy them and call the appropriate instance method via the Metaclass for that Object. We will automatically proxy them as they are retrieved from the ORM framework (via the powerful Static methods we enabled last week) - invisibly to the application developer.

You can download the source code for the Java On Grails mini-framework from here, and a demo app from here. - NB the jars contain the source, not the classes, ZIP uploads are not supported on JRoller. The demo app is heavily based on code by Jeremie Weldin - the pioneer in this area.

Getting started

In order to reference our Grails Objects we need to define an interface inheritance heirarchy that contains the methods we would like to make available to our Java classes. At the top of this hierarchy is a base class (org.java.on.grails.interfaces.IModel) that defines the Gorm instance methods. We should also define an interface that extends IModel that contains each of the instance methods on our Gorm object we would like to access.

We also need to tell Java on Grails which of our Grails classes are domain models - we can do this by having them implement the IGorm tagging interface (or by adding the @GORM annotation if you are using Groovy 1.1 - NB this functionality is untested atm).

We need to modify the behaviour of our DAO slightly. Our DAO interface (org.java.on.grails.interfaces.IAccess) now contains a method public List getAvailableModels() - which we must implement. This should simply return a list of our Domain Model class names (["Book","Author"] etc). Our DAO should define a closure keyed on the Domain Class name in the access map that instantiates an instance of each Domain Model. Remember that the DAO lives in the Grails world, and this is how we will create instances of our Grails models.

def access = [


                Book : {new Book()}


        ]

Java on Grails provides a handy configuration class called Grails. You can create an instance simply as follows

        IAccess access = (IAccess)cl.loadClass("Access",false,true)
                                                     .newInstance();

        Grails grails = new Grails(access,"com.models","com.statics");

It takes three constructor parameters - our DAO instance, and two string package names in which it will look for the interfaces that define the methods we want to make available in Java. Java on Grails defines an interface that allows you to implement different strategies for interface resolution (org.java.on.grails.interfaces.IInterfaceResolver), or you can just configure them manually. By default Java on Grails will look in the package specified for a class with the following name .. So for our Book model it will use the interface com.models.Book as the interface that defines the instance methods to be added, and the interface com.statics.Book as the interface that defines the static methods we wish to use for our Book. The Grails class will automatically configure Java on Grails and populate a map with our Static finder instances.

Grails grails = new Grails(access,"com.models","com.statics");
com.statics.Book Book = (com.statics.Book)grails.getStatics().get("Book");

List<Book> books = Book.list();

for(Book book : books){

        System.out.println("Book : " + book.getTitle());
        book.setTitle(book.getTitle() + " changed");
        System.out.println("Book changed : " + book.getTitle() );
        book.save();
}

Handling relations

Lazy loading won't work until we create and initialise a HibernatePersistenceContextInterceptor with our SessionFactory. Grails does this work itself for you, in a servlet filter. You will create a SessionFactory as part of the GORM / Hibernate configuration process - take a look at Test.groovy in Jeremie Weldin's GORM without Grails tutorial.

 

  HibernatePersistenceContextInterceptor interceptor = 
        new HibernatePersistenceContextInterceptor();
  interceptor.setSessionFactory(sessionFactory);
  try { 
     
     interceptor.init();
     //do gorm work here
     //if in a filter -- > chain.doFilter(request, response);
  }
  finally {
    interceptor.destroy();
  }

Disclaimer

Please view the code supplied as more of a how-to, than a certified production ready framework. If you are using the code, and have any issues, please let me know and we can update the codebase!

Resources

Jeremie Weldin's GORM outside of Grails' tutorial Java on Grails pilot Java on Grails : Genesis episode 2

Downloads

Java on Grails mini-framework Java on Grails demo app
Note the source is stored in jars due to upload file extension restrictions.

Groovy 1.1 Beta has support for annotations and Grails 0.5 comes with support for additional Collections (e.g. Lists) in GORM (compositions also worth mentioning!)..

Cool..

When we last saw our heroes, the first brave Grails' objects were fumbling about in the Java world, lost without their powers. The next step in our intrepid Objects' epic journey, however, will be to discover how to use and control their GORM powers while in Javaland.

Let's define a simple Grails domain model consisting of a Book Object. As the Book Object is compiled by the Grails class loader we can't define references to the class in our Java classes. We could however define an IBook interface and have the Grails Book implement it. In fact, as they take their first baby steps in the Java world, we will have our Gorm objects directly implement a simple interface so that we can reference them e.g.


class Book implements IBook{
    
        String title


}
public interface IBook{

        public String getTitle();
        public void setTitle(String title);
}

There is, however, a major problem with this approach. There are many methods available on the Book object that won't be there at compile time, this may cause the Grails compiler to barf. A better approach is to have a Dynamic proxy implement the interface and call our Groovy Object. This way we can call any of the dynamic Gorm methods we wish. And we will do this, but for simplicity - not yet.

Getting started down the dynamic road


The simplest place to start is probably with the static methods available on GORM Classes. First let's define an interface that includes all of the common base finder methods..

public interface IStatic<DomainType,IDType> {

                public Integer count();
                public Integer countBy(String criteria,Object... args);

                public grails.orm.HibernateCriteriaBuilder createCriteria();

                public Boolean exists(IDType id);

                public<E> E executeQuery(String query,Object... args);

                public<E> E executeQuery(Closure query);  //-- we could also embed support for a SQL DSL..

                public DomainType find(String query,Object... args);
                public DomainType find(DomainType example);
                public DomainType find(Closure query);

                public   List<DomainType>  findAll(String query,Object... args);

                public List<DomainType> findAll(Closure query);

                public DomainType findBy(String query,Object... args);

                public List<DomainType> findAllBy(String query,Object... args);

                public DomainType findWhere(Map params);

                public List<DomainType> findAllWhere(Map params);

                public DomainType get(IDType params);
                public List<DomainType> getAll(IDType... ids);
                public List<DomainType> list();
                public List<DomainType> list(Map params);
                public List<DomainType> listOrderBy(String query,Map params);

                public<E> E withCriteria(Closure query);

                public void withTransaction(Closure transaction);
        }

We can use this interface as a base, by extending it to include the specific dynamic finder methods we want to use. N.B. Although we will not have to provide any implementation for these methods, we do need to let statically typed Java know which methods we'd like to be able to use.

Calling static finder methods

Next let's create a generic dynamic invocation handler that can call any GORM dynamic finder method for us. All it needs is a single instance of the GORM class we wish to process.

public class Static<DomainType,IDType> implements InvocationHandler {

        GroovyObject gormModel;



        public Static(GroovyObject model){
                this.gormModel = model;

        }

        /* (non-Javadoc)
         * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
         */
        public Object invoke(Object target, Method method, Object[] args) throws Throwable {
                // TODO Auto-generated method stub
                    Object result = gormModel.getMetaClass().
                                     invokeStaticMethod(null,method.getName(),
                                      args);


                return result;
        }



Creating the GORM-Java proxier


It might be nice to have a standard way to create instances of our GORM invocation handler - so let's define a factory to create them. This will come in handy later when we need to perform so jiggery-pokery to proxy the models returned themselves.

public class  StaticFactory {



                public IStatic create(GroovyObject key) {

                return (IStatic) java.lang.reflect.Proxy.newProxyInstance(
                          getClass().getClassLoader(),
                          new Class[]{IStatic.class},
                          new Static(key));



                }

        }

Trying it out


Remember our DAO from last week? If instead of putting full blown access here we put instead code to create an instance of our GORM Objects (our DAO lives in the Grails world) - we can use this to get a handle on our GORM models.

public class Access implements IAccess{


        def access = [


                book : {new Book()}


        ]

        public Object access(String key){
                def m = access[key]

                return m.call()
        }

        public Object access(String key,Object [] args){

                return access[key].call(args)
        }





}

We can create our Access instance as last week, via reflection. Let's assume we've done that. The code below shows how to create a Static instance capable of executing the GORM dynamic finders. Instead of calling those methods directly on the class we simply get a handle on the appropriate IStatic instance and call the method on that.

public List listAllBooksFromStatic(IAccess gorm){
                StaticFactory factory = new StaticFactory();
                GroovyObject bookModel = gorm.access("book");

                IStatic<IBook,Long> Book = factory.create(bookModel);

                List<IBook> books = Book.list();
                for(IBook book : books){
                        System.out.println("Next book " + book.getTitle());
                }
                return books;
        }

But what about the really dynamic methods?


Let's try and find all Books by title, first let's create an interface that extends IStatic

public interface IStaticBook<DomainType,IDType> extends IStatic<DomainType,IDType> {

        public IBook findByTitle(String title);
}

Then plug that interface in the factory instead of IStatic. Later on we'll plug in an Interface resolver into the factory rather than hard coding the interface to use.

        public IStatic create(GroovyObject key) {

                return (IStatic) java.lang.reflect.Proxy.newProxyInstance(
                                            getClass().getClassLoader(),
                                            new Class[]{IStaticBook.class},
                                            new Static(key));



                }

And let's modify our access code and find by title

        public void findByTitle(IAccess gorm){
                StaticFactory factory = new StaticFactory();
                GroovyObject bookModel = gorm.access("book");

                IStaticBook<IBook,Long> Book = factory.create(bookModel);

                IBook book = Book.findByTitle("The Shining");

        }

More to do


This code is fairly raw example code. You should ofcourse tidy up the creation of IStatic objects - in your application only one instance per type need actually exist. They are pretty good candidates for injection via DI container. But more work remains - we have yet to add support for the dynamic methods provided on the GORM objects themselves....


To be continued..

Resources

Jeremie Weldin's GORM outside of Grails' tutorial Java on Grails pilot Java on Grails : Genesis episode 2 Java on Grails : Save the bean, save the world putting it all together

Downloads

Java on Grails mini-framework Java on Grails demo app
Note the source is stored in jars due to upload file extension restrictions.

There exist some JVM objects that have innate special abilities. Although unaware of it now, these objects will not only save the Java world, but change it forever. Special abilities such as spontaneous method generation, the ability to persist oneself permanently, or erase every trace their existence, the ability to intelligently self-organise without recourse to foreign wordy verbosity...

These special Objects have been documented to exist deep within a framework, known to the cognescenti as Grails. Up until now Grails has been hugely popular within the Groovy community. What would happen if the special Objects within Grails could not only teleport across Classloaders and past the Java-Groovy boundary, as many Groovy Objects have done in the past, but also teleport across that boundary with their powers intact? ...

A great job

Jeremie Weldin has done a great job of getting GORM (an excellent wrapper over hibernate) to work outside of Grails. I've been playing about with taking this one step further, and allowing Java code to take advantage of all that GORM goodness (i.e. not only easy configuration, but also the dynamic helper methods). The first step was to create a Groovy DAO class - that would be compiled and managed by the Grails classloader. This could then access all of our GORM domain classes. By implementing a DAO interface defined in Java, and by instantiating our DAO via reflection (after extracting the class from the Grails Class loader) we can now access all of our Grails Domain Objects in Java. So far, so good, but no dynamic helper methods yet.

Simple Beginnings

If you want to follow along download Jeremie's code from his blog and implement the following classes.

Our Java DAO interface ...
public interface IAccess<E> {

  public<T> T access(E key);
  public<T> T access(E key,Object... args);

}
Our Groovy DAO Implementation

This class needs to live inside the Grails world, implement it in a folder under grails-app

public class Access implements IAccess{

  def access = [

    listAllBooks : {Book.list()},
    save : { it.save() },

  ]

  public Object access(String key){

    return access[key].call()
  }

  public Object access(String key,Object [] args){

    return access[key].call(args)
  }

}

NB - in the next Groovy release, which will support enums, we could use enums rather than Strings to configure the DAO

Our code to initialise our DAO
IAccess access = cl.loadClass("Access",false,true).newInstance()

Take a look at Jeremie's Test.groovy class - where he creates the Grails application to load and manage the GORM classes - this is where you will get the Class loader. If you are attempting this from within a standard Grails application you can use the following in your own Java code to get at the Class loader.

Accessing the Grails Classloader
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
ClassLoader cl = (ClassLoader)ctx.getBean("classLoader");

Beware the automatic compilation by the Groovy Eclipse plugin - it seems to be important that Grails - and not the plugin - compiles the Grails classes!

Retaining the powers

By defining all of the Grails data access methods we want to leverage in our DAO we can take advantage of the full power of GORM, indirectly. The next level however, would be to help those Grails managed GORM objects cross-over into the standard Java world while still retaining their full range of powers. We can do this with the help of plain old Java interfaces, JDK dynamic proxies and the power of the Groovy language (libraries!)..

To be continued...

Resources

Jeremie Weldin's GORM outside of Grails' tutorial Java on Grails pilot Java on Grails : Genesis episode 2 Java on Grails : Save the bean, save the world putting it all together

Downloads

Java on Grails mini-framework Java on Grails demo app
Note the source is stored in jars due to upload file extension restrictions. Vote for or against this entry on Dzone.com!
This one is a no brainer. The simple answer is yes it is. Should we pump resources into fixing a problem Sun didn't solve for us? Or should we swallow our pride and learn the new improved ActionScript that powers Flex? Personally, I think the later. Ed's reasoning sounds like an emotional / religous attachment to Java (or repulsion from ActionScript). Realistically, Adobe have solved the problem for us -they seem to have created a top notch platform for client side web development. If you spend your resources developing a Java alternative for tomorrow (because you prefer Java to ActionScript), your competitors will spend theirs delivering a better user experience on Flex today.

My employer (AOL Technologies) is hiring Java developers and QA engineers for it's Dublin, Ireland office. If you're a strong Java developer and would like to work on cool projects like the technology platform that powers Fullview and a host of other applications, or on local based projects such as Search-on-a-map, or yellow pages, then drop me a line at johnmcclean -at- hotmail -dot- com. You must be entitled to work in Ireland (be an EU citizen or have an Irish work permit).

Benefits include a free onsite gym, an excellent subsidised canteen, free coffee/tea/cappucinos/lattes, pension, health care, 23 paid holidays, onsite foosball & pool tables, bonus scheme, etc, etc... Oh and Dublin pubs for avoiding the Irish weather!

Share wedding photos & memories with a free wedding website Fresh Ideas For Brides: a wedding blog aggregator


You are viewing a mobilized version of this site...
View original page here

Mobilized by Mowser Mowser