Standalone GORM does not find entity classes using Spring-boot and multimodule Gradle build

295 views
Skip to first unread message

Rune Engseth

unread,
Nov 7, 2014, 7:18:48 AM11/7/14
to grails-de...@googlegroups.com
Hi

This is a "fork" of the original question on SO.
http://stackoverflow.com/questions/26714530/spring-boot-does-not-honour-entityscan-in-multimodule-gradle-build-using-gorm

I quickly scanned the Configuration of the Grails documentation, without finding any clues on how to override/set where the entity classes are located

--

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 Spring boot 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




Reply all
Reply to author
Forward
0 new messages