I'm using maven-jaxb2-plugin
to generate Java classes according to a WSDL.
Generated Java classes are under package com.myapp.generated
and for example, there is Jaxb2 generated class com.myapp.generated.SomeRequest
:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"someRequestType"
})
@XmlRootElement(name = "someRequest")
public class SomeRequest
{
// generated code
}
which I'm extending then I have it in a different package:
package com.myapp.extended.someRequest;
class SomeRequestExtended extends com.myapp.generated.SomeRequest {
// additional code
}
Then using Spring Boot (v2.2.9) / spring-oxm (v5.2.8) I specify Bean for Jaxb2Marshaller to scan that package:
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("com.myapp.extended.*");
return marshaller;
}
During runtime, unfortunately, there is a problem it doesn't find it:
class package com.myapp.extended.someRequest.SomeRequestExtended; nor any of its super class is known to this context.
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:567) ~[na:1.8.0_201]
...
Does anyone know what is the reason, and how to make it scan specified packages to find the SomeRequestExtended class?
The reason is that the required XmlRootElement on JAXB classes is not inherited in subclasses because interface XmlRootElement doesn't have @Inherited annotation:
package javax.xml.bind.annotation;
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE})
public @interface XmlRootElement {
java.lang.String namespace() default "##default";
java.lang.String name() default "##default";
}
To solve the issue, you can manually add/copy it from parent class to subclass:
package com.myapp.extended.someRequest;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"someRequestType"
})
@XmlRootElement(name = "someRequest")
class SomeRequestExtended extends com.myapp.generated.SomeRequest {
// additional code
}
Also make sure, that the @XmlAccessorType(XmlAccessType.FIELD)
and @XmlType
are still valid in subclass - in my example, the field should be visible, or you can change the definition to getter method using XmlAccessType.PUBLIC_MEMBER
HINT: Additionally, if there is, and usually is, a file package-info.java
generated by JAXB, then it should also be copied to a new package, like in my example to: package com.myapp.extended.someRequest;
If not there might be problems when resolving classes by marshaller!