Поставка другой версии JAXB для JAX-WS в Java 1.6

У меня есть сторонний jar, который поставляется с jaxb-impl.jar и включает его в свой манифест classpath. Проблема в том, что, похоже, что предоставление вашей собственной версии JAXB (независимо от того, какая версия это может быть), похоже, нарушает SoapFaultBuilder в JAX-WS.

СогласноНеофициальное руководство JAXBПохоже, что Sun сознательно изменила имя пакета, когда свернула JAXB в JDK, чтобы избежать конфликтов с автономной версией. Однако SoapFaultBuilder (я полагаю, часть JAX-WS), который поставляется с JDK, явно зависит от нового внутреннего имени пакета. Это приводит к сбою при создании сообщения об ошибке, если вы добавили автономный JAXB-файл (даже если это та же версияномер JAXB).

Вот мой маленький тестовый пример: я делаю тривиальный веб-сервис:

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

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);
    }

}

И класс для публикации веб-службы:

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, а затем запускаю этот клиент для него:

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"));

    }

}

Это правильно выплевывает исключение, которое было выброшено веб-службой. Однако, когда я добавляю любую версию jaxb-impl.jar, будь то в classpath или в одобренной lib, я получаю следующую трассировку стека:

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 ( обратите внимание на отсутствующий «внутренний» подпакет в иерархии пакетов).

Также в соответствии сНеофициальное руководство JAXB, они говорят, что вам нужно использовать одобренную библиотеку для корректного переопределения версии JAXB. Как оказалось, SOAPFaultBuilder использует JAXBContext.newInstance () для поиска пути к классу для файла с именем/META-INF/services/javax.xml.bind.JAXBContextзатем вручную загрузите (и рефлексивно создайте) JAXBContext на основе имени класса, указанного в файле. Так что это не имеет значения - classpath или одобренная lib дают вам такое же поведение.

Один из способов это добавить-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 и все еще быть в состоянии успешно захватить сообщения об ошибках? (Все работает нормально для меня, пока нет ошибок, генерируемых веб-службой).

Ответы на вопрос(3)

Ваш ответ на вопрос