2

How does one setup a Spring Boot app written mostly in java and be able to refer to Groovy scripts as well?

I read the following articles:

http://www.ibm.com/developerworks/library/j-groovierspring1/ http://www.ibm.com/developerworks/library/j-groovierspring2/

These were written well before Spring Boot's time. I want the runtime dynamic nature of Groovy scripts in my java based Spring Boot application. I don't want to compile my Groovy classes out-of-band and refer to them. I want the scripting ability (as described in the linked web pages).

What I've done so far is just create a bare bones Spring Boot app that really does nothing and tried to get the app to recognize a bean implemented by a Groovy script. I used a modified version of GroovyPdfGenerator that's mentioned in the linked articles.

Here's what I have:

// PdfGenerator.java, lives under demo
package demo;
public interface PdfGenerator {
    String pdfFor(String name);
}

// GroovyPdfGenerator.groovy, lives under demo
package demo
import demo.PdfGenerator
class GroovyPdfGenerator implements PdfGenerator {
    public String pdfFor(String name) {
        return "Hello, World!"
    }
}

// beans.xml, lives under src/main/resources
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/lang
    http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
    <lang:groovy id="pdfGenerator" script source="classpath:GroovyPdfGenerator.groovy"/>
</beans>

// DemoGroovyTaskApplication.java, lives under demo
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource(value = { "classpath:beans.xml" })
public class DemoGroovyTaskApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoGroovyTaskApplication.class, args);
    }
}

I tried moving the Groovy file to under resources/ but that didn't work. Also, I couldn't figure out how to get Spring Boot to load the Groovy bean other than using a XML configuration.

Anyone know how this may work?

Forgot to mention, what I get w/ my code is a ClassNotFoundException. I broke on that exception and Spring is looking scriptFactory.pdfGenerator.

Here's the stack trace w/ debugging enabled (sans Negative Matches):

2015-01-23 05:47:49.646  INFO 56013 --- [          main] demo.DemoGroovyTaskApplication        : Starting DemoGroovyTaskApplication on gary-fong2.local with PID 56013 (/Users/gary.fong/development/spring/experiments/my-workspace/demoGroovyTask/target/classes started by gary.fong in /Users/gary.fong/development/spring/experiments/my-workspace/demoGroovyTask)
2015-01-23 05:47:49.650 DEBUG 56013 --- [          main] o.s.boot.SpringApplication            : Loading source class demo.DemoGroovyTaskApplication
2015-01-23 05:47:49.694 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application.yaml' resource not found
2015-01-23 05:47:49.694 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application.xml' resource not found
2015-01-23 05:47:49.694 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application.properties' resource not found
2015-01-23 05:47:49.694 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application.yml' resource not found
2015-01-23 05:47:49.694 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application.yaml' resource not found
2015-01-23 05:47:49.694 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application.xml' resource not found
2015-01-23 05:47:49.694 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application.properties' resource not found
2015-01-23 05:47:49.695 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application.yml' resource not found
2015-01-23 05:47:49.695 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application.yaml' resource not found
2015-01-23 05:47:49.695 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application.xml' resource not found
2015-01-23 05:47:49.695 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application.properties' resource not found
2015-01-23 05:47:49.695 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application.yml' resource not found
2015-01-23 05:47:49.695 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application.yaml' resource not found
2015-01-23 05:47:49.695 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application.xml' resource not found
2015-01-23 05:47:49.695 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application.properties' 
2015-01-23 05:47:49.695 DEBUG 56013 --- [          main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application.yml' resource not found
2015-01-23 05:47:49.700  INFO 56013 --- [          main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@a39e3dd: startup date [Fri Jan 23 05:47:49 PST 2015]; root of context hierarchy
2015-01-23 05:47:50.014  INFO 56013 --- [          main] o.s.b.f.xml.XmlBeanDefinitionReader      : Loading XML bean definitions from class path resource [beans.xml]
2015-01-23 05:47:50.377  INFO 56013 --- [          main] .b.l.ClasspathLoggingApplicationListener : Application failed to start with classpath: [file:/Users/gary.fong/development/spring/experiments/my-workspace/demoGroovyTask/target/classes/, file:/Users/gary.fong/.m2/repository/org/springframework/boot/spring-boot-starter/1.2.1.RELEASE/spring-boot-starter-1.2.1.RELEASE.jar, file:/Users/gary.fong/.m2/repository/org/springframework/boot/spring-boot/1.2.1.RELEASE/spring-boot-1.2.1.RELEASE.jar, file:/Users/gary.fong/.m2/repository/org/springframework/spring-context/4.1.4.RELEASE/spring-context-4.1.4.RELEASE.jar, file:/Users/gary.fong/.m2/repository/org/springframework/spring-aop/4.1.4.RELEASE/spring-aop-4.1.4.RELEASE.jar, file:/Users/gary.fong/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar, file:/Users/gary.fong/.m2/repository/org/springframework/spring-beans/4.1.4.RELEASE/spring-beans-4.1.4.RELEASE.jar, file:/Users/gary.fong/.m2/repository/org/springframework/spring-expression/4.1.4.RELEASE/spring-expression-4.1.4.RELEASE.jar, file:/Users/gary.fong/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/1.2.1.RELEASE/spring-boot-autoconfigure-1.2.1.RELEASE.jar, file:/Users/gary.fong/.m2/repository/org/springframework/boot/spring-boot-starter-logging/1.2.1.RELEASE/spring-boot-starter-logging-1.2.1.RELEASE.jar, file:/Users/gary.fong/.m2/repository/org/slf4j/jcl-over-slf4j/1.7.8/jcl-over-slf4j-1.7.8.jar, file:/Users/gary.fong/.m2/repository/org/slf4j/slf4j-api/1.7.8/slf4j-api-1.7.8.jar, file:/Users/gary.fong/.m2/repository/org/slf4j/jul-to-slf4j/1.7.8/jul-to-slf4j-1.7.8.jar, file:/Users/gary.fong/.m2/repository/org/slf4j/log4j-over-slf4j/1.7.8/log4j-over-slf4j-1.7.8.jar, file:/Users/gary.fong/.m2/repository/ch/qos/logback/logback-classic/1.1.2/logback-classic-1.1.2.jar, file:/Users/gary.fong/.m2/repository/ch/qos/logback/logback-core/1.1.2/logback-core-1.1.2.jar, file:/Users/gary.fong/.m2/repository/org/springframework/spring-core/4.1.4.RELEASE/spring-core-4.1.4.RELEASE.jar, file:/Users/gary.fong/.m2/repository/org/yaml/snakeyaml/1.14/snakeyaml-1.14.jar]
2015-01-23 05:47:50.378 DEBUG 56013 --- [          main] utoConfigurationReportLoggingInitializer : 
=========================
AUTO-CONFIGURATION REPORT
=========================
Positive matches:
-----------------
   JmxAutoConfiguration
      - @ConditionalOnClass classes found: org.springframework.jmx.export.MBeanExporter (OnClassCondition)
      - matched (OnPropertyCondition)
   JmxAutoConfiguration#mbeanExporter
      - @ConditionalOnMissingBean (types: org.springframework.jmx.export.MBeanExporter; SearchStrategy: current) found no beans (OnBeanCondition)
   JmxAutoConfiguration#mbeanServer
      - @ConditionalOnMissingBean (types: javax.management.MBeanServer; SearchStrategy: all) found no beans (OnBeanCondition)
   JmxAutoConfiguration#objectNamingStrategy
      - @ConditionalOnMissingBean (types: org.springframework.jmx.export.naming.ObjectNamingStrategy; SearchStrategy: current) found no beans (OnBeanCondition)
   PropertyPlaceholderAutoConfiguration#propertySourcesPlaceholderConfigurer
      - @ConditionalOnMissingBean (types: org.springframework.context.support.PropertySourcesPlaceholderConfigurer; SearchStrategy: current) found no beans (OnBeanCondition)
2015-01-23 05:47:50.384 ERROR 56013 --- [          main] o.s.boot.SpringApplication            : Application startup failed
java.lang.NoClassDefFoundError: org/codehaus/groovy/control/CompilationFailedException
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2615)
    at java.lang.Class.getDeclaredMethods(Class.java:1860)
    at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:571)
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:490)
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:474)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:241)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1057)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1030)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.scripting.support.ScriptFactoryPostProcessor.prepareScriptBeans(ScriptFactoryPostProcessor.java:357)
    at org.springframework.scripting.support.ScriptFactoryPostProcessor.predictBeanType(ScriptFactoryPostProcessor.java:251)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:599)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1397)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:434)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:404)
    at org.springframework.context.support.AbstractApplicationContext.getBeanNamesForType(AbstractApplicationContext.java:1046)
    at org.springframework.context.support.AbstractApplicationContext.registerListeners(AbstractApplicationContext.java:726)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:477)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
    at demo.DemoGroovyTaskApplication.main(DemoGroovyTaskApplication.java:11)
Caused by: java.lang.ClassNotFoundException: org.codehaus.groovy.control.CompilationFailedException
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 29 common frames omitted
2015-01-23 05:47:50.384  INFO 56013 --- [          main] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@a39e3dd: startup date [Fri Jan 23 05:47:49 PST 2015]; root of context hierarchy
2015-01-23 05:47:50.386  WARN 56013 --- [          main] s.c.a.AnnotationConfigApplicationContext : Exception thrown from LifecycleProcessor on context close
java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: org.springframework.context.annotation.AnnotationConfigApplicationContext@a39e3dd: startup date [Fri Jan 23 05:47:49 PST 2015]; root of context hierarchy
    at org.springframework.context.support.AbstractApplicationContext.getLifecycleProcessor(AbstractApplicationContext.java:357)
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:877)
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:836)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:343)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
    at demo.DemoGroovyTaskApplication.main(DemoGroovyTaskApplication.java:11)
Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/groovy/control/CompilationFailedException
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2615)
    at java.lang.Class.getDeclaredMethods(Class.java:1860)
    at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:571)
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:490)
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:474)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:241)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1057)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1030)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.scripting.support.ScriptFactoryPostProcessor.prepareScriptBeans(ScriptFactoryPostProcessor.java:357)
    at org.springframework.scripting.support.ScriptFactoryPostProcessor.predictBeanType(ScriptFactoryPostProcessor.java:251)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:599)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1397)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:434)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:404)
    at org.springframework.context.support.AbstractApplicationContext.getBeanNamesForType(AbstractApplicationContext.java:1046)
    at org.springframework.context.support.AbstractApplicationContext.registerListeners(AbstractApplicationContext.java:726)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:477)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
    at demo.DemoGroovyTaskApplication.main(DemoGroovyTaskApplication.java:11)
Caused by: java.lang.ClassNotFoundException: org.codehaus.groovy.control.CompilationFailedException
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 29 more
4
  • What build tool you use? Commented Jan 23, 2015 at 6:25
  • This isn't a build it's an IDE. Commented Jan 23, 2015 at 7:32
  • Can you post the full exception and stack trace? Commented Jan 23, 2015 at 13:14
  • Sorry, it's Maven. I'll put the trace in the main post. I enabled debugging so there's a bit more output than usual. Commented Jan 23, 2015 at 13:51

1 Answer 1

3

I was able to resolve my issue.

I had to 1) install Groovy-Eclipse, 2) add the Groovy libraries to the build path. For good measure, I also enabled [Enable script folder support] so that my script isn't compiled at build time.

Once I got all of this in, Eclipse reported an error with my "import" statement in the Groovy script. And once I removed that, it all worked. Very cool.

Thanks all

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.