embed cxf in osgi

8 views
Skip to first unread message

pathfinder

unread,
Sep 7, 2007, 2:12:40 AM9/7/07
to cxf-zh
在我最近的项目中,需要在客户端使用Web Service。我的客户端采用osgi架构,因此在整合过程中出现了一些问题。

其中一个比较严重的问题就是classloader。当第一次启动时,所有的程序都OK,但一旦我update了调用cxf的bundle,就会报以下
的错误:

java.lang.ClassCastException: class org.apache.cxf.bus.CXFBusFactory
at java.lang.Class.asSubclass(Class.java:3018)
at org.apache.cxf.BusFactory.newInstance(BusFactory.java:149)
at org.apache.cxf.BusFactory.newInstance(BusFactory.java:132)
at org.apache.cxf.BusFactory.getDefaultBus(BusFactory.java:69)
at org.apache.cxf.BusFactory.getDefaultBus(BusFactory.java:58)
at org.apache.cxf.BusFactory.getThreadDefaultBus(BusFactory.java:98)
at
org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:
54)
at javax.xml.ws.Service.<init>(Service.java:57)
at javax.xml.ws.Service.create(Service.java:302)
......

我查看了BusFactory.newInstance()的代码,如下:

ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();
......
Class<? extends BusFactory> busFactoryClass;
try {
busFactoryClass = Class.forName(className, true,
classLoader).asSubclass(BusFactory.class);
instance = busFactoryClass.newInstance();
} catch (Exception ex) {
LogUtils.log(LOG, Level.SEVERE,
"BUS_FACTORY_INSTANTIATION_EXC", ex);
throw new RuntimeException(ex);
}

很显然这个错误就是由于context classloader 和 default classloader 不一致导致的。不知道有什么简单的方法
解决?

当然我可以在Activator.start中强制将context classloader设为当前class的classloader,但这个好像
不太合适。

Willem Jiang

unread,
Sep 7, 2007, 2:28:52 AM9/7/07
to cxf...@googlegroups.com
我觉得你可以在初始化CXF的时候把context classloader设为当前class的
classloader,在调用完成后再把context classloader设回去就行了。

不太明白你下面这段话的意思?

"当第一次启动时,所有的程序都OK,但一旦我update了调用cxf的bundle,就会报以下
的错误:"

你所说的update是啥意思?

BTW
IONA内部也在Eclipse中使用CXF,好像没有出现过你所说的这个问题。

Willem

alexgreenbar

unread,
Sep 7, 2007, 2:33:05 AM9/7/07
to cxf-zh
What's your meaning for "但一旦我update了调用cxf的bundle"? Do you mean you
update your bundle which will call cxf dynamically in OSGi
environment?

I use CXF embedded into Eclipse for a while, before cxf 2.0 release,
there has a big issue of initializing cxf bus inside Eclipse due to
cxf use Spring bean configuration, but Spring can't load its
configuration from Eclipse bundle(plugin)
But so far it works fine for me.

Also, you can try:
*****************
//use spring bus factory
SpringBusFactory spFactory = new SpringBusFactory();
Bus bus = spFactory.createBus("/cxfconfig/cxf.xml", false);
spFactory.setDefaultBus(bus);
*****************

cxf.xml is a configuration file include all beans' config which needed
by cxf, you can put cxf.xml into one of your bundle

wish this help
--Alex

maomao

unread,
Sep 7, 2007, 2:46:47 AM9/7/07
to cxf-zh
有可能是版本引起的,你用的是什么版本呢? 建议使用最新的版本
或者试试alex说的这个方法。

不过他说是在update时候才出现问题

pathfinder

unread,
Sep 7, 2007, 2:48:28 AM9/7/07
to cxf-zh

On 9月7日, 下午2时33分, alexgreenbar <alexgreen...@gmail.com> wrote:
> What's your meaning for "但一旦我update了调用cxf的bundle"? Do you mean you
> update your bundle which will call cxf dynamically in OSGi
> environment?

是的,其实我就是在equinox的控制台中用 refresh 命令动态的更新了那个使用cxf的bundle。
呵呵,不好意思,没描述清楚。

目前我就是采用willem 的办法, 在 start()开始时,将当前的classloader设为context classloader,
然后在start()结束时,再设回context classloader。但这个方法我看起来不是很稳妥。 ^_^

我知道在spring-osgi 中可以帮助管理 context classloader,而且cxf也大量的运用了spring,
就是不知道啥时候能够出一个osgi版的cxf,能方便的在osgi环境中使用。

昨天我在查看http://people.apache.org/repo/m2-incubating-repository/时,看到一个cxf-
bundle,还很开心的以为就是一个osgi版的cxf,
下来一看MANIFEST.MF,才发现里面一点OSGI的配置都没有,失望啊。

willem

unread,
Sep 7, 2007, 3:30:04 AM9/7/07
to cxf-zh
你遇到的这个 java.lang.ClassCastException 是由于两个没有直接继承关系的class loader分别加载了
org.apache.cxf.bus.CXFBusFactory所造成的。
设置 thread context class loader 是一个有效的方法,也是Java 给我们的一个救命稻草 :)

如果你觉得直接设置thread context class loader 不放心(其实也没有什么不放心的地方),那你可以看看这篇文章,看完你就
应该放心了。
http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html


Willem.

On Sep 7, 2:12 pm, pathfinder <pathfinder.n...@gmail.com> wrote:

alexgreenbar

unread,
Sep 7, 2007, 3:44:09 AM9/7/07
to cxf-zh
did you try to reinstall/restart your bundle? AFAIK, I don't think put
code into bundle's start() method is a good way, if there has any
exceptions in your bundle's start() method, your bundle will be dead
locked, and it's very very hard to debug this.

if you have to use thread context classloader so far, please put the
code somewhere but start() method

OSGi specification do support dynamical update bundle, but I don't
know if equinox implement it or not? as you know, Eclipse itself need
restart when you update one of your plugin using Eclipse update
manager.

Cheers,
--Alex

Reply all
Reply to author
Forward
0 new messages