OSGi客户端从JavaEE服务器访问EJB的RMI ClassCastException [英] RMI ClassCastException in OSGi client accessing EJB from JavaEE server

查看:156
本文介绍了OSGi客户端从JavaEE服务器访问EJB的RMI ClassCastException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个OSGi应用程序。使用EJB context.lookup必须将Thread上下文类加载器设置为bundle类加载器才能投射。像这样:

  Thread.currentThread()。setContextClassLoader(getClass()。getClassLoader()); 
Entity entity = bean.getOne();
System.out.println(entity.getClass()。getClassLoader());

输出是


org.apache.felix.framework.BundleWiringImpl@7468776f

此代码有效。如果我有ArrayList,则无法进行转换。

  Thread.currentThread()。setContextClassLoader(getClass()。getClassLoader )); 
ArrayList< Entity>实体= bean.getMany();

此代码返回ClassCastException。



检查

  ArrayList< Entity> temp = new ArrayList< Entity>(); 
System.out.println(temp.getClass()。getClassLoader());

返回NULL - 它表示 bootstrap类。如何解决这个问题?



编辑: ArrayList with String works,classic array works,但ArrayList and ArrayList with Entiry does not work。

 类Bean {
....
@Override //这不起作用
public ArrayList< Entity> readMany(){
Entity dir1 = new Entity();
dir1.setContent(1 test);
实体dir2 =新实体();
dir2.setContent(2 test);
ArrayList< Entity> result = new ArrayList<>();
result.add(dir1); result.add(dir2);
返回结果;
}

@Override //这个工作
public ArrayList< String> readMany2(){
String str1 = new String(1 test);
String str2 = new String(2 test);
ArrayList< String> result = new ArrayList<>();
result.add(str1);
result.add(str2);
返回结果;


@Override //这个工作
public Entity [] readArray(){
ArrayList< Entity> AL = readMany();
实体[] ar =新实体[al.size()];
for(int i = 0; i< al.size(); i ++){
ar [i] = al.get(i);
}
return ar;
}

@Override //这不工作$ b $ public ArrayList readSimpleArrayList(){
ArrayList< Entity>加仑= readMany();
ArrayList al = new ArrayList();
for(Entity obj:gal){
al.add(obj);
}
return al;
}
...
}

这里是日志


java.lang.ClassCastException:
com.test.cmn.shd.base.dir.language.LanguageDirEntity不能转换to
com.test.cmn.shd.base.dir.language.LanguageDirEntity at
com.test.cmn.dt.base.Activator.start(Activator.java:83)at
org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:645)
在org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
。在组织。 apache.felix.framework.Felix.startBundle(Felix.java:1895)维持在
org.apache.felix
org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)。 framework.BundleImpl.start(BundleImpl.java:931)在
com.test.cmn.dt.loader.LoaderModel.startCoreModule(LoaderModel.java:149)
在com.test.cmn.dt. loader.LoaderModel.access $ 100(LoaderModel.java:39)
at
com.test.cmn.dt.loader.LoaderModel $ InstallAndStartModuleWorker.doInBackg轮(LoaderModel.java:79)
。在
$ com.test.cmn.dt.loader.LoaderModel InstallAndStartModuleWorker.doInBackground(LoaderModel.java:73)
。在javax.swing.SwingWorker $ 1 .CALL(SwingWorker.java:296)在
java.util.concurrent.FutureTask.run(FutureTask.java:262)在
javax.swing.SwingWorker.run(SwingWorker.java:335)在
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
。在
$ java.util.concurrent.ThreadPoolExecutor中Worker.run(ThreadPoolExecutor.java:615)
在java.lang.Thread.run(Thread.java:744)

编辑2 - 完整代码 strong>此代码在客户端计算机上执行。 JavaEE(GF4)正在服务器上运行。有三个osgi包:用于服务器,用于客户端和共享。的共享副本是无论在服务器和客户端上,并包含和LanguageDirBeanRemote LanguageDirEntity。



 类加载器thatLoader = Thread.currentThread()。 getContextClassLoader(); 
Thread.currentThread()。setContextClassLoader(getClass()。getClassLoader());
尝试{
属性jndiProps = new Properties();
jndiProps.put(java.naming.factory.initial,com.sun.enterprise.naming.impl.SerialInitContextFactory);
jndiProps.put(java.naming.factory.url.pkgs,com.sun.enterprise.naming);
jndiProps.put(java.naming.factory.state,com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl);
jndiProps.setProperty(org.omg.CORBA.ORBInitialHost,x.x.x.x);
jndiProps.setProperty(org.omg.CORBA.ORBInitialPort,3700);
InitialContext ctx = new InitialContext(jndiProps);
LanguageDirBeanRemote bean =(LanguageDirBeanRemote)ctx.lookup(java:global / ...);
ArrayList< LanguageDirEntity>元素= bean.readDirectory();
System.out.println(这里我得到错误:+ elements.get(0).getContent());
} finally {
Thread.currentThread()。setContextClassLoader(thatLoader);
}

编辑3
我打开了一个 bug

解决方案

谢谢大家。我终于解决了它。我正在写我如何理解它。有两种方法可以将gf-client与osgi客户端一起使用:


  1. 不是官方的方式 - 通过glassfish捆绑并通过手动方式安装osgi api。

  2. 官方方式 - 将glassfish / lib / gf-client.jar和glassfish / modules复制到客户端和classpath中添加gf-clinet.jar。 b

我不知道怎么做,我是用第一种方法做的。我不能说错,因为glassfish本身就是osgi。当我以第二种方式完成这个问题时,这个问题就消失了。所以当你从java classpath和osgi bundle加载时,问题出现在不同的类加载器中。


I have an OSGi application. Working with EJB context.lookup I had to set Thread context class loader as bundle class loader in order to be able to cast. Like this:

Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
Entity entity=bean.getOne();
System.out.println(entity.getClass().getClassLoader());

output is

org.apache.felix.framework.BundleWiringImpl@7468776f

This code works. The problem that I can't cast if I have ArrayList

Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
ArrayList<Entity> entities=bean.getMany();

This code returns ClassCastException.

Checking

ArrayList<Entity> temp=new ArrayList<Entity>();
System.out.println(temp.getClass().getClassLoader());

returns NULL - it means bootstrap class. How can it be fixed?

EDIT:

The most interesting, that ArrayList with String works, classic array works, but ArrayList and ArrayList with Entiry don't work.

Class Bean {
....
  @Override //THIS DOESN'T WORK
    public ArrayList<Entity> readMany() {
        Entity dir1=new Entity();
        dir1.setContent("1 test");
        Entity dir2=new Entity();
        dir2.setContent("2 test");
        ArrayList<Entity> result=new ArrayList<>();
        result.add(dir1);result.add(dir2);
        return result;
    }

    @Override //THIS WORKS
    public ArrayList<String> readMany2() {
        String str1=new String("1 test");
        String str2=new String("2 test");
        ArrayList<String> result=new ArrayList<>();
        result.add(str1);
        result.add(str2);
        return result; 
    }

@Override //THIS WORKS
public Entity[] readArray() {
    ArrayList<Entity> al=readMany();
    Entity[] ar=new Entity[al.size()];
    for (int i = 0; i < al.size(); i++) {
        ar[i]=al.get(i);
    }
    return ar;
}

@Override //THIS DOESN'T WORK
public ArrayList readSimpleArrayList() {
    ArrayList<Entity> gal=readMany();
    ArrayList al= new ArrayList();
    for (Entity obj : gal) {
        al.add(obj);
    }
    return al;
}
...
}

Here is the log

java.lang.ClassCastException: com.test.cmn.shd.base.dir.language.LanguageDirEntity cannot be cast to com.test.cmn.shd.base.dir.language.LanguageDirEntity at com.test.cmn.dt.base.Activator.start(Activator.java:83) at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:645) at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977) at org.apache.felix.framework.Felix.startBundle(Felix.java:1895) at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944) at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:931) at com.test.cmn.dt.loader.LoaderModel.startCoreModule(LoaderModel.java:149) at com.test.cmn.dt.loader.LoaderModel.access$100(LoaderModel.java:39) at com.test.cmn.dt.loader.LoaderModel$InstallAndStartModuleWorker.doInBackground(LoaderModel.java:79) at com.test.cmn.dt.loader.LoaderModel$InstallAndStartModuleWorker.doInBackground(LoaderModel.java:73) at javax.swing.SwingWorker$1.call(SwingWorker.java:296) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at javax.swing.SwingWorker.run(SwingWorker.java:335) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:744)

EDIT 2 - FULL CODE. This code is executed on client computer. JavaEE (GF4) is running on server. There are three osgi bundles:for server,for client and shared. The copy of shared is both on server and on clients and contains LanguageDirBeanRemote and LanguageDirEntity.

ClassLoader thatLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
try {
       Properties jndiProps = new Properties();
       jndiProps.put("java.naming.factory.initial", "com.sun.enterprise.naming.impl.SerialInitContextFactory");
       jndiProps.put("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
       jndiProps.put("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
       jndiProps.setProperty("org.omg.CORBA.ORBInitialHost", "x.x.x.x");
       jndiProps.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
       InitialContext ctx = new InitialContext(jndiProps);
       LanguageDirBeanRemote bean=(LanguageDirBeanRemote)ctx.lookup("java:global/...");
       ArrayList<LanguageDirEntity> elements=bean.readDirectory();
      System.out.println("HERE I GET THE ERROR:"+elements.get(0).getContent());
} finally {
Thread.currentThread().setContextClassLoader(thatLoader);
}

EDIT 3 I opened a bug

解决方案

Thank you everybody. I've finally solved it. I'm writing how as I understand it. There are two ways to use gf-client with osgi client:

  1. Not official way - take glassfish bundles and manually install them via osgi api.
  2. Official way - copy glassfish/lib/gf-client.jar and glassfish/modules to client and in classpath add gf-clinet.jar.

I don't know how, I did by the first way. I can't call it wrong, because glassfish is osgi itself. When I did it by the second way this problem disappeared. So the problem was in different classloaders when you load from java classpath and from osgi bundle.

这篇关于OSGi客户端从JavaEE服务器访问EJB的RMI ClassCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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