1

当我在同一个项目中运行我的 playOrm junit 测试时,我有 nosql.Persistence 类(以及我的映射实体)它运行良好。但是,我需要使用我的 DAO 和我的 find 方法将我的实体打包到一个 jar 文件中。当我从其他项目中使用这个 dao 时,我得到了下面的异常。

没有线索。关于从哪里开始寻找的任何想法?

java.lang.RuntimeException: Failure scanning class(see chained exception)=class com.alvazan.orm.api.z8spi.meta.DboTableMeta
    at com.alvazan.orm.layer0.base.MyClassAnnotationDiscoveryListener.scanClass(MyClassAnnotationDiscoveryListener.java:44)
    at com.alvazan.orm.layer0.base.MyClassAnnotationDiscoveryListener.discovered(MyClassAnnotationDiscoveryListener.java:34)
    at com.impetus.annovention.Discoverer.discoverAndIntimateForClassAnnotations(Discoverer.java:197)
    at com.impetus.annovention.Discoverer.discover(Discoverer.java:155)
    at com.alvazan.orm.layer0.base.BaseEntityManagerFactoryImpl.rescan(BaseEntityManagerFactoryImpl.java:80)
    at com.alvazan.orm.layer0.base.BaseEntityManagerFactoryImpl.setup(BaseEntityManagerFactoryImpl.java:131)
    at com.alvazan.orm.impl.bindings.BootstrapImpl.createInstance(BootstrapImpl.java:51)
    at com.alvazan.orm.api.base.Bootstrap.create(Bootstrap.java:53)
    at com.alvazan.orm.api.base.Bootstrap.create(Bootstrap.java:48)
    at com.alvazan.orm.api.base.Bootstrap.create(Bootstrap.java:45)
    at com.alvazan.orm.api.base.Bootstrap.create(Bootstrap.java:41)
    at com.s1mbi0se.dmp.da.dao.PlayOrmConfiguration.init(PlayOrmConfiguration.java:40)
    at com.s1mbi0se.dmp.da.dao.PlayOrmConfiguration.getEntityManager(PlayOrmConfiguration.java:46)
    at com.s1mbi0se.dmp.da.dao.AbstractDao.getEm(AbstractDao.java:10)
    at com.s1mbi0se.dmp.da.dao.UserDao.insertOrUpdateUser(UserDao.java:15)
    at com.s1mbi0se.dmp.module.UserModule.persistData(UserModule.java:101)
    at com.s1mbi0se.dmp.processor.mapred.SelectorReducer.reduce(SelectorReducer.java:55)
    at com.s1mbi0se.dmp.processor.mapred.SelectorReducer.reduce(SelectorReducer.java:1)
    at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:176)
    at org.apache.hadoop.mapred.Task$NewCombinerRunner.combine(Task.java:1502)
    at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.sortAndSpill(MapTask.java:1436)
    at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.flush(MapTask.java:1298)
    at org.apache.hadoop.mapred.MapTask$NewOutputCollector.close(MapTask.java:699)
    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:766)
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:370)
    at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:212)
Caused by: com.google.inject.ProvisionException: Guice provision errors:

1) Error injecting constructor, java.lang.ExceptionInInitializerError
  at com.alvazan.orm.impl.meta.data.MetaClassSingle.<init>(MetaClassSingle.java:22)
  while locating com.alvazan.orm.impl.meta.data.MetaClassSingle

1 error
    at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:987)
    at com.alvazan.orm.impl.meta.data.MetaInfo.findOrCreate(MetaInfo.java:60)
    at com.alvazan.orm.impl.meta.scan.ScannerForClass.addClass(ScannerForClass.java:57)
    at com.alvazan.orm.layer0.base.MyClassAnnotationDiscoveryListener.scanClass(MyClassAnnotationDiscoveryListener.java:42)
    ... 25 more
Caused by: java.lang.ExceptionInInitializerError
    at com.alvazan.orm.impl.meta.data.MetaAbstractClass.<init>(MetaAbstractClass.java:17)
    at com.alvazan.orm.impl.meta.data.MetaClassSingle.<init>(MetaClassSingle.java:22)
    at com.alvazan.orm.impl.meta.data.MetaClassSingle$$FastClassByGuice$$29abb300.newInstance(<generated>)
    at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40)
    at com.google.inject.internal.DefaultConstructionProxyFactory$1.newInstance(DefaultConstructionProxyFactory.java:60)
    at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85)
    at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
    at com.google.inject.internal.InjectorImpl$4$1.call(InjectorImpl.java:978)
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1024)
    at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:974)
    ... 28 more
Caused by: java.lang.ClassCastException: com.alvazan.orm.api.z8spi.meta.TypedRow_$$_javassist_0 cannot be cast to javassist.util.proxy.Proxy
    at com.alvazan.orm.api.z8spi.meta.DboTableMeta.testInstanceCreation(DboTableMeta.java:93)
    at com.alvazan.orm.api.z8spi.meta.DboTableMeta.<clinit>(DboTableMeta.java:84)
    ... 38 more
4

1 回答 1

2

您遇到了某种类加载问题。创建 NoSqlEntityManagerFactory 时可能需要传入类加载器。你在这里处理这段代码

static {
    ProxyFactory f = new ProxyFactory();
    f.setSuperclass(TypedRow.class);
    f.setInterfaces(new Class[] {NoSqlTypedRowProxy.class});
    f.setFilter(new MethodFilter() {
        public boolean isHandled(Method m) {
            // ignore finalize()
            if(m.getName().equals("finalize"))
                return false;
            else if(m.getName().equals("equals"))
                return false;
            else if(m.getName().equals("hashCode"))
                return false;
            return true;
        }
    });
    Class clazz = f.createClass();
    testInstanceCreation(clazz);

    typedRowProxyClass = clazz;

    NAME_PATTERN = Pattern.compile("[a-zA-Z_][a-zA-Z_0-9]*");
}

private static Proxy testInstanceCreation(Class<?> clazz) {
    try {
        Proxy inst = (Proxy) clazz.newInstance();
        return inst;
    } catch (InstantiationException e) {
        throw new RuntimeException("Could not create proxy for type="+clazz, e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException("Could not create proxy for type="+clazz, e);
    }
}

注意它位于静态初始化块中,因此将运行一次,并且此代码在正常情况下始终有效。例如,如果您有一个在一个 ClassLoader 中创建的 Car 类,并且在另一个类加载器中创建了同一个 Car 类,您实际上可以像这样 (Car)car 进行强制转换并获得一个 classCastException,因为该汽车是一个 Car类加载器不是其他类加载器的 Car。

好的,所以第 1 步是在创建 NoSqlEntityManagerFactory 时尝试传入您自己的类加载器,这样您就知道正在使用哪个类加载器。查看我上面的代码,我不确定哪个类加载器正在创建代理,所以我需要检查它以确保它是同一个类加载器。

一个大问题是 hadoop 是否已经在使用另一个类加载器中加载的 javassist,或者您是否将 javassist 作为 mapreduce 作业的一部分发送?

编辑:好的,另外,您还需要为 javassist 设置线程 Context Loader....我将在 PlayOrm 中修复此问题,因此在下一个版本中您不必...现在执行此操作

  1. 调用 Thread.currentThread.setContextClassLoader(yourClassloader)
  2. 调用 Bootstrap.create 并将其传递给 SAME 类加载器
  3. 验证 javassist 是从同一个类加载器加载的

这是我找到关于哪个类加载器 javassist 正在使用的信息供您参考的代码

   protected ClassLoader getClassLoader0() {
591         ClassLoader loader = null;
592         if (superClass != null && !superClass.getName().equals("java.lang.Object"))
593             loader = superClass.getClassLoader();
594         else if (interfaces != null && interfaces.length > 0)
595             loader = interfaces[0].getClassLoader();
596  
597         if (loader == null) {
598             loader = getClass().getClassLoader();
599             // In case javassist is in the endorsed dir
600             if (loader == null) {
601                 loader = Thread.currentThread().getContextClassLoader();
602                 if (loader == null)
603                     loader = ClassLoader.getSystemClassLoader();
604             }
605         }
606 
607         return loader;
608     }

院长

于 2012-10-18T15:31:00.320 回答