Maven Spring引导开发工具:使用CommandLineRunner和Spring数据存储库进行热重新加载时崩溃

Maven Spring引导开发工具:使用CommandLineRunner和Spring数据存储库进行热重新加载时崩溃,maven,intellij-idea,spring-boot,spring-data,Maven,Intellij Idea,Spring Boot,Spring Data,我正在用SpringBoot1.3.2、SpringDataMongoDB和SpringSecurity开发一个项目,使用开发工具,IntellijIDEA15.0.3,使用Maven 我确实阅读了SpringBootDeveloper工具,并按照指示仔细配置了所有内容,热重新加载工作正常 然后,由于我需要在应用程序启动期间执行一些任务,主要是连接到数据库并执行验证,如果需要,还需要执行插入,因此我决定使用CommandLineRunnerbean,如下所示: @Configuration pu

我正在用SpringBoot1.3.2、SpringDataMongoDB和SpringSecurity开发一个项目,使用开发工具,IntellijIDEA15.0.3,使用Maven

我确实阅读了SpringBootDeveloper工具,并按照指示仔细配置了所有内容,热重新加载工作正常

然后,由于我需要在应用程序启动期间执行一些任务,主要是连接到数据库并执行验证,如果需要,还需要执行插入,因此我决定使用
CommandLineRunner
bean,如下所示:

@Configuration
public class DatabaseInitializer {

   @Bean
   CommandLineRunner verifyConfiguration(ConfigurationRepository repository) {
       return args -> { 
           // The id is a provided one and i can't modify it.
           if (repository.findOne(...) == null) { // this is the offending line 
               //perform some tasks here  
           }
       };
   }

   // more CommandLineRunners following the same approach

}
如果我重新启动应用程序,一切正常,没有崩溃,没有错误,但是当我触发dev tools热重新加载时,它会失败,并抛出以下堆栈跟踪:

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:809) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:790) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:777) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
    at com.adrisasws.gestor.CesteriaApariciApplication.main(CesteriaApariciApplication.java:15) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_72]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_72]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_72]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_72]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.3.2.RELEASE.jar:1.3.2.RELEASE]
Caused by: org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate com.adrisasws.gestor.configuracion.api.outputs.ConfiguracionFacturacion using constructor NO_CONSTRUCTOR with arguments 
    at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:64) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
    at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:83) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:251) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:231) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1186) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.access$200(MappingMongoConverter.java:78) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1134) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getValueInternal(MappingMongoConverter.java:870) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWithPersistentProperty(MappingMongoConverter.java:283) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWithPersistentProperty(MappingMongoConverter.java:271) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:309) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:271) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:231) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:191) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:187) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:78) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate$ReadDbObjectCallback.doWith(MongoTemplate.java:2224) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:1855) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:1672) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate.findById(MongoTemplate.java:614) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.findOne(SimpleMongoRepository.java:119) ~[spring-data-mongodb-1.8.2.RELEASE.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_72]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_72]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_72]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_72]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:483) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:468) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:440) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at com.sun.proxy.$Proxy160.findOne(Unknown Source) ~[na:na]
    at com.adrisasws.gestor.Inicializacion.lambda$inicializacionConfiguracion$1(Inicializacion.java:47) ~[classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:806) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
    ... 11 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.adrisasws.gestor.configuracion.api.outputs.ConfiguracionFacturacion]: Specified class is an interface
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:101) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:61) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
    ... 47 common frames omitted
我知道它抱怨
configurationfacturacion
作为一个接口,文档的一个属性被声明为一个接口,但是在我的代码中,我总是实例化一个具体的实现,正如我所说,在正常启动和执行期间,一切都很好

所以基本上我的问题是:

  • 为什么它正常工作,但在热加载时失败?这是一个错误,然后我应该提交一个问题
  • <> LI>或者在使用<代码> @文档注释的实体类中使用抽象是一个非常糟糕的实践,我应该考虑重构?
另外,如果你需要更多的信息,请询问,我会更新问题

Update:当数据库中的元素不存在时,
CommandLineRunner
第一次运行,因此
findOne()
调用返回null,即热重新加载不会失败

Update2:避免使用
findOne()
,尽可能使用
exists()
count()
,解决了问题,但似乎不是一个确定的解决方案,因为幸运的是,在我的用例中,我不需要访问数据,只需检查数据是否存在,或者知道有多少条记录,但在其他一些必须访问数据的用例中,开发人员无法享受从DevTools热重新加载的好处

如果有任何帮助,下面是有关此特定问题的更多信息:

在Spring Data MongoDB的特定情况下,当
@Document
类中的一个字段被声明为接口时,则在数据库中,在表示该字段的嵌入文档中,插入一个名为
\u class
的属性,该属性的值为具体实现的完全限定类名,例如:

public class AddressDocument implements Address {
    ...
}

@Document
public class PersonDocument {
    private Address address;
    ...
}
执行以下操作时:

PersonDocument p = new PersonDocument();
p.setAddress(new AddressDocument(...));
repository.save(p);
然后,存储在数据库中的mongo文档将具有以下形式:

{
    ...
    address : {
        "_class" : "package.AddressDocument",
        ...
    }
    ...
}

因此,很明显,Spring数据正在使用
\u class
来确定要使用什么类来实例化该类,出于某种原因,DevTools正在绕过该机制。

撇开这是否是一种糟糕的做法不谈,如果您在实体类中使用的接口工作正常,并且仅在重新加载期间失败,那么我们(Spring Boot团队)希望看到这一点,并在可能的情况下予以修复。您能用一个小的示例项目打开一个Spring引导问题()吗?在问题跟踪器中创建了和。另外,我正在用我在创建演示项目时发现的一个小细节来更新这个问题。@AndyWilkinson如果你将你的发现的答案发布在网站上,我将很乐意接受。