[
https://issues.apache.org/jira/browse/CXF-6791?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18126926#comment-18126926
]
Colm O hEigeartaigh commented on CXF-6791:
------------------------------------------
This isn’t a CXF bug. The behaviour comes from the JAXB data binding layer. I
compiled the classes wsdl2java generated from your MWE and unmarshalled the
payload with plain JAXB (RI 2.3.x), without CXF or Spring on the classpath. It
fails with the same error:
{noformat}
javax.xml.bind.UnmarshalException: Unable to create an instance of
com.basetypes._abstract.HeaderType
* with linked exception: [java.lang.InstantiationException]
{noformat}
_Why it happens_
In concrete.xsd, concrete:message narrows the type of “header” from
abstract:headerType to concrete:headerType by {_}restriction{_}. The JAXB 2.x
spec maps derivation by restriction to a plain Java subclass that adds no
properties, so the generated class is empty:
{code:java}
public class Message extends com.basetypes._abstract.Message \{ }
{code}
The only “header” field is the one inherited from the abstract base, and it’s
typed as the abstract class:
{code:java}
@XmlElement(required = true)
protected com.basetypes._abstract.HeaderType header;
{code}
The narrowed type from the schema is lost in the Java model. When JAXB reads
<header> without an xsi:type attribute, it can only use the declared field
type, which is abstract, so it can’t create an instance. SoapUI and Oxygen
accept the WSDL because they validate against the schema, which is valid. They
never have to bind it to Java classes.
_Workarounds_
h2. Have clients send an explicit xsi:type on the element. I verified that this
works with your classes. JAXB then creates com.types.concrete.HeaderType:
{code:xml}
<header xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://concrete.types.com" xsi:type="c:headerType">
<comment>...</comment>
</header>
{code}
h2. Customise the generated code with a JAXB bindings file or an XJC plugin
(e.g. annox), adding @XmlElement(type = com.types.concrete.HeaderType.class) to
the “header” field. This only works if the abstract base is used by just one
concrete subtype.
h2. Remove abstract="true" from the base type, which I realise doesn’t suit a
contract-first project.
Unrelated to the exception: the inline xsd:schema in service.wsdl has no
targetNamespace, so “payload” ends up in no namespace. That’s also why
wsdl2java generated both generated.Payload and com.namespace.service.Payload.
Adding a targetNamespace to the inline schema would make this cleaner.
> Nested Abstract classes are not converted correctly from a WSDL
> ---------------------------------------------------------------
>
> Key: CXF-6791
> URL: https://issues.apache.org/jira/browse/CXF-6791
> Project: CXF
> Issue Type: Bug
> Components: Soap Binding
> Affects Versions: 3.1.5
> Environment: MacOS 10.11.3, Apache CXF 3.1.5, SoapUI 5.2.1, Oxygen
> 17.1
> Reporter: Julian Peters
> Priority: Major
> Attachments: MWE.zip
>
>
> The attached example features a message and wrapped header. Both are defined
> in "abstract.xsd" (with appropriate namespace). In "concrete.xsd" both two
> new types are defined, both deriving from their respective partners in
> "abstract". The concrete:message is now wrapping a concrete:header. In the
> "service.wsdl" i define a service, using the concrete:message in a wrapper
> element.
> Now I use "wsdl2java" for convertion, add a dash of spring-boot to get the
> whole thing running. The end-result is that for a message like
> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
> <soapenv:Header/>
> <soapenv:Body>
> <payload>
> <content>
> <header>
> <comment>fdsafdsafdsafdsa</comment>
> </header>
> </content>
> </payload>
> </soapenv:Body>
> </soapenv:Envelope>
> i run into an unmarshalling-exception (also attached). The Server apparently
> tries to instantiate the abstract class (from "abstract.xsd"), not the one
> from concrete.xsd. I double checked with SoapUI and Oxygen, both seem to have
> no problem with the wsdl.
> Of course, removing the "abstract" from the abstract-Header solves the
> problem, but that is not really a solution for a contract-first driven
> project.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)