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

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

问题描述

我有一个带有jaxb-impl.jar的第三方jar,并将其包含在其manifest类路径中。问题是,似乎提供自己版本的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时,无论是在类路径还是在支持的lib中,我都会得到这个堆栈跟踪:

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

因为com.sun会发生异常.xml.bind.v2.runtime.JAXBContextImpl从我的jaxb-impl扩展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指南,他们说你需要使用支持的lib才能正确覆盖JAXB的版本。事实证明,SOAPFaultBuilder使用JAXBContext.newInstance()在类路径中搜索名为 /META-INF/services/javax.xml.bind.JAXBContext 的文件,然后根据文件中指定的类名手动加载(并反复创建)JAXBContext。因此无关紧要 - classpath或endorsed lib会给你相同的行为。

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).

推荐答案

我被困在这问题,但能够通过设置如下的系统属性来使用此论坛 Q& A中列出的解决方法:

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天全站免登陆