Sunday, September 6, 2009

Migrating Web Services from JDeveloper 10g to 11g

Although most of the migration steps from JDeveloper 10g/OC4J to JDeveloper 11g/WebLogic are automated, there are some exceptions. One such case where you have to roll up your sleeves and do some coding are EJB 3 Session Beans that are exposed as Web Services using JAX-WS annotations. JDeveloper 10g generates a separate Java interface containing JAX-WS Web Service annotations when using the EJB 3 Session Bean Wizard and selecting the option to create a Web Service interface. Note that this option isn’t available in JDeveloper 11g, but you can right-click an EJB Session Bean and select the generate Web Service option that will give you the same result.

When migrating the JDeveloper 10g workspace to a JDeveloper 11g application -by opening the jws file in JDeveloper 11g- most of the migration work is automatically done; for example the workspace and project files are updated and existing deployment plans are converted.

If you then deploy the project to the integrated WebLogic server everything seems to deploy and run just fine. However if you expand the deployment in the WebLogic Server Administration Console you’ll see that there are no web services listed, only EJBs.

Here are some simple steps to correct this:

  1. Remove the Java interface containing the JAX-WS Web Service annotations that was generated in JDeveloper 10g and remove the interface from the implements statement in the EJB Session Bean class.
  2. Add a @WebService annotation to the EJB 3 Session Bean containing the following arguments: name, serviceName, and portName. Check the WSDL of the current deployed Web Service generated with JDeveloper 10g to obtain its metadata such as name, namespace, and portname. These values can be used in the new @WebService annotations of the migrated Web Service in JDevloper 11g so that Web Service clients don’t break due to different namespaces, portnames, endpoints, and so on. You can also use other annotations to influence the endpoint and WSDL of the Web Service. However mind that some annotations are WebLogic-specific and not part of the JAX-WS standard.
  3. Optionally add other JAX-WS annotations as needed.
  4. Replace the JAX-RPC project libraries with the JAX-WS Web Services library.
  5. The current WebLogic JAX-WS stack -more specific the JAXB implementation- does not support java.util.Map and java.util.Collection family types as Web Service method return or input types. Deployment fails with the message “java.util.Map is an interface, and JAXB can’t handle interfaces” and “java.util.Map does not have a no-arg default constructor”. A logical workaround would be to replace these types with concrete implementations that have a no-argument constructor; for example java.util.HashMap. Although deployment then succeeds, the information contained in the map is lost at runtime when requests/responses are (un)marshalled. A final workaround was to replace the java.util.Map with a two-dimensional array. Although I’m not really happy with this workaround, it works for now.

Deploy the project and voila, the WebLogic Server Administration Console shows both EJBs and Web Services.

So “no coding required”, or just a little bit perhaps :-) ?

P.S. Some useful links: