WSDL 2 Java
So you decided to do wsdl 2 java design. This is currently
the more “proper” way to go about it. For more information about this debate
see: http://docs.spring.io/spring-ws/site/reference/html/tutorial.html.
You have the wsdl but how do you generate the code?
Maven Plugin
If all you need is to convert one wsdl, you can do a quite simple
solution with maven using the ant plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-classes</phase>
<configuration>
<target>
<java classname="org.apache.cxf.tools.wsdlto.WSDLToJava"
fork="true">
<arg value="-impl"
/>
<arg value="-b"
/>
<arg value="bindings.xjb"
/>
<arg value="-server"
/>
<arg value="-d"
/>
<arg value="gen"
/>
<arg value="-wsdlLocation"
/>
<arg value="/WEB-INF/wsdls/my.wsdl"
/>
<arg value="my.wsdl"
/>
<classpath>
<path refid="maven.compile.classpath"
/>
</classpath>
</java>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
This plugin will generate using the cxf engine a java file
with all the schema files needed for the code.
This is a good solution if you just need one file or want to
just look things over.
If you have multiple wsdl’s and you want to intervene during
the generating process you need to do it by code. Also in the case that you do
not know in advance what the wsdls are but only know the directory of the wsdls,
then you need to generate them via code.
Java Code
To run the cxf engine via the java code you will need to run
the same command line as above just via java code.
So why do we want to use java code and not just a simple maven
plugin. First reason is, if you want to add a binding file. For more about
binding please see: http://www.oracle.com/technetwork/articles/entarch/jax-ws-jaxb-customization-082750.html,
https://blogs.oracle.com/sdimilla/entry/implementing_handlers_using_jaxws_2.
Binding files allows you to change the way the java code is
generated. You can add annotations, or define the package name and many more
things.
Binding files, recommend that you add the wsdl location in
the binding file, like:
<jaxws:bindings
wsdlLocation="xxx.wsdl"
The disadvantage of this, is that you need to create a
template binding file so that you can change the name for each wsdl file. The
other option is to just omit this section in the binding file.
The main options are: where to generate the code, whether or not to
compile it, and the wsdl location. For all options see http://cxf.apache.org/docs/wsdl-to-java.html.
Another issue that needs to be handled is the location of
the command path relevant to the bind file. You can put the bind file where
ever you want, but when passing the location to the api, the relative path must
be relative to the working directory of the command execution. For an easy way of calculating relative paths
between directories please see:
Code generation intervene
One of the features that are greatly missing is the ability
to intervene in the code generation of the wsdl service file. If you want to intervene
in the generation of the xsd files, you can do this with jaxb plugins.
For a nice example that adds support for XmlElementWrapper
see (https://github.com/dmak/jaxb-xew-plugin).
For more information on plugins and jaxb extensions see http://www.jroller.com/gmazza/entry/enhancing_jaxb_artifacts.
The problem is that for the wsdl generation cxf did not use
the jaxb plugins scheme and there is no official way to intervene in the code
generation.
I “hack” can be done. Cxf uses a velocity template to
generate the file. The velocity template name is iml.vm. So if you write your
own template (and place it in the same package as cxf template), and add it to
a jar that is in the classpath before the cxf jar, your template will be used by
cxf and not the internal one.
Other issues for code generation
If you are generating all the web service stubs, you will
most probably also want your code to add to your cxf xml file all the proper endpoints
as well.
Generation of Code
Since we will be generating the service classes from the
wsdl’s you need to think if this process is a onetime process or an ongoing
one. If it is part of your build system, then you cannot edit the generated
files (by default cxf generates the files with a TEMP suffix). There are a few
options to solve this issue. First you need to make sure that all generated
files are not in the source area but in the generated (/target/ generated-sources).
You now have a few options of how to add your specific code,
while still continue to regenerate the service classes. The simple one is to
just copy the service class into you source code. This sort of defeats the idea
of having new services added dynamically. Second solution is if you edited the template generation you can have all services
delegate the call to a central spring bean, and then use the proxy pattern to
handle all calls. Third option is to add an AOP layer to catch all calls to the
service and write a generic code for all of them without having to do any wiring
or changing of cxf templates.
No comments:
Post a Comment