OSGi客户端从JavaEE服务器访问EJB的RMI ClassCastException [英] RMI ClassCastException in OSGi client accessing EJB from JavaEE server
问题描述
我有一个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客户端一起使用:
- 不是官方的方式 - 通过glassfish捆绑并通过手动方式安装osgi api。
- 官方方式 - 将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:
- Not official way - take glassfish bundles and manually install them via osgi api.
- 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屋!