ClassCastException: 无法转换为 com.sun.xml.internal.bind.v2.runtime.reflect.Accessor

ClassCastException: Cannot be cast to com.sun.xml.internal.bind.v2.runtime.reflect.Accessor

我有一个 SOAP 网络服务,我正试图在应用程序内部调用它。我正在使用 cxf-codegen-plugin (3.1.10) 从 WSDL 生成源代码。

使用生成的客户端,如果我在应用程序中调用网络服务,效果很好。但是,我还在导致问题的应用程序中针对同一个包使用了另一个 JAXB 实例。

例如,以下效果很好:

OutboundServicePortType service = new OutboundService().getOutboundServicePort();
service.sendMessage(message);

但是,在之前初始化新的 JAXB 实例会导致 getOutboundServicePort() 调用失败:

JAXBContext.newInstance(SendMessageRequest.class);

OutboundServicePortType service = new OutboundService().getOutboundServicePort();
service.sendMessage(message);

具有以下堆栈跟踪:

Caused by: java.lang.ClassCastException: outbound.model.standard.StandardOutboundMessage$JaxbAccessorF_messageUUId cannot be cast to com.sun.xml.internal.bind.v2.runtime.reflect.Accessor
    at com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.instanciate(OptimizedAccessorFactory.java:190)
    at com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.get(OptimizedAccessorFactory.java:179)
    at com.sun.xml.internal.bind.v2.runtime.reflect.Accessor$FieldReflection.optimize(Accessor.java:271)
    at com.sun.xml.internal.bind.v2.runtime.property.SingleElementLeafProperty.<init>(SingleElementLeafProperty.java:77)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:166)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:488)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:153)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:488)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:305)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
    at com.sun.xml.internal.bind.api.JAXBRIContext.newInstance(JAXBRIContext.java:152)
    at com.sun.xml.internal.bind.api.JAXBRIContext.newInstance(JAXBRIContext.java:96)
    at com.sun.xml.internal.ws.developer.JAXBContextFactory.createJAXBContext(JAXBContextFactory.java:98)
    at com.sun.xml.internal.ws.db.glassfish.JAXBRIContextFactory.newContext(JAXBRIContextFactory.java:79)
    ... 25 more

到目前为止我尝试过的事情:

JAXB classes from Webservice marshalling error

Problems creating JAXBContext to marshal object as XML

Netbeans with JAXB Random ClassCastException ..cannot be cast to com.sun.xml.bind.v2.runtime.reflect.Accessor

我正准备用剩下的那根小绳子上吊。我在这里错过了什么?

我不想回答我自己的问题,但我想确保清楚地记录了我最终采用的解决方案。

根本问题是 camel-jaxb 引入的 jaxb-impl jar 与 JDK 8 提供的版本冲突。

This answer 更清楚地描述了正在发生的事情:

I encountered the same error when I tried to upgrade JAXB to a newer version than what came with the JDK. Java encountered two or more instances of JAXB at runtime and could not decide which version to use.

在我的例子中,我简单地排除了 camel-jaxb 附带的 jaxb-impl,应用程序开始正常工作。

我 运行 在测试范围内遇到了同样的问题。对我来说,添加 jaxws-rt 运行time jar 很有帮助。请注意,我只是为我的测试范围添加了它。您不会在产品 运行 时间内执行此操作,因为 JEE 容器应该已经具有此或其他实现。

<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>2.2.3</version>
    <scope>test</scope>
</dependency>

我 运行 在尝试通过 Maven 运行 我的 JUnit 测试时遇到此错误,即使它们在 Eclipse 中通过了本地测试。我的解决方案是在 @BeforeClass 中放置:

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

如果您使用 spring 启动 2.2 以上。6.RELEASE 将此 属性 添加到您的 pom:

2.3.2

因为在下一个版本中它更改了 java.xml.bind 实现:

看看这个 pom IE:

https://repo1.maven.org/maven2/org/glassfish/jaxb/jaxb-runtime/2.3.5/jaxb-runtime-2.3.5.pom :

--add-opens org.glassfish.jaxb.runtime/com.sun.xml.bind.v2=java.xml.bind --add-opens org.glassfish.jaxb.runtime/com.sun.xml.bind.v2.schemagen=java.xml.bind --add-opens org.glassfish.jaxb.runtime/com.sun.xml.bind.v2.schemagen.xmlidref= java.xml.bind --add-opens java.base/java.lang=org.glassfish.jaxb.runtime --add-opens java.base/java.lang.reflect=org.glassfish.jaxb.runtime --add-opens org.glassfish.jaxb.runtime/com.sun.xml.bind.v2.runtime.reflect.opt=java.xml.bind