Java 在play framework应用程序内的spring data solr中进行查询时发生NoClassDefFoundError
在PlayFrameworkV2.3.8应用程序中进行SpringDataSolr查询时,我一直遇到一个问题。查询似乎成功了,但是spring使用的类加载器找不到我的数据模型类的类文件,并抛出一个Java 在play framework应用程序内的spring data solr中进行查询时发生NoClassDefFoundError,java,spring,solr,playframework,spring-data-solr,Java,Spring,Solr,Playframework,Spring Data Solr,在PlayFrameworkV2.3.8应用程序中进行SpringDataSolr查询时,我一直遇到一个问题。查询似乎成功了,但是spring使用的类加载器找不到我的数据模型类的类文件,并抛出一个NoClassDefFoundError。下面是一些相关代码 首先是包“model”中的数据模型: package model; import org.apache.solr.client.solrj.beans.Field; import org.springframework.data.annot
NoClassDefFoundError
。下面是一些相关代码
首先是包“model”中的数据模型:
package model;
import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.annotation.Id;
public class Theatre
{
@Id
String id;
@Field
String docType;
// other fields, getters, and setters omitted for brevity
}
以下是存储库:
package model;
import java.util.List;
import org.springframework.data.solr.repository.SolrCrudRepository;
public interface TheatreRepository extends SolrCrudRepository<Theatre, String>
{
List<Theatre> findByDocType(String doc__type);
void delete(Theatre deleted);
List<Theatre> findAll();
Theatre findOne(String id);
@SuppressWarnings("unchecked")
Theatre save(Theatre persisted);
}
以下是基于JavaConfig的spring配置:
package plugins.solr;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.solr.core.SolrOperations;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.repository.config.EnableSolrRepositories;
import org.springframework.data.solr.server.support.HttpSolrServerFactory;
import play.Play;
@ComponentScan
@Configuration
@EnableSolrRepositories(basePackages = { "model" })
public class SolrConfig
{
public SolrConfig()
{
}
@Bean
public SolrServer solrServer()
{
HttpSolrServerFactory factory = new HttpSolrServerFactory( new HttpSolrServer( Play.application().configuration().getString( "ems.solr.url" ) ) );
return factory.getSolrServer();
}
@Bean
public SolrOperations solrTemplate()
{
return new SolrTemplate( this.solrServer() );
}
}
因此,在运行时,重新加载浏览器窗口时调用Application.index()
,从而调用theaterepository.findByDocType(“theater”)代码>被执行。这是来自该调用的堆栈跟踪:
java.lang.NoClassDefFoundError: model/Theatre
at model.Theatre_Instantiator_982rn.newInstance(Unknown Source) ~[na:na]
at org.springframework.data.convert.BytecodeGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(BytecodeGeneratingEntityInstantiator.java:193) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
at org.springframework.data.convert.BytecodeGeneratingEntityInstantiator.createInstance(BytecodeGeneratingEntityInstantiator.java:76) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:127) ~[spring-data-solr-1.4.0.RELEASE.jar:na]
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:119) ~[spring-data-solr-1.4.0.RELEASE.jar:na]
Caused by: java.lang.ClassNotFoundException: model.Theatre
at java.lang.ClassLoader.findClass(ClassLoader.java:531) ~[na:1.7.0_80]
at java.lang.ClassLoader.loadClass(ClassLoader.java:425) ~[na:1.7.0_80]
at java.lang.ClassLoader.loadClass(ClassLoader.java:358) ~[na:1.7.0_80]
at model.Theatre_Instantiator_982rn.newInstance(Unknown Source) ~[na:na]
at org.springframework.data.convert.BytecodeGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(BytecodeGeneratingEntityInstantiator.java:193) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
我注意到,model.Theatre
类文件在play frameworks类装入器中,但不在系统类装入器中。然而,这似乎不应该是一个问题,因为spring能够在需要实例化类的实例时找到TheaterEspority
类文件。我想一定有一些简单的事情我做错了,但在尝试了一些事情和做了一些研究之后,我仍然不知所措。
我确实找到了下面的帖子,但似乎并不相关,因为它引用了SpringDataMongoDB版本之间的差异
此外,我还尝试在spring应用程序上下文中使用play Framework类加载器,方法是在SolrPlugin.onStart()中执行以下操作
这导致相同的NoClassDefFoundError
和堆栈跟踪。在设置类加载器之后,我还尝试在同一个函数中进行查询,但再次收到相同的错误 一种解决方法是在MappingMongoConverter
中强制使用ReflectionTityInstantiator
,它将恢复到1.7.0之前的版本。基于反射的发布实例化策略。例如:
mappingConverter.setInstantiators(
new EntityInstantiators(ReflectionEntityInstantiator.INSTANCE));
我从未能够使用SpringDataSolr1.4.0解决这个问题。然而,我更新到SpringDataSolr1.4.1,并克服了这个错误!所以我猜这是1.4.0中的一个bug。然而,我在1.4.1中也发现了一个bug。如果solr文档中有任何多值
字段,那么当spring data solr试图通过type.getComponentType()
获取组件的类型属性时,它将在MappingSolrConverter.SolrPropertyValueProvider.readValue()
中失败,并出现空指针异常。我通过删除文档中所有的多值
字段来解决这个问题(不理想)在MappingMongoConverter
中设置实例化策略将如何帮助我处理MappingSolrConverter
中的mulitValued
字段?这是根据堆栈跟踪解决由bytecodegeneratingtityinstantiator
引起的noClassDefoundError
的方法。请注意剧院实例化器982rn
,它是运行时生成的类。我的解决方案从bytecodegeneratingtityinstantiator
变为reflectiontityinstantiator
,速度较慢,但也不太依赖于类加载器的设置。此处的详细信息:。好的。。。但是,正如我在上面的评论中提到的,这个错误在1.4.1中已经修复,因此没有必要绕过字节码生成TityInstantiator
。但是,我可以尝试您的解决方案,看看1.4.0中是否存在多值
solr字段错误(我猜是这样的)
java.lang.NoClassDefFoundError: model/Theatre
at model.Theatre_Instantiator_982rn.newInstance(Unknown Source) ~[na:na]
at org.springframework.data.convert.BytecodeGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(BytecodeGeneratingEntityInstantiator.java:193) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
at org.springframework.data.convert.BytecodeGeneratingEntityInstantiator.createInstance(BytecodeGeneratingEntityInstantiator.java:76) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:127) ~[spring-data-solr-1.4.0.RELEASE.jar:na]
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:119) ~[spring-data-solr-1.4.0.RELEASE.jar:na]
Caused by: java.lang.ClassNotFoundException: model.Theatre
at java.lang.ClassLoader.findClass(ClassLoader.java:531) ~[na:1.7.0_80]
at java.lang.ClassLoader.loadClass(ClassLoader.java:425) ~[na:1.7.0_80]
at java.lang.ClassLoader.loadClass(ClassLoader.java:358) ~[na:1.7.0_80]
at model.Theatre_Instantiator_982rn.newInstance(Unknown Source) ~[na:na]
at org.springframework.data.convert.BytecodeGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(BytecodeGeneratingEntityInstantiator.java:193) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
ctx = new AnnotationConfigApplicationContext(SolrConfig.class);
((AnnotationConfigApplicationContext)ctx).setClassLoader( Play.application().classloader() );
mappingConverter.setInstantiators(
new EntityInstantiators(ReflectionEntityInstantiator.INSTANCE));