I have a multimodule gradle build, using spring-boot and standalone GORM.
The domain entities are located in a separate submodule, so that these domain objects and gorm can be used across several spring-boot (and non-spring-boot) applications.
Structure
build.gradle
- module1-with-springboot-jersey (depending on module 3)
-- src/main/groovy/geit/api/Application.groovy
- module2-with-springboot-groovytemplate (depending on module 3)
- module3-standalone-gorm-with-entities
-- src/main/groovy/geit/domain/../Animal.groovy
- module4-apache-camel-app (depending on module 3)
When running gradle bootRun in module1, the jersey app, it starts the application, however when trying to access a rest resource returning an Animal, it fails with a stacktrace:
2014-11-03 13:16:03.679 ERROR 44316 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/api].[jerseyServlet] : Servlet.service() for servlet [jerseyServlet] in context with path [/api] threw exception [java.lang.IllegalStateException: Method on class [geit.domain.entity.experimental.reku.Animal] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.] with root cause
java.lang.IllegalStateException: Method on class [geit.domain.entity.experimental.reku.Animal] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.
at geit.domain.entity.experimental.reku.Animal.currentGormStaticApi(Animal.groovy)
at geit.domain.entity.experimental.reku.Animal.$static_methodMissing(Animal.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1270)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1493)
at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1481)
at groovy.lang.ExpandoMetaClass.invokeStaticMethod(ExpandoMetaClass.java:1123)
at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:50)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at geit.api.experimental.reku.AnimalsResource.greet(AnimalsResource.groovy:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
un.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1270)
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:406)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:350)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:106)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:259)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:320)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1028)
at org.glassfish.jersey.servlet.WebComponent.servComponent.java:373)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:219)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:280)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:98)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
g.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:90)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1736)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1695)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:744)
So I read up on the documentation, and find this http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-separate-entity-definitions-from-spring-configuration Hmm.. @EntityScan looks promising
So I annotate my Application class, like this
@ComponentScan
@EnableAutoConfiguration(exclude = GroovyTemplateAutoConfiguration.class)
@EntityScan(basePackageClasses=Animal)
class ApiApplication {
static void main(String[] args) {
SpringApplication.run ApiApplication, args
}
}
But now, the gradle bootRun fails at startup
2014-11-03 13:20:43.790 INFO 44376 --- [ main] utoConfigurationReportLoggingInitializer :
Error starting ApplicationContext. To display the auto-configuration report enabled debug logging (start with --debug)
2014-11-03 13:20:43.797 ERROR 44376 --- [ main] o.s.boot.SpringApplication : Application startup failed
java.lang.IllegalStateException: Unable to configure LocalContainerEntityManagerFactoryBean from @EntityScan, ensure an appropriate bean is registered.
at org.springframework.util.Assert.state(Assert.java:385)
at org.springframework.boot.orm.jpa.EntityScanRegistrar$EntityScanBeanPostProcessor.onApplicationEvent(EntityScanRegistrar.java:124)
at org.springframework.boot.orm.jpa.EntityScanRegistrar$EntityScanBeanPostProcessor.onApplicationEvent(EntityScanRegistrar.java:94)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:773)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:131)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:483)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:692)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:962)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:951)
at org.springframework.boot.SpringApplication$run.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
g.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
at geit.api.ApiApplication.main(ApiApplication.groovy:31)
2014-11-03 13:20:43.798 INFO 44376 --- [ main] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@4c85ba73: startup date [Mon Nov 03 13:20:35 CET 2014]; root of context hierarchy
2014-11-03 13:20:43.801 INFO 44376 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0
2014-11-03 13:20:43.806 INFO 44376 --- [ main] o.s.b.a.e.jmx.EndpointMBeanExporter : Unregistering JMX-exposed beans on shutdown
2014-11-03 13:20:43.806 INFO 44376 --- [ main] o.s.b.a.e.jmx.EndpointMBeanExporter : Unregistering JMX-exposed beans
2014-11-03 13:20:43.807 INFO 44376 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
Exception in thread "main" java.lang.IllegalStateException: Unable to configure LocalContainerEntityManagerFactoryBean from @EntityScan, ensure an appropriate bean is registered.
at org.springframework.util.Assert.state(Assert.java:385)
at org.springframework.boot.orm.jpa.EntityScanRegistrar$EntityScanBeanPostProcessor.onApplicationEvent(EntityScanRegistrar.java:124)
at org.springframework.boot.orm.jpa.EntityScanRegistrar$EntityScanBeanPostProcessor.onApplicationEvent(EntityScanRegistrar.java:94)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:773)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:131)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:483)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:692)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:962)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:951)
at org.springframework.boot.SpringApplication$run.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
at geit.api.ApiApplication.main(ApiApplication.groovy:31)
:api:bootRun FAILED
FAILURE: Build failed with an exception.
I've also tried with @EntityScan(basePackages = "geit.domain") to trigger scanning from a package higher in the hierarchy, but this gives the same error
But, if I move the domain/entity classes into the (jersey) application module, then it works. This however, prevents me from using gorm in more than one application. Which is something we need to achieve, so that module 1,2 and 4 above can use the standalone gorm module
Is this a missing feature or bug? :)
PS. When moving the Application class to the top-level package, then it works ok! That is, from package /geit/api/Application.groovy to /geit/Application.groovy All submodules have the same toplevel package name, so maybe that is why it works? It still puzzles my though
The question left unanswered. Our solution is to convert from GORM to spring-data/jpa.