Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Duplicate
-
4.0.0
-
None
-
None
-
Unknown
Description
Dear CXF developers,
I am using version 4.0.0 of CXF cxf-spring-boot-starter-jaxws.
My CXF jaxws services are wrapped in Spring Boot 3.0. I also use akarta.xml.bind-api 4.0.0 and org.eclipse.persistence.moxy 4.0.1.
I generate Java models with cxf-codegen-plugin with the following configuration:
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<dependencies>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf.xjc-utils</groupId>
<artifactId>cxf-xjc-runtime</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf.xjcplugins</groupId>
<artifactId>cxf-xjc-ts</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.4.0-b180830.0359</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
<defaultOptions>
<noAddressBinding>true</noAddressBinding>
<faultSerialVersionUID>3105839350746982386</faultSerialVersionUID>
<extraargs>
<extraarg>-xjc-Xannotate</extraarg>
</extraargs>
</defaultOptions>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/wsdl/myservice.wsdl</wsdl>
<wsdlLocation>classpath:wsdl/myservice.wsdl</wsdlLocation>
<serviceName>myservice</serviceName>
<bindingFiles>
<bindingFile>${basedir}/src/main/resources/wsdl/bindings.xjb</bindingFile>
</bindingFiles>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
Binding file has the following configuration:
<?xml version="1.0"?> <jaxb:bindings version="3.0" xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb" jaxb:extensionBindingPrefixes="annox xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:annox="http://annox.dev.java.net" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"> <jaxb:bindings> <jaxb:bindings> <jaxb:globalBindings typesafeEnumMaxMembers="3000" generateElementProperty="false" mapSimpleTypeDef="false" fixedAttributeAsConstantProperty="true" choiceContentProperty="true" typesafeEnumBase="xs:boolean"> </jaxb:globalBindings> </jaxb:bindings> </jaxb:bindings> <jaxb:bindings schemaLocation="*"> <jaxb:bindings node="//xs:complexType" multiple="true" required="false"> <annox:annotateClass>@lombok.experimental.SuperBuilder</annox:annotateClass> <annox:annotateClass>@jakarta.xml.bind.annotation.XmlRootElement</annox:annotateClass> <annox:annotateClass>@lombok.NoArgsConstructor</annox:annotateClass> </jaxb:bindings> <jaxb:bindings node="//xs:element" multiple="true" required="false"> <annox:annotate target="field"> @org.eclipse.persistence.oxm.annotations.XmlNullPolicy(nullRepresentationForXml= XmlMarshalNullRepresentation.ABSENT_NODE, xsiNilRepresentsNull=false) </annox:annotate> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings>
Model class generation works fine, nullable properties are marked with annotation:
@XmlNullPolicy(nullRepresentationForXml = XmlMarshalNullRepresentation.ABSENT_NODE, xsiNilRepresentsNull = false)
To start Moxy Runtime use the following settings in main method of Application:
System.setProperty("jakarta.xml.bind.JAXBContextFactory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
I use this initialisation because I still need to use Spring Web Service Client from Spring WS in parallel.
But on application startup I get errors:
Caused by: java.lang.reflect.InvocationTargetException: null
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.apache.cxf.common.jaxb.JAXBUtils$3.run(JAXBUtils.java:1189) ~[cxf-core-4.0.0.jar:4.0.0]
at org.apache.cxf.common.jaxb.JAXBUtils$3.run(JAXBUtils.java:1183) ~[cxf-core-4.0.0.jar:4.0.0]
at java.base/java.security.AccessController.doPrivileged(AccessController.java:569) ~[na:na]
at org.apache.cxf.common.jaxb.JAXBUtils.createContext(JAXBUtils.java:1183) ~[cxf-core-4.0.0.jar:4.0.0]
... 64 common frames omitted
Caused by: jakarta.xml.bind.JAXBException: Property "eclipselink.default-target-namespace" is not supported.
at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:126) ~[jaxb-runtime-4.0.1.jar:4.0.1 - a95cb76]
I have examined your code and found that you are using hard coded call to "Class<?> factoryClass = ClassLoaderUtils.loadClass("org.glassfish.jaxb.runtime.v2.ContextFactory" in cxf-core org.apache.cxf.common.jaxb.JAXBUtils
I have experimented a bit and if you can make a few changes in two classes everything will work. The classes need to be changed:
1. org.apache.cxf.common.jaxb.JAXBContextCache Method getCachedContextAndSchemas in lines 197 to 194
old code
if (defaultNs != null) { if (HAS_MOXY){ map.put("eclipselink.default-target-namespace", defaultNs); } map.put("org.glassfish.jaxb.defaultNamespaceRemap", defaultNs); }
new code
if (defaultNs != null){ if (HAS_MOXY){ map.put("eclipselink.default-target-namespace", defaultNs); } else{ map.put("org.glassfish.jaxb.defaultNamespaceRemap", defaultNs); } }
2. org.apache.cxf.common.jaxb.JAXBUtils
2.1 Method getPostfix in lines 1105 to 1117
old code:
private static String getPostfix(Class<?> cls) { String className = cls.getName(); //TODO: review and remove "com.sun" package name check if (className.contains("org.glassfish.jaxb") || className.contains("com.sun.xml.bind") || className.startsWith("com.ibm.xml")){ return ""; } else if (className.contains("com.sun.xml.internal") || className.contains("eclipse")){ //eclipse moxy accepts sun package CharacterEscapeHandler return ".internal"; } return null; }
new code:
private static String getPostfix(Class<?> cls) { String className = cls.getName(); //TODO: review and remove "com.sun" package name check if (className.contains("org.glassfish.jaxb") || className.contains("com.sun.xml.bind") || className.startsWith("com.ibm.xml") || className.contains("eclipse")) { //eclipse moxy 4.0 accepts glassfish package CharacterEscapeHandler see const SUN_CHARACTER_ESCAPE_HANDLER // Const in MOXY 4.0.1 // SUN_CHARACTER_ESCAPE_HANDLER= "org.glassfish.jaxb.characterEscapeHandler"; // SUN_JSE_CHARACTER_ESCAPE_HANDLER = "com.sun.xml.internal.bind.characterEscapeHandler"; // SUN_CHARACTER_ESCAPE_HANDLER_MARSHALLER = "org.glassfish.jaxb.marshaller.CharacterEscapeHandler"; // SUN_JSE_CHARACTER_ESCAPE_HANDLER_MARSHALLER = "com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler" // part of setProperty(String key, Object value) from Class org.eclipse.persistence.jaxb. JAXBMarshaller // else if (SUN_CHARACTER_ESCAPE_HANDLER.equals(key) || SUN_JSE_CHARACTER_ESCAPE_HANDLER.equals(key) || // SUN_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key) || // SUN_JSE_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key)) { // if (value == null) { // xmlMarshaller.setCharacterEscapeHandler(null); // } else { // xmlMarshaller.setCharacterEscapeHandler(new CharacterEscapeHandlerWrapper(value)); // } return ""; } else if (className.contains("com.sun.xml.internal")) { return ".internal"; } return null; }
2.2 Method createContext in lines 1179 to 1202
old code:
public static JAXBContext createContext(final Set<Class<?>> classes, final Map<String, Object> map) throws JAXBException { JAXBContext ctx = null; try { ctx = AccessController.doPrivileged(new PrivilegedExceptionAction<JAXBContext>() { public JAXBContext run() throws Exception { //This is a workaround for CXF-8675 Class<?> factoryClass = ClassLoaderUtils.loadClass("org.glassfish.jaxb.runtime.v2.ContextFactory", JAXBContextCache.class); Method m = factoryClass.getMethod("createContext", Class[].class, Map.class); Object context = m.invoke(null, classes.toArray(new Class<?>[0]), map); return (JAXBContext) context; } }); } catch (PrivilegedActionException e2) { if (e2.getException() instanceof JAXBException){ JAXBException ex = (JAXBException) e2.getException(); throw ex; } else { throw new RuntimeException(e2.getException()); } } return ctx; }
new code:
public static JAXBContext createContext(final Set<Class<?>> classes, final Map<String, Object> map) throws JAXBException { JAXBContext ctx = null; try { ctx = AccessController.doPrivileged(new PrivilegedExceptionAction<JAXBContext>() { public JAXBContext run() throws Exception { String factoryClassName = classNameFromSystemProperties("org.glassfish.jaxb.runtime.v2.ContextFactory"); //This is a workaround for CXF-8675 Class<?> factoryClass = ClassLoaderUtils.loadClass(factoryClassName, JAXBContextCache.class); Method m = factoryClass.getMethod("createContext", Class[].class, Map.class); Object context = m.invoke(null, classes.toArray(new Class<?>[0]), map); return (JAXBContext) context; } }); } catch (PrivilegedActionException e2) { if (e2.getException() instanceof JAXBException) { JAXBException ex = (JAXBException) e2.getException(); throw ex; } else{ throw new RuntimeException(e2.getException()); } } return ctx; } private static String classNameFromSystemProperties(String defaultValue) throws JAXBException { String factoryClassName = getSystemProperty(JAXBContext.JAXB_CONTEXT_FACTORY, defaultValue); if (factoryClassName != null){ return factoryClassName; } return null; } private static String getSystemProperty(String property, String defaultValue) { String value = System.getProperty(property); if (value != null){ return value; } else{ return defaultValue; } }
With this Changes work for me fine, without Errors. Can you please check if you can incorporate these changes into CXF-CORE.
If you have other possibilities to configure org.eclipse.persistence.moxy. Can you please describe.
Thanks in advance
Anderas Rusjaev
Attachments
Issue Links
- duplicates
-
CXF-5131 Update CXF's JAXB handling to detect/support Eclipselink Moxy
- Open