当我的映射类在一个单独的jar文件中时,playorm启动异常

时间:2012-10-18 15:07:28

标签: playorm

当我在同一个项目中运行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

1 个答案:

答案 0 :(得分: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);
    }
}

注意它位于静态初始化程序块中,因此将运行一次,此代码在正常情况下始终有效。例如,如果你有一个Car类在一个ClassLoader中创建,并且在另一个类加载器中创建了相同的Car类,你实际上可以像这样(Car)汽车一样投射并得到一个classCastException,因为这是一辆Car in one classloader不是其他类加载器的Car。

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

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

编辑:好的,还有,你需要为javassist设置线程Context Loader ....我将在PlayOrm中解决这个问题,所以在下一个版本中你将不必....现在这样做< / p>
  1. 调用Thread.currentThread.setContextClassLoader(yourClassloader)
  2. 调用Bootstrap.create并将其传递给SAME类加载器
  3. 验证javassist是从同一个类加载器加载的
  4. 以下是代码,我在其中找到了有关哪个类加载器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     }
    

    迪安