2014-11-03 3 views
2

У меня есть многомодульная градильна конструкция, использующая весеннюю загрузку и автономную GORM.Весенняя обувь не чести @EntityScan в многомодульной градировке с использованием GORM

Объекты домена расположены в отдельном подмодуле, поэтому эти объекты домена и gorm могут использоваться в нескольких приложениях с пружинной загрузкой (и без пружины).

Структуры

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) 

При запуске Gradle bootRun в Module1, приложение Джерси, он запускает приложение, однако при попытке получить доступ к остальному ресурса возвращающему животному, он терпит неудачу с 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) 

Так что я читал на документации, и найти это http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-separate-entity-definitions-from-spring-configuration Хм .. @EntityScan выглядит многообещающим

Так что я аннотирование моего класса приложений, как этого

@ComponentScan 
@EnableAutoConfiguration(exclude = GroovyTemplateAutoConfiguration.class) 
@EntityScan(basePackageClasses=Animal) 
class ApiApplication { 
    static void main(String[] args) { 
     SpringApplication.run ApiApplication, args 
    } 

} 

Но теперь, Gradle bootRun терпит неудачу при запуске

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[email protected]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. 

Я также попытался с @EntityScan (basePackages = «Гейт .domain ") для запуска сканирования из пакета выше в иерархии, но это дает ту же ошибку

Но, если я переведу классы домена/сущности в (трикотаж) на модуле, то он работает. Однако это мешает мне использовать gorm в нескольких приложениях. Это то, что нам нужно достичь, так что модули 1,2 и 4 выше могут использовать автономный модуль града

Это недостающая функция или ошибка?

PS. При перемещении класса Application в пакет верхнего уровня, он работает нормально! То есть, из пакета /geit/api/Application.groovy в /geit/Application.groovy Все подмодули имеют одинаковое имя пакета верхнего уровня, так что, возможно, именно поэтому она работает? Это все еще озадачивает меня, хотя

+0

'@ EntityScan' предназначен для JPA, и вы не используете его, если используете GORM (по крайней мере, не в том виде, в котором он был предназначен). Я не думаю, что есть эквивалентная аннотация. Возможно, Graeme или один, если команда Grails может помочь больше (если вы не можете добавить теги grails, спросите, и я сделаю это для вас). –

+0

Спасибо. Я добавил тег grails к вопросу. – runeaen

ответ

0

Вопрос остался без ответа. Нашим решением является преобразование из GORM в spring-data/jpa.

0

Я нашел своего рода способ взломать это.

Даже если мы занимаемся автономной загрузкой GORM + Spring, GORM по-прежнему получает экземпляр GrailsApplication.

Так подключите к почтовому процессору bean post. Когда наступит очередь на процесс sessionFactory, выберите базовый grailsApplication и зарегистрируйте свои классы домена Groovy как артефакты класса домена.

Здесь

@Component 
class GrailsApplicationPostProcessor implements BeanPostProcessor { 

    public static final String DEFAULT_SESSION_FACTORY_BEAN_NAME = "sessionFactory" 

    public static final Class [] domainClasses = [ 
     Client.class, Feature.class, User.class 
    ] 

    @Override 
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
     if (DEFAULT_SESSION_FACTORY_BEAN_NAME.compareTo(beanName) == 0) { 
     if (bean instanceof ConfigurableLocalSessionFactoryBean) { 
      ConfigurableLocalSessionFactoryBean sf = (ConfigurableLocalSessionFactoryBean) bean 
      GrailsApplication ga = sf.grailsApplication 
      String domainClassType = DomainClassArtefactHandler.TYPE 
      for (Class c in domainClasses) { 
       ga.addArtefact(domainClassType, c) 
      } 
     } 
     } 
     bean 
    } 

    @Override 
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
     bean 
    } 
} 

Другим решением было бы попробовать и упаковать классы доменов как двоичный плагин Grails, и загрузить плагин (и, следовательно, его ресурсы в комплекте) в этом методе постобработки. Надеюсь это поможет.

+0

OMG это действительно отстой. Даже при этом вы ** все еще ** должны иметь класс фиктивной сущности в корневом пакете вашего приложения, чтобы сообщить GORM «Да, пожалуйста, включите настойчивость для меня». Я поднимаю проблему для пользователей Spring. Благодарю. –