play フレームワーク v2.3.8 アプリケーション内から spring-data-solr クエリを作成すると、問題が発生し続けます。クエリは成功したように見えますが、Spring が使用しているクラス ローダーは、データ モデル クラスのクラス ファイルを見つけることができず、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);
}
Play フレームワークの Application クラス:
package controllers;
import java.util.ArrayList;
import java.util.List;
import model.Theatre;
import model.TheatreRepository;
import play.*;
import plugins.solr.SolrPlugin;
import views.html.*;
public class Application extends Controller {
public static Result index() {
TheatreRepository repository = Play.application().plugin( SolrPlugin.class ).getTheatreRepository();
if( repository != null )
{
List<Theatre> allTheatres = null;
try
{
allTheatres = repository.findByDocType("theatre");
Logger.info( "List of theatres found: " + allTheatres.toString() );
for(Theatre theatre: allTheatres)
{
Logger.info( "This theatre is: " + theatre.toString() );
}
}
catch( NoClassDefFoundError | ClassNotFoundException e )
{
Logger.error( "Classpath: " + System.getProperty( "java.class.path" ) );
}
}
else
{
Logger.error( "TheatreRepository is NULL!" );
}
return ok(index.render("Your new application is ready."));
}
}
そして、春の ApplicationContext :
package plugins.solr;
import play.Plugin;
import model.TheatreRepository;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import play.Logger;
import play.Play;
import play.api.Application;
public class SolrPlugin extends Plugin
{
private TheatreRepository theatreRepository;
ApplicationContext ctx;
public SolrPlugin(Application app)
{
}
public TheatreRepository getTheatreRepository()
{
return theatreRepository;
}
@Override
public void onStart()
{
super.onStart();
Logger.info( "Solr plugin started" );
ctx = new AnnotationConfigApplicationContext(SolrConfig.class);
theatreRepository = ctx.getBean( TheatreRepository.class );
}
}
JavaConfig ベースのスプリング構成は次のとおりです。
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()
にブラウザ ウィンドウをリロードするときに呼び出され、その結果、への呼び出しtheatreRepository.findByDocType("theatre");
が実行されます。これは、その呼び出しからのスタック トレースです。
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 フレームワークのクラス ローダーにあるが、システム クラス ローダーにはないことです。TheatreRespoitory
ただし、そのクラスのインスタンスをインスタンス化する必要があるときに、Spring がクラス ファイルを見つけることができたため、これは問題ではないようです。私が間違っている簡単なことがあるに違いないと思いますが、いくつかのことを試して調査を行った後、私はまだ途方に暮れています. 次の投稿を見つけましたが、spring-data-mongodb のバージョン間の違いを参照しているため、関連性がないようです。
また、Spring アプリケーション コンテキストで次のようにして、play フレームワーク クラス ローダーを使用してみました。SolrPlugin.onStart()
ctx = new AnnotationConfigApplicationContext(SolrConfig.class);
((AnnotationConfigApplicationContext)ctx).setClassLoader( Play.application().classloader() );
これにより、同じNoClassDefFoundError
スタックトレースが発生しました。クラスローダーを設定した直後に、この同じ関数でクエリを作成しようとしましたが、同じエラーが再び発生しました。