groovy
  1. groovy
  2. GROOVY-2116

add an extension mechanism to allow new GDK methods to be added to other libraries by other projects using a META-INF/services/groovy/groovyMethods file on the classpath to list Classes to be used to load GDK methods

    Details

    • Type: Improvement Improvement
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0-rc-1
    • Component/s: groovy-jdk
    • Labels:
      None
    • Patch Submitted:
      Yes
    • Number of attachments :
      2

      Issue Links

        Activity

        Hide
        james strachan added a comment -

        attached patch - as I don't seem to have commit karma any more

        Show
        james strachan added a comment - attached patch - as I don't seem to have commit karma any more
        Hide
        Graeme Rocher added a comment -

        Hi James, have you considered using ExpandoMetaClass? http://groovy.codehaus.org/ExpandoMetaClass

        it is becoming the standard way to extend the functionality of Groovy and you don't have to write a custom meta class per Groovy class.

        Show
        Graeme Rocher added a comment - Hi James, have you considered using ExpandoMetaClass? http://groovy.codehaus.org/ExpandoMetaClass it is becoming the standard way to extend the functionality of Groovy and you don't have to write a custom meta class per Groovy class.
        Hide
        james strachan added a comment -

        I used an ExpandoMetaClass in the end (as there's no other option! . However I'm not totally happy with it - as it assumes that the user of your library is gonna call some magic install script in some place to make sure the methods get added. This is probably fine in lots of frameworks like Grails where there's already an initialization point - but in general, adding groovy methods to arbitrary code - we need some kinda auto-discovery way to find the expando-metaclass scripts.

        Whether we use Java code as in my patch, or groovy and ExpandoMetaClass doesn't matter a whole lot - the main issue we need to address IMHO is adding an auto-discovery mechanism so we can by default add methods to new types by adding a jar to the classpath - without the user having to remember to call some initialization script

        Show
        james strachan added a comment - I used an ExpandoMetaClass in the end (as there's no other option! . However I'm not totally happy with it - as it assumes that the user of your library is gonna call some magic install script in some place to make sure the methods get added. This is probably fine in lots of frameworks like Grails where there's already an initialization point - but in general, adding groovy methods to arbitrary code - we need some kinda auto-discovery way to find the expando-metaclass scripts. Whether we use Java code as in my patch, or groovy and ExpandoMetaClass doesn't matter a whole lot - the main issue we need to address IMHO is adding an auto-discovery mechanism so we can by default add methods to new types by adding a jar to the classpath - without the user having to remember to call some initialization script
        Hide
        Guillaume Laforge added a comment -

        I postponing this issue a little, as I'd like we discuss the topic at Groovy DevCon #4.
        There are different mechanisms, like the magic package for MetaClasses, and there was an idea for defining EMCs in some magic startup script, and also this proposal your make.
        I'd like to find a good way to make things consistent in that area, and I think it deserve some thought.

        Show
        Guillaume Laforge added a comment - I postponing this issue a little, as I'd like we discuss the topic at Groovy DevCon #4. There are different mechanisms, like the magic package for MetaClasses, and there was an idea for defining EMCs in some magic startup script, and also this proposal your make. I'd like to find a good way to make things consistent in that area, and I think it deserve some thought.
        Hide
        Andrew O'Malley added a comment -

        A mechanism (such as James') that adds methods statically would be a great addition. In particular, it would allow tools like the JetGroovy plugin to do static analysis on the methods.

        For example, at present if I use auto completion with "new File()" in JetGroovy it lists "eachFileRecurse". However, anything added via ExpandoMetaClass is not visible. Nor can it ever be as it is only bound dynamically at runtime (static analysis could never determine if the code that adds the method via ExpandoMetaClass gets executed).

        Show
        Andrew O'Malley added a comment - A mechanism (such as James') that adds methods statically would be a great addition. In particular, it would allow tools like the JetGroovy plugin to do static analysis on the methods. For example, at present if I use auto completion with "new File()" in JetGroovy it lists "eachFileRecurse". However, anything added via ExpandoMetaClass is not visible. Nor can it ever be as it is only bound dynamically at runtime (static analysis could never determine if the code that adds the method via ExpandoMetaClass gets executed).
        Hide
        Peter Niederwieser added a comment -

        Really want to see a META-INF/services based solution that lets me add GDK methods in DGM-style, without EMC and potentially written in Java.

        Show
        Peter Niederwieser added a comment - Really want to see a META-INF/services based solution that lets me add GDK methods in DGM-style, without EMC and potentially written in Java.
        Hide
        CÚdric Champeau added a comment -

        The attached patch allows adding default groovy methods by adding custom jar in the classpath. Those jars must provide a META-INF/services/org.codehaus.groovy.dgm.extensions file which lists the FQN of extension classes which are written in a DGM-style. Here's an example :

        MyExtension.java
        package groovy.dgm;
        
        public class MyExtension {
            public static String dup(String str) {
                if (str==null) return null;
                return str+str;
            }
        }
        
        META-INF/services/org.codehaus.groovy.dgm.extensions
        groovy.dgm.MyExtension
        

        The mechanics are therefore similar to those used for global AST transformations and custom compiler extensions.

        Show
        CÚdric Champeau added a comment - The attached patch allows adding default groovy methods by adding custom jar in the classpath. Those jars must provide a META-INF/services/org.codehaus.groovy.dgm.extensions file which lists the FQN of extension classes which are written in a DGM-style. Here's an example : MyExtension.java package groovy.dgm; public class MyExtension { public static String dup( String str) { if (str== null ) return null ; return str+str; } } META-INF/services/org.codehaus.groovy.dgm.extensions groovy.dgm.MyExtension The mechanics are therefore similar to those used for global AST transformations and custom compiler extensions.
        Hide
        Paul King added a comment -

        Nice patch. For 1.9 I have something similar but aligned with grapes rather than just the ones found during registry bootstrapping. I think grapes is also where custom compiler extensions more naturally belong too but the current compiler extensions mechanism was put in place as an interim solution for groovypp.

        Show
        Paul King added a comment - Nice patch. For 1.9 I have something similar but aligned with grapes rather than just the ones found during registry bootstrapping. I think grapes is also where custom compiler extensions more naturally belong too but the current compiler extensions mechanism was put in place as an interim solution for groovypp.
        Hide
        CÚdric Champeau added a comment -

        I'm not sure such a feature should only be available through grapes : having a global way of adding such methods looks interesting to me. Do you think we should provide both ?

        Show
        CÚdric Champeau added a comment - I'm not sure such a feature should only be available through grapes : having a global way of adding such methods looks interesting to me. Do you think we should provide both ?
        Hide
        blackdrag blackdrag added a comment -

        The last time I was thinking about this area I had the thought that it might be best not to have a file class in the style of DefaultGroovyMethods from which we get the methods. I was thinking that it might be better to think of that more as a kind of plugin and that it maybe should instead provide the MetaMethods directly. We could then also do it fully in spi style.

        Show
        blackdrag blackdrag added a comment - The last time I was thinking about this area I had the thought that it might be best not to have a file class in the style of DefaultGroovyMethods from which we get the methods. I was thinking that it might be better to think of that more as a kind of plugin and that it maybe should instead provide the MetaMethods directly. We could then also do it fully in spi style.
        Hide
        CÚdric Champeau added a comment -

        Yes, the DefautGroovyMethods class already has support for this (the "additionals" static field). However, it looks much more complicated to provide MetaMethods than implementing extensions through DGM style.

        Show
        CÚdric Champeau added a comment - Yes, the DefautGroovyMethods class already has support for this (the "additionals" static field). However, it looks much more complicated to provide MetaMethods than implementing extensions through DGM style.
        Hide
        Peter Niederwieser added a comment -

        From a user's perspective, I'm very much in favor of implementing methods in DGM style. In particular, I want to be able to implement the methods in Groovy or Java.

        Show
        Peter Niederwieser added a comment - From a user's perspective, I'm very much in favor of implementing methods in DGM style. In particular, I want to be able to implement the methods in Groovy or Java.
        Hide
        blackdrag blackdrag added a comment -

        the additionals parts is not used by the runtime, it is used by groovydoc and by the part that generates callsites for the dgm methods. If we really wanted to do it like dgm, then we would need those hundreds of generated classes. The reason we have them simply is, that laoding them is faster than loading a giant DGM and inspecting it through reflection. Also a point to consider is that the more methods are added the slower groovy will startup, since that complete registry is done once at startup. I was thinking that we should have a more efficient system, but I couldn't come up with one yet

        Show
        blackdrag blackdrag added a comment - the additionals parts is not used by the runtime, it is used by groovydoc and by the part that generates callsites for the dgm methods. If we really wanted to do it like dgm, then we would need those hundreds of generated classes. The reason we have them simply is, that laoding them is faster than loading a giant DGM and inspecting it through reflection. Also a point to consider is that the more methods are added the slower groovy will startup, since that complete registry is done once at startup. I was thinking that we should have a more efficient system, but I couldn't come up with one yet
        Hide
        Peter Niederwieser added a comment -

        I don't know the details. Just saying that as a user, I'd like to write DGM-style methods. I assume the number of methods added in such a way would be way below the number of DGM methods. IMHO this feature should only be used by end-user applications. For libraries, the risk of nasty conflicts is too high.

        Show
        Peter Niederwieser added a comment - I don't know the details. Just saying that as a user, I'd like to write DGM-style methods. I assume the number of methods added in such a way would be way below the number of DGM methods. IMHO this feature should only be used by end-user applications. For libraries, the risk of nasty conflicts is too high.
        Show
        CÚdric Champeau added a comment - See http://docs.codehaus.org/display/GROOVY/Creating+an+extension+module

          People

          • Assignee:
            CÚdric Champeau
            Reporter:
            james strachan
          • Votes:
            5 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: