Availability

Child pages
  • Groovy Macro

Skip to end of metadata
Go to start of metadata


Description

Java scripting using Groovy

Documentation

  • Help available in the notation guide.

Parameters

Pre-defined variables

Usage

{groovy}
println("Hello world");
{groovy}
{groovy:output=wiki|script=#example.py|var1=test}
{groovy} 
{groovy:var1=hello|var2=world}
print "Output parameter"
print var1 + var2
out.println(var1 + var2)
{groovy}
classpath example
{groovy:classpath=/sde/tools/gint-1.5.0.jar}
...
{groovy}
 

Using the html markup builder

{groovy}
def list = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
html.table(class: 'confluenceTable') {
  tbody {
    list.each { row ->
      tr {
        row.each { column ->
            td(class: 'confluenceTd', column)
        }
      }
    }
  }
}
{groovy}

Security

This macro supports Macro Security for Confluence.

 

13 Comments

  1. Hi,

    Thank you for a great plugin. This is helping me build a lot of custom extensions to confluence.

    Is there anyway to set the default value of the groovy macro classpath without having to explicitly set it on every macro invocation?

    Failing that, is there anyway of using the confluenceHome parameter value when setting the classpath? For example: 

    {groovy:classpath=$confluenceHome/script/tools;$confluenceHome/script/lib}
    ...

    Many thanks

    Bahman

    1. No, not at this time. But that is planned for the near future. Feel free to create an issue if there isn't one already for that specifically. 
    2. The default classpath setting (see the parameter) only works for classes not jars, so it isn't very convenient.  There is no variable replacement either. You can request that, but a global setting is probably more useful.
    1. Cool. Thanks for the quick reply. Will create the issue.

  2. Hello,

    is it possible to use classes and methods with your plugin?

    e.g.

     

    {groovy:output=wiki}
    
    class Callee { 
    	void hello(){ 
    		println "hello, world" 
    	}
    }
    
    c = new Callee()
    c.hello()
    
    {groovy}
    
    

     

    In my case, the method is not called by the class variable "c"


    Thanks,

    Michael

     

    1. Yes, but you always need to use out for putting things on the page:

      {groovy:output=wiki}
      
      class Callee {
          PrintWriter out; // for output of macro result
          void hello(){ 
      		out.println "hello, world" 
      	}
      }
      
      c = new Callee()
      c.out = out  // make out available to the class
      c.hello()
      {groovy}
  3. Hi,

    I just tried an upgrade from 3.4 to 4.2 and all my groovy scripts broke complaining about missing classes. The missing classes are in Jar files which I'd copied into the Confluence\lib directory. With version 3.4 of the groovy macro I did not need to add the Confluence\lib path to the groovy macro classpath variable as it seemed this was implicitly included.

    So to check the theory that the classpath was initialised differently between 3.4 and 4.2 I ran the following snippet but it generated the same output for both versions i.e. a single entry for the script directory as documented.

    {groovy}
    this.class.classLoader.getURLs().each { url->println "- ${url.toString()}" }
    {groovy}

    Can you please tell me if anything has changed around classpath and class loading in the new version? I've had to go back to the old version as I have a lot of groovy scripts which will take time to edit.

    Thanks

    Bahman

    1. Yes, Confluence 4.x and up prevent plugins from accessing various services unless explicitly imported. You will need to explicitly set the classpath for jars/classes you need to access. For groovy, that means setting the classpath parameter.

      1. We are migrating from 3.5 to 5.4. including our various groovy scripts which were developed since many years. We are running into classpath issues with imports from org.apache.xxx or even com.atlassian.confluence.util.xxx . These can be solved through adding the jars in the classpath parameter. ( I'm not the groovy expert, I'm the migrator.)

        But this seems not to be a sustainable solution - which strategy you would recommend for the future in order to minimize upgrade effort ? Is this related to SCRP-127 ? Is there any documentation on what is accessible through the default classpath? We are encountering that not everthing which is sitting in WEF-INF/lib is accessible. 

        1. Correct, the system classpath is not available. You pretty much have to set your own classpath based on what your code needs. This isn't much different to what plugin developers had to do to migrate their code, identify all the things they need and make sure it is part of the plugin bundle. It may be possible to automatically include some additional commonly used accessed but it is hard to determine that give how varied programs can be.
          For general guidance perspective:

          1. When you write your own code/scripts, then it is implied they have to be maintained and potentially changed as Confluence moves forward. 
          2. In the past with my migrations, I would always look to eliminate custom changes as much as possible by looking for alternatives available on the upgraded Confluence or with new plugins.
          3. Confluence in the past has been pretty good for upward compatibility except for a few major things after 3.5 (storage format, user management changes, templates, WEB-INF use/access). Moving from 3.5 is likely going to be your most difficult migration and incompatibility scenario. Especially going from 3.5 to 5.x, that is a big jump.
  4. Hi Bob - Sorry if this is something inherit in Confluence itself that I'm just missing (and I can understand the security reasons for doing so), but I'm trying to do an HTTPS request from within groovy and getting:

    Error rendering macro 'groovy' : javax/security/auth/x500/X500Principal

    I'm using "groovyx.net.http.RESTClient" and receive the above as soon as the 'get' method is called on a an https URL.  I thought it might be a matter of having the SSL cert in the confluence user keystore, but I get the same issue with non-SSL requests as well.  Is this something that can work?  

    The reason for this is I need to take in some XML data, do a little processing on it, and display it on a page.

    Thanks

     

     

     

     

    1. Don't know. Make sure your classpath parameter has all classes you need. Surround the code with try/catch and see if you get more details. Open an issue with specific code if you are still stuck, although, I am not sure I can help. Also, the XSLT Macro might be useful for things like this.

      1. Bob - This shed any light (below stack trace)?  I'm not a java guru, so I'm a little lost here.  Confluence is using its include jre (/usr/local/confluence/jre/) and I can see the class in question in lib/rt.jar.  I was assuming that the groovy module would also be using this jre, but am I wrong?  directly trying to "import javax.security.auth.x500.X500Principal" shows the class as unresolvable. 

        I should probably add I'm using Grape:

        @Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7')

        in order to get access to groovyx.net.http.HTTPBuilder fo the request.

        stacktrace:

        java.lang.ClassNotFoundException: javax.security.auth.x500.X500Principal

        -------

        org.apache.http.conn.ssl.AbstractVerifier.getCNs(AbstractVerifier.java:264) org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:147) org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:130) org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572

        1. I would put an explicit reference to the jar on the classpath parameter first to get that working. Then work to get grab working. I have had some difficulties in the past with grab and the user directory it is using.