Is it possible to migrate existing JAX-RPC web services to JAX-WS without any WSDL or domain model...
I am preparing to migrate SOAP web services from JAX-RPC to JAX-WS.
It has to be as smooth as possible:
- WSDL must not be modified.
- New JAX-WS web services should use the same implementation as their old JAX-RPC counterparts (maximum reuse of code, no copy/paste).
- New JAX-WS web services should be able to operate in parallel with their old JAX-RPC counterparts.
How it is working today:
- Existing WSDL are generated from the JAX-RPC @WebService classes,
- XML schemas are hand-written, and compiled by XMLBeans.
- At runtime, XMLBeans objects are converted into model objects by hand-written *Converter classes.
How we want to make it work after the migration:
- New JAX-WS web services will be contract-first: Service Endpoint Interfaces (SEI) will be generated from existing WSDL.
- XML types should be binded directly to existing model objects.
- Binding configuration should be external (not use annotations).
I am using wsimport goal from jaxws-maven-plugin (http://www.mojohaus.org/jaxws-maven-plugin/) to generate Java code from WSDL.
The services will be deployed as a web app (not EJB) in WebLogic Server 12.2.1.3.
I tried without success to use:
- JAX-WS and JAXB binding customizations
- WLS doc says that "If customizations are required, Oracle recommends [creating external binding] to maintain flexibility by keeping the customizations separate from the WSDL or XML Schema document.")
- it seems that I have to use annotations, and I couldn't find a way to use XmlAdapters without modifying model objects (to add XmlJavaTypeAdapter).
- EclipseLink MOXy external binding (EclipseLink MOXy is the default data binding and JAXB provider in WLS12.2.1.3).
- The doc states that "EclipseLink MOXy provides (...) the ability to use an external metadata file to configure the equivalent of JAXB annotations without modifying the Java source it refers to"
- but says also that "EclipseLink MOXy extensions can be leveraged (...) only in the Java to WSDL scenario".
- as a matter of fact I couldn't manage to have maven tooling nor the app to use this binding.
Put in code, it looks like:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>myapp</artifactId>
<packaging>war</packaging>
<groupId>sandbox.jaxws_migration</groupId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version></plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version>
<dependencies>
<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>webservices-tools</artifactId>
<version>2.3.1</version>
</dependency>
<!-- see https://java.net/jira/browse/WSIT-1672 -->
<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>webservices-rt</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<xadditionalHeaders>true</xadditionalHeaders>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/wsdl/hello_world.wsdl
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions name="HelloWorld"
targetNamespace="http://service.myapp/helloworld/"
xmlns:tns ="http://service.myapp/helloworld/"
xmlns:wsdl ="http://schemas.xmlsoap.org/wsdl/"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
xmlns:soap ="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:p ="http://types.myapp/person/"
>
<wsdl:types>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://service.myapp/helloworld/">
<xs:import namespace="http://types.myapp/person/" schemaLocation="../xsd/person.xsd"/>
<xs:element name="sayHello">
<xs:complexType>
<xs:sequence>
<xs:element name="who" type="p:person"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="sayHelloResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="greetings" type="xs:string">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="sayHello"> <wsdl:part name="p" element="tns:sayHello"/> </wsdl:message>
<wsdl:message name="sayHelloResponse"><wsdl:part name="p" element="tns:sayHelloResponse"/></wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="sayHello">
<wsdl:input message="tns:sayHello"/>
<wsdl:output message="tns:sayHelloResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorld" type="tns:HelloWorld">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHello"><soap:operation soapAction="sayHello"/><wsdl:input><soap:body use="literal"/></wsdl:input><wsdl:output><soap:body/></wsdl:output></wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorld">
<wsdl:port name="HelloWorld" binding="tns:HelloWorld">
<soap:address location="http://my.fake.url"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
src/xsd/person.xsd
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="http://types.myapp/person/"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="person">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="surname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
src/main/java/myapp/service/HelloWorld.java
package myapp.service;
import javax.jws.WebService;
import myapp.legacy.model.LegacyPerson;
@WebService(
endpointInterface = "myapp.service.helloworld.HelloWorld",
wsdlLocation = "wsdl/hello_world.wsdl"
)
public class HelloWorld implements myapp.service.helloworld.HelloWorld {
@Override
public String sayHello(LegacyPerson who) {
return "Hello " + who.getLegacyName() + " " + who.getLegacySurname();
}
}
src/main/java/myapp/legacy/model/LegacyPerson.java
package myapp.legacy.model;
public class LegacyPerson {
private String legacyName;
private String legacySurname;
public String getLegacyName() {
return legacyName;
}
public void setLegacyName(String legacyName) {
this.legacyName = legacyName;
}
public String getLegacySurname() {
return legacySurname;
}
public void setLegacySurname(String legacySurname) {
this.legacySurname = legacySurname;
}
}
src/jaxws/bindings.xml
<jaxb:bindings version="2.0"
xmlns:jaxb ="http://java.sun.com/xml/ns/jaxb"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
schemaLocation="../xsd/person.xsd"
>
<jaxb:bindings node="/xs:schema/xs:complexType[@name='person']">
<jaxb:class ref="myapp.legacy.model.LegacyPerson"/><!-- Make the SEI use my legacy model, but how should I describe how to bind the data? -->
<!-- This will make wsimport say : "compiler was unable to honor this property customization. It is attached to a wrong place, or its inconsistent with other bindings." -->
<!-- <jaxb:bindings node="//xs:element[@name='name']">
<jaxb:property name="legacyName" />
</jaxb:bindings>-->
</jaxb:bindings>
</jaxb:bindings>
References
- https://javaee.github.io/metro-jax-ws/doc/user-guide/
- https://download.oracle.com/otn-pub/jcp/jaxb-2_3-mrel3-eval-spec/JAXB-2.3-spec.pdf
- https://download.oracle.com/otn-pub/jcp/websvcs_metadata-2_1-mrel2-eval-spec/JSR181-2.1-MR.pdf
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-jws.htm#WSGET156
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-datatypes.htm#GUID-2C55847C-0990-4763-8041-EECE802A7EB1
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-datatypes.htm#WSGET212
- http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
JAX-WS & JAX-RS with EclipseLink MOXy and external mapping documents
java web-services jaxb eclipselink jax-ws-customization
add a comment |
I am preparing to migrate SOAP web services from JAX-RPC to JAX-WS.
It has to be as smooth as possible:
- WSDL must not be modified.
- New JAX-WS web services should use the same implementation as their old JAX-RPC counterparts (maximum reuse of code, no copy/paste).
- New JAX-WS web services should be able to operate in parallel with their old JAX-RPC counterparts.
How it is working today:
- Existing WSDL are generated from the JAX-RPC @WebService classes,
- XML schemas are hand-written, and compiled by XMLBeans.
- At runtime, XMLBeans objects are converted into model objects by hand-written *Converter classes.
How we want to make it work after the migration:
- New JAX-WS web services will be contract-first: Service Endpoint Interfaces (SEI) will be generated from existing WSDL.
- XML types should be binded directly to existing model objects.
- Binding configuration should be external (not use annotations).
I am using wsimport goal from jaxws-maven-plugin (http://www.mojohaus.org/jaxws-maven-plugin/) to generate Java code from WSDL.
The services will be deployed as a web app (not EJB) in WebLogic Server 12.2.1.3.
I tried without success to use:
- JAX-WS and JAXB binding customizations
- WLS doc says that "If customizations are required, Oracle recommends [creating external binding] to maintain flexibility by keeping the customizations separate from the WSDL or XML Schema document.")
- it seems that I have to use annotations, and I couldn't find a way to use XmlAdapters without modifying model objects (to add XmlJavaTypeAdapter).
- EclipseLink MOXy external binding (EclipseLink MOXy is the default data binding and JAXB provider in WLS12.2.1.3).
- The doc states that "EclipseLink MOXy provides (...) the ability to use an external metadata file to configure the equivalent of JAXB annotations without modifying the Java source it refers to"
- but says also that "EclipseLink MOXy extensions can be leveraged (...) only in the Java to WSDL scenario".
- as a matter of fact I couldn't manage to have maven tooling nor the app to use this binding.
Put in code, it looks like:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>myapp</artifactId>
<packaging>war</packaging>
<groupId>sandbox.jaxws_migration</groupId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version></plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version>
<dependencies>
<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>webservices-tools</artifactId>
<version>2.3.1</version>
</dependency>
<!-- see https://java.net/jira/browse/WSIT-1672 -->
<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>webservices-rt</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<xadditionalHeaders>true</xadditionalHeaders>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/wsdl/hello_world.wsdl
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions name="HelloWorld"
targetNamespace="http://service.myapp/helloworld/"
xmlns:tns ="http://service.myapp/helloworld/"
xmlns:wsdl ="http://schemas.xmlsoap.org/wsdl/"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
xmlns:soap ="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:p ="http://types.myapp/person/"
>
<wsdl:types>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://service.myapp/helloworld/">
<xs:import namespace="http://types.myapp/person/" schemaLocation="../xsd/person.xsd"/>
<xs:element name="sayHello">
<xs:complexType>
<xs:sequence>
<xs:element name="who" type="p:person"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="sayHelloResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="greetings" type="xs:string">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="sayHello"> <wsdl:part name="p" element="tns:sayHello"/> </wsdl:message>
<wsdl:message name="sayHelloResponse"><wsdl:part name="p" element="tns:sayHelloResponse"/></wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="sayHello">
<wsdl:input message="tns:sayHello"/>
<wsdl:output message="tns:sayHelloResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorld" type="tns:HelloWorld">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHello"><soap:operation soapAction="sayHello"/><wsdl:input><soap:body use="literal"/></wsdl:input><wsdl:output><soap:body/></wsdl:output></wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorld">
<wsdl:port name="HelloWorld" binding="tns:HelloWorld">
<soap:address location="http://my.fake.url"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
src/xsd/person.xsd
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="http://types.myapp/person/"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="person">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="surname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
src/main/java/myapp/service/HelloWorld.java
package myapp.service;
import javax.jws.WebService;
import myapp.legacy.model.LegacyPerson;
@WebService(
endpointInterface = "myapp.service.helloworld.HelloWorld",
wsdlLocation = "wsdl/hello_world.wsdl"
)
public class HelloWorld implements myapp.service.helloworld.HelloWorld {
@Override
public String sayHello(LegacyPerson who) {
return "Hello " + who.getLegacyName() + " " + who.getLegacySurname();
}
}
src/main/java/myapp/legacy/model/LegacyPerson.java
package myapp.legacy.model;
public class LegacyPerson {
private String legacyName;
private String legacySurname;
public String getLegacyName() {
return legacyName;
}
public void setLegacyName(String legacyName) {
this.legacyName = legacyName;
}
public String getLegacySurname() {
return legacySurname;
}
public void setLegacySurname(String legacySurname) {
this.legacySurname = legacySurname;
}
}
src/jaxws/bindings.xml
<jaxb:bindings version="2.0"
xmlns:jaxb ="http://java.sun.com/xml/ns/jaxb"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
schemaLocation="../xsd/person.xsd"
>
<jaxb:bindings node="/xs:schema/xs:complexType[@name='person']">
<jaxb:class ref="myapp.legacy.model.LegacyPerson"/><!-- Make the SEI use my legacy model, but how should I describe how to bind the data? -->
<!-- This will make wsimport say : "compiler was unable to honor this property customization. It is attached to a wrong place, or its inconsistent with other bindings." -->
<!-- <jaxb:bindings node="//xs:element[@name='name']">
<jaxb:property name="legacyName" />
</jaxb:bindings>-->
</jaxb:bindings>
</jaxb:bindings>
References
- https://javaee.github.io/metro-jax-ws/doc/user-guide/
- https://download.oracle.com/otn-pub/jcp/jaxb-2_3-mrel3-eval-spec/JAXB-2.3-spec.pdf
- https://download.oracle.com/otn-pub/jcp/websvcs_metadata-2_1-mrel2-eval-spec/JSR181-2.1-MR.pdf
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-jws.htm#WSGET156
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-datatypes.htm#GUID-2C55847C-0990-4763-8041-EECE802A7EB1
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-datatypes.htm#WSGET212
- http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
JAX-WS & JAX-RS with EclipseLink MOXy and external mapping documents
java web-services jaxb eclipselink jax-ws-customization
add a comment |
I am preparing to migrate SOAP web services from JAX-RPC to JAX-WS.
It has to be as smooth as possible:
- WSDL must not be modified.
- New JAX-WS web services should use the same implementation as their old JAX-RPC counterparts (maximum reuse of code, no copy/paste).
- New JAX-WS web services should be able to operate in parallel with their old JAX-RPC counterparts.
How it is working today:
- Existing WSDL are generated from the JAX-RPC @WebService classes,
- XML schemas are hand-written, and compiled by XMLBeans.
- At runtime, XMLBeans objects are converted into model objects by hand-written *Converter classes.
How we want to make it work after the migration:
- New JAX-WS web services will be contract-first: Service Endpoint Interfaces (SEI) will be generated from existing WSDL.
- XML types should be binded directly to existing model objects.
- Binding configuration should be external (not use annotations).
I am using wsimport goal from jaxws-maven-plugin (http://www.mojohaus.org/jaxws-maven-plugin/) to generate Java code from WSDL.
The services will be deployed as a web app (not EJB) in WebLogic Server 12.2.1.3.
I tried without success to use:
- JAX-WS and JAXB binding customizations
- WLS doc says that "If customizations are required, Oracle recommends [creating external binding] to maintain flexibility by keeping the customizations separate from the WSDL or XML Schema document.")
- it seems that I have to use annotations, and I couldn't find a way to use XmlAdapters without modifying model objects (to add XmlJavaTypeAdapter).
- EclipseLink MOXy external binding (EclipseLink MOXy is the default data binding and JAXB provider in WLS12.2.1.3).
- The doc states that "EclipseLink MOXy provides (...) the ability to use an external metadata file to configure the equivalent of JAXB annotations without modifying the Java source it refers to"
- but says also that "EclipseLink MOXy extensions can be leveraged (...) only in the Java to WSDL scenario".
- as a matter of fact I couldn't manage to have maven tooling nor the app to use this binding.
Put in code, it looks like:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>myapp</artifactId>
<packaging>war</packaging>
<groupId>sandbox.jaxws_migration</groupId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version></plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version>
<dependencies>
<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>webservices-tools</artifactId>
<version>2.3.1</version>
</dependency>
<!-- see https://java.net/jira/browse/WSIT-1672 -->
<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>webservices-rt</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<xadditionalHeaders>true</xadditionalHeaders>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/wsdl/hello_world.wsdl
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions name="HelloWorld"
targetNamespace="http://service.myapp/helloworld/"
xmlns:tns ="http://service.myapp/helloworld/"
xmlns:wsdl ="http://schemas.xmlsoap.org/wsdl/"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
xmlns:soap ="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:p ="http://types.myapp/person/"
>
<wsdl:types>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://service.myapp/helloworld/">
<xs:import namespace="http://types.myapp/person/" schemaLocation="../xsd/person.xsd"/>
<xs:element name="sayHello">
<xs:complexType>
<xs:sequence>
<xs:element name="who" type="p:person"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="sayHelloResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="greetings" type="xs:string">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="sayHello"> <wsdl:part name="p" element="tns:sayHello"/> </wsdl:message>
<wsdl:message name="sayHelloResponse"><wsdl:part name="p" element="tns:sayHelloResponse"/></wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="sayHello">
<wsdl:input message="tns:sayHello"/>
<wsdl:output message="tns:sayHelloResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorld" type="tns:HelloWorld">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHello"><soap:operation soapAction="sayHello"/><wsdl:input><soap:body use="literal"/></wsdl:input><wsdl:output><soap:body/></wsdl:output></wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorld">
<wsdl:port name="HelloWorld" binding="tns:HelloWorld">
<soap:address location="http://my.fake.url"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
src/xsd/person.xsd
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="http://types.myapp/person/"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="person">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="surname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
src/main/java/myapp/service/HelloWorld.java
package myapp.service;
import javax.jws.WebService;
import myapp.legacy.model.LegacyPerson;
@WebService(
endpointInterface = "myapp.service.helloworld.HelloWorld",
wsdlLocation = "wsdl/hello_world.wsdl"
)
public class HelloWorld implements myapp.service.helloworld.HelloWorld {
@Override
public String sayHello(LegacyPerson who) {
return "Hello " + who.getLegacyName() + " " + who.getLegacySurname();
}
}
src/main/java/myapp/legacy/model/LegacyPerson.java
package myapp.legacy.model;
public class LegacyPerson {
private String legacyName;
private String legacySurname;
public String getLegacyName() {
return legacyName;
}
public void setLegacyName(String legacyName) {
this.legacyName = legacyName;
}
public String getLegacySurname() {
return legacySurname;
}
public void setLegacySurname(String legacySurname) {
this.legacySurname = legacySurname;
}
}
src/jaxws/bindings.xml
<jaxb:bindings version="2.0"
xmlns:jaxb ="http://java.sun.com/xml/ns/jaxb"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
schemaLocation="../xsd/person.xsd"
>
<jaxb:bindings node="/xs:schema/xs:complexType[@name='person']">
<jaxb:class ref="myapp.legacy.model.LegacyPerson"/><!-- Make the SEI use my legacy model, but how should I describe how to bind the data? -->
<!-- This will make wsimport say : "compiler was unable to honor this property customization. It is attached to a wrong place, or its inconsistent with other bindings." -->
<!-- <jaxb:bindings node="//xs:element[@name='name']">
<jaxb:property name="legacyName" />
</jaxb:bindings>-->
</jaxb:bindings>
</jaxb:bindings>
References
- https://javaee.github.io/metro-jax-ws/doc/user-guide/
- https://download.oracle.com/otn-pub/jcp/jaxb-2_3-mrel3-eval-spec/JAXB-2.3-spec.pdf
- https://download.oracle.com/otn-pub/jcp/websvcs_metadata-2_1-mrel2-eval-spec/JSR181-2.1-MR.pdf
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-jws.htm#WSGET156
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-datatypes.htm#GUID-2C55847C-0990-4763-8041-EECE802A7EB1
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-datatypes.htm#WSGET212
- http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
JAX-WS & JAX-RS with EclipseLink MOXy and external mapping documents
java web-services jaxb eclipselink jax-ws-customization
I am preparing to migrate SOAP web services from JAX-RPC to JAX-WS.
It has to be as smooth as possible:
- WSDL must not be modified.
- New JAX-WS web services should use the same implementation as their old JAX-RPC counterparts (maximum reuse of code, no copy/paste).
- New JAX-WS web services should be able to operate in parallel with their old JAX-RPC counterparts.
How it is working today:
- Existing WSDL are generated from the JAX-RPC @WebService classes,
- XML schemas are hand-written, and compiled by XMLBeans.
- At runtime, XMLBeans objects are converted into model objects by hand-written *Converter classes.
How we want to make it work after the migration:
- New JAX-WS web services will be contract-first: Service Endpoint Interfaces (SEI) will be generated from existing WSDL.
- XML types should be binded directly to existing model objects.
- Binding configuration should be external (not use annotations).
I am using wsimport goal from jaxws-maven-plugin (http://www.mojohaus.org/jaxws-maven-plugin/) to generate Java code from WSDL.
The services will be deployed as a web app (not EJB) in WebLogic Server 12.2.1.3.
I tried without success to use:
- JAX-WS and JAXB binding customizations
- WLS doc says that "If customizations are required, Oracle recommends [creating external binding] to maintain flexibility by keeping the customizations separate from the WSDL or XML Schema document.")
- it seems that I have to use annotations, and I couldn't find a way to use XmlAdapters without modifying model objects (to add XmlJavaTypeAdapter).
- EclipseLink MOXy external binding (EclipseLink MOXy is the default data binding and JAXB provider in WLS12.2.1.3).
- The doc states that "EclipseLink MOXy provides (...) the ability to use an external metadata file to configure the equivalent of JAXB annotations without modifying the Java source it refers to"
- but says also that "EclipseLink MOXy extensions can be leveraged (...) only in the Java to WSDL scenario".
- as a matter of fact I couldn't manage to have maven tooling nor the app to use this binding.
Put in code, it looks like:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>myapp</artifactId>
<packaging>war</packaging>
<groupId>sandbox.jaxws_migration</groupId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version></plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version>
<dependencies>
<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>webservices-tools</artifactId>
<version>2.3.1</version>
</dependency>
<!-- see https://java.net/jira/browse/WSIT-1672 -->
<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>webservices-rt</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<xadditionalHeaders>true</xadditionalHeaders>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/wsdl/hello_world.wsdl
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions name="HelloWorld"
targetNamespace="http://service.myapp/helloworld/"
xmlns:tns ="http://service.myapp/helloworld/"
xmlns:wsdl ="http://schemas.xmlsoap.org/wsdl/"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
xmlns:soap ="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:p ="http://types.myapp/person/"
>
<wsdl:types>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://service.myapp/helloworld/">
<xs:import namespace="http://types.myapp/person/" schemaLocation="../xsd/person.xsd"/>
<xs:element name="sayHello">
<xs:complexType>
<xs:sequence>
<xs:element name="who" type="p:person"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="sayHelloResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="greetings" type="xs:string">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="sayHello"> <wsdl:part name="p" element="tns:sayHello"/> </wsdl:message>
<wsdl:message name="sayHelloResponse"><wsdl:part name="p" element="tns:sayHelloResponse"/></wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="sayHello">
<wsdl:input message="tns:sayHello"/>
<wsdl:output message="tns:sayHelloResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorld" type="tns:HelloWorld">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHello"><soap:operation soapAction="sayHello"/><wsdl:input><soap:body use="literal"/></wsdl:input><wsdl:output><soap:body/></wsdl:output></wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorld">
<wsdl:port name="HelloWorld" binding="tns:HelloWorld">
<soap:address location="http://my.fake.url"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
src/xsd/person.xsd
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="http://types.myapp/person/"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="person">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="surname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
src/main/java/myapp/service/HelloWorld.java
package myapp.service;
import javax.jws.WebService;
import myapp.legacy.model.LegacyPerson;
@WebService(
endpointInterface = "myapp.service.helloworld.HelloWorld",
wsdlLocation = "wsdl/hello_world.wsdl"
)
public class HelloWorld implements myapp.service.helloworld.HelloWorld {
@Override
public String sayHello(LegacyPerson who) {
return "Hello " + who.getLegacyName() + " " + who.getLegacySurname();
}
}
src/main/java/myapp/legacy/model/LegacyPerson.java
package myapp.legacy.model;
public class LegacyPerson {
private String legacyName;
private String legacySurname;
public String getLegacyName() {
return legacyName;
}
public void setLegacyName(String legacyName) {
this.legacyName = legacyName;
}
public String getLegacySurname() {
return legacySurname;
}
public void setLegacySurname(String legacySurname) {
this.legacySurname = legacySurname;
}
}
src/jaxws/bindings.xml
<jaxb:bindings version="2.0"
xmlns:jaxb ="http://java.sun.com/xml/ns/jaxb"
xmlns:xs ="http://www.w3.org/2001/XMLSchema"
schemaLocation="../xsd/person.xsd"
>
<jaxb:bindings node="/xs:schema/xs:complexType[@name='person']">
<jaxb:class ref="myapp.legacy.model.LegacyPerson"/><!-- Make the SEI use my legacy model, but how should I describe how to bind the data? -->
<!-- This will make wsimport say : "compiler was unable to honor this property customization. It is attached to a wrong place, or its inconsistent with other bindings." -->
<!-- <jaxb:bindings node="//xs:element[@name='name']">
<jaxb:property name="legacyName" />
</jaxb:bindings>-->
</jaxb:bindings>
</jaxb:bindings>
References
- https://javaee.github.io/metro-jax-ws/doc/user-guide/
- https://download.oracle.com/otn-pub/jcp/jaxb-2_3-mrel3-eval-spec/JAXB-2.3-spec.pdf
- https://download.oracle.com/otn-pub/jcp/websvcs_metadata-2_1-mrel2-eval-spec/JSR181-2.1-MR.pdf
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-jws.htm#WSGET156
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-datatypes.htm#GUID-2C55847C-0990-4763-8041-EECE802A7EB1
- https://docs.oracle.com/middleware/12213/wls/WSGET/jax-ws-datatypes.htm#WSGET212
- http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
JAX-WS & JAX-RS with EclipseLink MOXy and external mapping documents
java web-services jaxb eclipselink jax-ws-customization
java web-services jaxb eclipselink jax-ws-customization
asked Nov 26 '18 at 13:27
Romain BuquetRomain Buquet
14614
14614
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53482156%2fis-it-possible-to-migrate-existing-jax-rpc-web-services-to-jax-ws-without-any-ws%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53482156%2fis-it-possible-to-migrate-existing-jax-rpc-web-services-to-jax-ws-without-any-ws%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown