Skip to content
fmarot edited this page Nov 1, 2012 · 13 revisions

Tutorial: CXF Webservice using Maven & an XML Catalog.

Note: Feel free to modify/enhance this wiki :)

If you just want to know how to have separate Maven projects for your WSDL+webservice and the XSDs files they use, jump directly to section “Technically speaking”. Note: the approach described here is “WSDL to java” meaning Java webservices are generated from WSDL and XSD type files.

Introduction

In a simple world you usually have your XSD along your WSDL and you can simply expose your webservices using CXF. In a complex world, you separate the XSD <--> Java mapping and the webservice into 2 disctinct projects... and you have to use a catalog and configure the “cxf-codegen-plugin” to do the Job.

Context

First, let’s introduce the need. Imagine that you have a single (Maven) project where you have your WSDL, your XSD(s) and you use CXF/Maven to generate Java sources from those. Everything is simple and works. this is the classic way.

Now, let’s imagine that the webservice you expose records clients orders. It’s your system’s entry point. Those orders are the core domain of your system, they are very complex objects and many other backend applications (webapps) share the same domain model. Great. Now imagine you have a problem on one of those apps on one specific order. And you got no f****** idea of what’s happening in the code there ! How would you debug ? An idea would be to write a unit test of the failed service reproducing the incorrect behavior. But you don’t know what’s wrong ! Then it would be easy if you could just get the xml from the original order, unmarschal it to a Java order and pass this order to your service to reproduce the behaviour in a JUnit test.

Context Diagram

Why separate the webservice into 2 projects ?

So now we have a need to be able to unmarschal the XML orders. Great. The XSD(s) are already in the webservice project. But the 2 easy solutions are not satisfactory:

  • either import in our test the full webservice project, meaning having to import a WAR as a dependency in our service ... ouch !
  • or create 2 artifacts from the unique webservice project. But, as Sonatype confirms, that is clearly not a good practice.

The retained solution is

  • to create another project (let’s call it “mapping-service”) that will contain:
    • the XSDs
    • the java code auto-generated from the XSD
    • the java code handling loading an order.xml file
  • make the webservice depend on the new project
  • in all other backend projects, we are now able to use the new project to leverage loading orders from XML files. Each time a problem appears with a specific order, we can take the original XML and load it thanks to our new project (“mapping servic”) whom misc backend projects depend now onto.

Maven projects hierarchy

Technically speaking

  1. In the mapping service project, we use the Maven “cxf-xjc-plugin” to generate Java sources from the XSD defining the Order object. that’s all, plain and simple.
  2. In the webservice project: the maven generate-sources phase is used by the “cxf-codegen-plugin” to generate Java files (remember, we’re doing WSDL to Java ?). BUT this plugin is configured specifically: ** the first tip is to use the -catalog option to point to an XML Catalog. Basically, the catalog we use just tells the plugin to look on the classpath for the XSDs. Remember we chose to export this/those file(s) into project mapping service ? Our wsdl references a XSD file containing the following code <xsd:import namespace="http://www.teamtter.com/tutorial/xmlmapping/xsd/order/v1" schemaLocation="xsd/types/v1/orderType.xsd" /> But xsd/types/v1/orderType.xsd is not a local file and classpath:xsd/types/v1/orderType.xsd is no correct XML so it justifies the use of an XML Catalog to do the translation. To learn more about XML Catalogs, please refer to Wikipedia or IBM DeveloperWorks ** the second tip is to use the -nexclude option as many times as there are XSD namespaces whom java sources are generated in other projects. Specifically here we use the following code to tell the plugin not to generate the OrderType.java (among other) file. Remember, it’s already generated in the mapping service project !

The rest of the app is classic CXF/Spring configuration (as described in the official CXF doc) to expose the webservice.

If you have any question regarding this tutorial, feel free to ask by creating a new issue.

Clone this wiki locally