在 Java 1.6 中为 JAX-WS 提供不同版本的 JAXB [英] Supplying a different version of JAXB for JAX-WS in Java 1.6

查看:57
本文介绍了在 Java 1.6 中为 JAX-WS 提供不同版本的 JAXB的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 jaxb-impl.jar 的第三方 jar,并将它包含在其清单类路径中.问题是,似乎提供您自己的 JAXB 版本(无论它可能是哪个版本)似乎会破坏 JAX-WS 中的 SoapFaultBuilder.

I have a third party jar that ships with a jaxb-impl.jar and includes it in its manifest classpath. The problem is, it seems as though supplying your own version of JAXB (regardless of which version it may be) seems to break the SoapFaultBuilder in JAX-WS.

根据 非官方 JAXB 指南,似乎 Sun 故意更改了包将 JAXB 折叠到 JDK 中时的名称,以避免与独立版本发生冲突.但是,JDK 附带的 SoapFaultBuilder(我相信是 JAX-WS 的一部分)明确依赖于新的内部包名称.如果您添加了独立的 JAXB jar(即使它是 JAXB 的编号相同版本),这会导致它在构建错误消息时失败.

According to the Unofficial JAXB Guide, it seems as though Sun deliberately changed the package name when it folded JAXB into the JDK in order to avoid conflicts with the stand-alone version. However, the SoapFaultBuilder (part of JAX-WS I believe) that ships with the JDK is explicitly dependent on the new, internal package name. This causes it to fail when building a fault message if you've added a stand-alone JAXB jar (even if it is the same version number of JAXB).

这是我的小测试用例:我制作了一个简单的 Web 服务:

Here is my small test case: I make a trivial Web Service:

package wstest;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

//Service Endpoint Interface
@WebService
@SOAPBinding(style = Style.RPC)
public interface HelloWorld{

    @WebMethod String getHelloWorldAsString(String name);

}

还有一个简单的抛出异常的实现.(因为问题只出现在 SOAPFaultBuilder 中):

And an implementation that simply throws an exception. (Since the problem only occurs in the SOAPFaultBuilder):

package wstest;

import javax.jws.WebService;

//Service Implementation
@WebService(endpointInterface = "wstest.HelloWorld")
public class HelloWorldImpl implements HelloWorld{

    @Override
    public String getHelloWorldAsString(String name) {
        //return "Hello World JAX-WS " + name;
        throw new RuntimeException("Exception for: " + name);
    }

}

还有一个发布网络服务的类:

And a class to publish the web service:

package wstest;

import javax.xml.ws.Endpoint;

//Endpoint publisher
public class HelloWorldPublisher{

    public static void main(String[] args) {
       Endpoint.publish("http://localhost:9999/ws/hello", new HelloWorldImpl());
    }

}

我运行 HelloWorldPublisher,然后针对它运行这个客户端:

I run the HelloWorldPublisher, and then run this client against it:

package wstest;

import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class HelloWorldClient{

    public static void main(String[] args) throws Exception {

    URL url = new URL("http://localhost:9999/ws/hello?wsdl");

        //1st argument service URI, refer to wsdl document above
    //2nd argument is service name, refer to wsdl document above
        QName qname = new QName("http://wstest/", "HelloWorldImplService");

        Service service = Service.create(url, qname);

        HelloWorld hello = service.getPort(HelloWorld.class);

        System.out.println(hello.getHelloWorldAsString("Matt"));

    }

}

这正确地吐出了 Web 服务抛出的异常.但是,当我添加任何版本的 jaxb-impl.jar 时,无论是在类路径中还是在背书的库中,我都会得到以下堆栈跟踪:

This correctly spits out the exception that was thrown by the Web Service. However, when I add any version of jaxb-impl.jar, whether on the classpath or in the endorsed lib, I get this stack trace:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:107)
    at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
    at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
    at $Proxy19.getHelloWorldAsString(Unknown Source)
    at wstest.HelloWorldClient.main(HelloWorldClient.java:21)
Caused by: java.lang.ClassCastException: com.sun.xml.bind.v2.runtime.JAXBContextImpl cannot be cast to com.sun.xml.internal.bind.api.JAXBRIContext
    at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.<clinit>(SOAPFaultBuilder.java:533)
    ... 5 more

发生异常是因为来自我的 jaxb-impl 的 com.sun.xml.bind.v2.runtime.JAXBContextImpl 扩展了 com.sun.xml.bind.api.JAXBRIContext 而不是 com.sun.xml.internal.bind.api.JAXBRIContext(注意包层次结构中缺少的内部"子包).

The exception occurs because com.sun.xml.bind.v2.runtime.JAXBContextImpl from my jaxb-impl extends com.sun.xml.bind.api.JAXBRIContext instead of com.sun.xml.internal.bind.api.JAXBRIContext (note the missing 'internal' sub-package in the package hierarchy).

另外根据 非官方 JAXB 指南,他们说你需要使用认可的库为了正确覆盖 JAXB 的版本.但事实证明,SOAPFaultBuilder 使用 JAXBContext.newInstance() 在类路径中搜索名为 /META-INF/services/javax.xml.bind.JAXBContext 的文件,然后手动加载(并反射性地创建) 基于文件中指定的类名的 JAXBContext.所以没关系 - 类路径或认可的库给你相同的行为.

Also according to the Unofficial JAXB Guide, they say you need to use endorsed lib in order to correctly override the version of JAXB. As it turns out though, SOAPFaultBuilder uses JAXBContext.newInstance() to search the classpath for a file named /META-INF/services/javax.xml.bind.JAXBContext, then manually load (and reflexively create) a JAXBContext based on the class name specified in the file. So it doesn't matter - classpath or endorsed lib gives you the same behavior.

一种解决方法是将 -Djavax.xml.bind.JAXBContext=com.sun.xml.internal.bind.v2.ContextFactory 添加到命令行,这会导致 JAXBContext.newInstance()忽略类路径上的 /META-INF/services/javax.xml.bind.JAXBContext 文件并手动指定 JAXB 的内置版本.另一种解决方法是简单地不指定您自己的 JAXB 并使用内置于 JDK 中的版本,但从非官方 JAXB 指南看来,Sun 设计此系统是为了能够处理提供您自己的 JAXB 实现.有没有人能够成功提供一个版本的 JAXB 并且仍然能够成功捕获故障消息?(只要 Web 服务没有产生错误,我就一切正常.

One workaround is to add -Djavax.xml.bind.JAXBContext=com.sun.xml.internal.bind.v2.ContextFactory to the command line, which causes JAXBContext.newInstance() to ignore the /META-INF/services/javax.xml.bind.JAXBContext file on the classpath and manually specifies the built-in version of JAXB. The other workaround is to simply not specify your own JAXB and use the version built into the JDK, but it seems from the Unofficial JAXB Guide, that Sun designed this system to be able to handle supplying your own JAXB implementation. Has anyone been able to successfully supply a version of JAXB and still be able to successfully capture fault messages? (Everything runs fine for me as long as there are no faults generated by the Web Service).

推荐答案

我被这个问题困住了,但通过设置一个像这样的系统属性:

I was stuck on this problem but was able to use the "work around" listed in this forum Q&A by setting a system property like so:

System.setProperty("javax.xml.bind.JAXBContext", 
                   "com.sun.xml.internal.bind.v2.ContextFactory"); 

这篇关于在 Java 1.6 中为 JAX-WS 提供不同版本的 JAXB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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