在Play框架应用程序中在spring-data-solr中进行查询时出现NoClassDefFoundError [英] NoClassDefFoundError when making a query in spring-data-solr within a play framework application

查看:99
本文介绍了在Play框架应用程序中在spring-data-solr中进行查询时出现NoClassDefFoundError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的播放框架v2.3.8应用程序中进行spring-data-solr查询时,我一直遇到问题.该查询似乎成功了,但随后Spring正在使用的类加载器找不到我的数据模型类的类文件,并抛出了NoClassDefFoundError.这是一些相关的代码.

I keep running into an issue when making a spring-data-solr query from within my play framework v2.3.8 application. The query seems to succeed but then the class loader spring is using can't find the class files for my data model classes and throws a NoClassDefFoundError. Here is some relevant code.

首先将数据模型放入模型"包中:

First the data model in package '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);
}

播放框架中的Application类:

The Application class in play framework:

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."));
    }
}

还有Spring的ApplicationContext:

And the ApplicationContext for spring:

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的spring配置:

Here is the JavaConfig based spring configuration:

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");的调用.这是该调用的堆栈跟踪:

So at run time Application.index() gets called when reloading the browser window and as a result the call to theatreRepository.findByDocType("theatre"); gets executed. This is the stack trace from that call:

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框架类加载器中,而不在系统类加载器中.但是,这似乎不应该是问题,因为spring可以在需要实例化该类的实例时找到TheatreRespoitory类文件.我认为肯定有一些简单的事情我做错了,但是尝试了几件事并进行研究之后,我仍然感到茫然. 我确实找到了以下帖子,但似乎无关紧要,因为它引用的是spring-data-mongodb版本之间的差异.

What I have noticed is that the model.Theatre class files are in play frameworks class loader but not in the system class loader. However, this doesn't seem like it should be a problem because spring was able to find the TheatreRespoitory class file when it needed to instantiate an instance of that class. I figure there must be something simple that I'm doing wrong but after trying a few things and doing research I'm still at a loss. I did find the following post but it doesn't seem to be relevant since it is referencing a difference between versions of spring-data-mongodb.

MongoDB NoClassDefFoundError

此外,我只是通过在SolrPlugin.onStart()

ctx = new AnnotationConfigApplicationContext(SolrConfig.class);
((AnnotationConfigApplicationContext)ctx).setClassLoader( Play.application().classloader() );

这导致相同的NoClassDefFoundError和堆栈跟踪.我还尝试在设置类加载器后立即在相同的函数中进行查询,并再次收到相同的错误.

This resulted in the same NoClassDefFoundError and stack trace. I also tried making the query in this same function, right after setting the class loader, and received the same error again.

推荐答案

一种解决方法是强制MappingMongoConverter中的ReflectionEntityInstantiator还原为1.7.0.RELEASE基于反射的实例化策略.例如:

A workaround is to force ReflectionEntityInstantiator in MappingMongoConverter which reverts to pre 1.7.0.RELEASE instantiation strategy based on reflection. For example:

mappingConverter.setInstantiators(
    new EntityInstantiators(ReflectionEntityInstantiator.INSTANCE));

这篇关于在Play框架应用程序中在spring-data-solr中进行查询时出现NoClassDefFoundError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆