I'm building (multiple) complex webservice with base XSD types from all kinds of standards (GML, SWE, XLINK, etc). Now, I would like to break up the compilation into more steps, preferrably one for each of the standards I'm using.
Advantages:
1) I can add create tooling libraries that I can re-use in all of my webservices on each of the standards.
2) I can make use of the power of JAXB2 basics plugin, which seems to work very nicely with the maven-jaxb2-plugin (org.jvnet.jaxb2.maven2) and create for instance interface bindings. This in contrast with the jaxws-maven-plugin plugin.
The final step would be using the org.jvnet.jax-ws-commons:maven-jaxb2-plugin to create the actual web service that I can implement in an EJB (or call as a client).
Now, the org.jvnet.jaxb2.maven2:maven-jaxb2-plugin plugin allows me to refer to episodes by means of their maven coordinate, as part of its like this:
<episodes>
<episode>
<groupId>org.example</groupId>
<artifactId>jaxb2-basics-test-episodes-a</artifactId>
</episode>
</episodes>
How can I do this by means of the org.jvnet.jax-ws-commons:maven-jaxb2-plugin? I've searched a lot, and experimented like this:
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>>maven-jaxb2-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
</execution>
</executions>
<configuration>
<wsdlDirectory>src/main/resources/</wsdlDirectory>
<wsdlFiles>
<wsdlFile>example.wsdl</wsdlFile>
</wsdlFiles>
<xjcArgs>
<xjcArg>-b</xjcArg>
<xjcArg>../cpt-xsd/target/generated-sources/xjc/META-INF/sun-jaxb.episode</xjcArg>
</xjcArgs>
<verbose>true</verbose>
</configuration>
</plugin>
Which takes the episode file from the target dir of the (compiled) JAXB dependend project. This sometimes even fails in the maven build (why I did not figure out yet).
I've tried to use catalog files to make a mapping but (I think I saw somewhere a catalog mapping that took maven coordinates as destination), but haven't succeeded yet.
Are you aware of the OGC Schemas and Tools Project? (Disclaimer: I'm the author.)
Now, to your question. My guess would be that org.jvnet.jax-ws-commons:maven-jaxb2-plugin does not support the "Maven coordinates" as you call them. This was a feature I've specifically implemented for my org.jvnet.jaxb2.maven2:maven-jaxb2-plugin (disclaimer: I'm the author).
From the other hand, episode file is nothing but a JAXB binding file. So you can simply extract this file from the JAR artifact (for instance using the maven-dependency-plugin) and then include it more or less like you do it already. Just don't point to directories in other modules, this is not reliable.
Related
I'm using jaxws-maven-plugin to execute wsimport for a web service consumer app. I'm using the -clientjar option on wsimport which was introduced with JAX-WS 2.2.2 RI in 2010. I do this because I want to bundle the WSDL within the jar.
I don't have a problem crafting the pom. For plugin configuration I do something like:
<configuration>
...
<args>
<arg>-clientjar</arg>
<arg>bundled-wsdl.jar</arg>
</args>
</configuration>
When I execute a build my created jar, lets call it myapp.jar, has file bundled-wsdl.jar within it. Inside the bundled-wsdl.jar's META-INF directory I find the wsdl and xsd just as I like them. I'm also quite happy with the generated java code that come as a result of using the -clientjar option. So far so good.
But this stuff should be in myapp.jar's META-INF, right?
The fact that it sits within bundled-wsdl.jar's META-INF doesn't help me a lot.
The funny thing is that I do in fact get a wsdl file in myapp.jar's META-INF which makes the application actually work. How it gets there I don't know. Also the xsd file isn't there, only in bundled-wsdl.jar's META-INF.
The basic question is how to correctly use wsimport -clientjar option in a Maven project ?
Java 1.7.0_45.
The -clientjar option is really poorly documented, IMHO.
Here's how I believe it works:
When the -clientjar <jarfile> option is used three things are happening:
You'll get a <jarfile> generated in the directory pointed to by
the -d argument to the wsimport tool. This will contain within
it both WSDL and any relevant XSD files as well. This little bundle will not be used for anything at all. If you want to make use of it it would be entirely up to you. But before you do see (2) below. I'm not sure what to use this jarfile for other than as a form of documentation.
You'll get a copy of the WSDL put into a file called
META-INF/wsdl/<svcname>.wsdl. The generated classes will use this
file in the no-arg proxy constructor. So this is what will actually
be used if you request a bundled WSDL file with the -clientjar
option.
The generated code will change so that wsdlLocation, if you are using the default no-arg constructor on the #WebServiceClient class, will be that of the bundled WSDL (from (2)), rather than the remote WSDL. Indeed if you use -wsdllocation on your command line together with -clientjar then whatever you specify with -wsdllocation will have no effect as -clientjar will take precedence.
So we must focus on (2) and (3) because that's the only one being actually used ... at least if you use the generated code as-is.
It is interesting to note that the result of (2) is only a WSDL file. This file may have embedded links to XSD files but as far as I can tell such link will never be followed. The reason is that when we say a web service consumer needs the WSDL at runtime it really only needs the WSDL itself, at not the schema. The schema is "hardcoded" into the consumer and there's no way of changing it at runtime. Hence there's no reason to read schema information at runtime. (THIS IS FROM MY UNDERSTANDING)
Second thing to note about the WSDL that's included with (2): It is really just a copy of the original WSDL so it may not have endpoint you want. Actually in most cases it won't. This means that in this situation you'll need to set the endpoint yourself :
// Use no-arg constructor. Means it uses the WSDL bundled into the
// META-INF/wsdl directory rather than trying to retrieve WSDL over the
// network.
service = new HelloSvc_Service();
hello = service.getHelloSvcPort();
// Since we're using a bundled WSDL the web service URL cannot
// be derived from that (it would be wrong!). So we have to set
// it explicitly.
((BindingProvider) hello).getRequestContext().put(
BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://myhellowebservice-address");
The documentation for this plugin is a joke. A workaround is to manually extract the contents from the client jar after it is created like follows:
<build>
<plugins>
<plugin>
<!--
Generates JAXWS classes for all of the WSDL files in $[project.base.dir}/src/wsdl.
-->
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<args>
<arg>-clientjar</arg>
<arg>${project.build.directory}/wsimport-client.jar</arg>
</args>
<wsdlUrls>
<wsdlUrl>https://webservice.com/service.wsdl</wsdlUrl>
</wsdlUrls>
</configuration>
</execution>
</executions>
<configuration>
<target>2.1</target>
<verbose>true</verbose>
</configuration>
</plugin>
<plugin>
<!--
Unjar the wsimport-client.jar created in the jaxws-maven-plugin to the WAR's classes folder
-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<target>
<unzip src="${project.build.directory}/wsimport-client.jar" dest="${project.build.directory}/classes" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
taken from here: https://gist.github.com/mpellegrini/5439304
I had the same issue, and I had to unzip the created jars and re-zip in one single jar (so, putting the wsdl file from the inner jar in the final jar).
Thanks to peterh comment, I think I understood the "trick": in Maven output I can see a log like
jaxws:wsimport args: [..., -Xnocompile, -clientjar wsdl.jar, ...]
so the wsimport command is launched without compiling che code, and in fact a wsdl.jar is created in the target/classes folder.
I think wsimport is just generating the sources and the jar with the wsdl, then the compilation and the packaging is done in the following steps.
I'm new to maven, and I want to use maven to generate the java code from a wsdl file (using the wsimport plugin ?), which is in my project (not in a url).
I think the wsdl file should be somewhere in myprojet/src/main/resources, and the generated sources in myproject/target/generatedsources/ws.
If the choice of these places ok ? If so, how can I create the sources from the wsdl to the designated folder using maven ? Can I choose the java package name of the sources ? Should I ? Should I then make a jar file out of the sources ? How can I make sure that the generated sources are accessible for the compilation (in the classpath) ?
thank you.
There are several ways to do this with the wsimport plugin, but most examples would require more knowledge of your pom.xml
Apache CXF is a popular free plugin for this exact purpose
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/myService.wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
NOTE: You can definitely make a jar out of the generated sources, but this would be a separate entry inside your POM
check out Apache's Axis2 -- it's designed specifically to help generate code based on an WSDL for web services. Basically it's exactly what you are looking for:
http://axis.apache.org/axis2/java/core/
EDIT: To expand, I typically will run the wsdl2java(.bat or .sh) file and point it to the wsdl (either on the web or local copy) and it generates everything else. It can even package it all into a jar for you (my preferred method because it's "cleaner"). You likely won't have any need to go into the generated code and change anything, you just end up adding that jar to your classpath then import like any other library and use it.
I'm looking to convert a WSDL version 1.1 into a WSDL 2.0 format as part of our maven build process.
I've come across the Woden Converter utility which uses XSL to do this conversion, and would like to use it. However, there seems to be no documentation or examples (that I can find) on how to configure or use the related maven plugin: woden-converter-maven-plugin
Does anyone have experience with this, and could they please share the maven plugin config details?
Justification (for those that require it):
We have a contract-first Web Service and have a recent requirement to expose our WSDL in 2.0 format to one particular client. To save on maintaining two identical WSDLs, we'd like to maintain the 1.1 wsdl and have the build process auto-generate the 2.0 version.
Here are the sources for the plugin. There's not much you can set. Check the fields. You can set those up in the <configuration/> section of your plugin.
Consider this:
<plugin>
<groupId>org.apache.woden</groupId>
<artifactId>woden-converter-maven-plugin</artifactId>
<version>1.0M9</version>
<executions>
<execution>
<id>convert</id>
<goals>
<goal>convert</goal>
</goals>
<configuration>
<wsdl><!-- File or URL of wsdl1.1 document.Also multiple
WSDL files can be specified as a comma separated
list. -->
</wsdl>
<targetNS>
<!-- New target namespace for WSDL2.0 document. -->
</targetNS>
<targetDir>
<!-- Target directory for output, default
location is project build directory. -->
</targetDir>
<sourceDir><!-- Source directory for output. --></sourceDir>
<verbose><!-- Verbose mode --></verbose>
<overwrite><!-- Overwrite existing files. --></overwrite>
</configuration>
</execution>
</executions>
</plugin>
I am working on a fairly large WS project involving more than 20 different WebServices. These webservices, while independent from each other, share a sizable set of common types. We are using wsimport as an ant target in our build script to generate the proxy classes.
Problem:
As the number of our WS(and corresponding WSDLs) has increased, we noticed that the build times for our proxy classes has been climbing up pretty steep. Upon further investigation(and profiling), we found out that a huge chunk of the build time was being spent by wsimport on repeatedly generating the common types. It has gotten to a point that generating, compiling and packaging these proxy classes and their common types are taking around 15-20 mins. This is a problem for us and we are looking for ways to trim down the build time.
Question:
Is there a way to only generate the common types once? I've looked into some solutions found by googling. One involved writing a WSDL accumulator which parses the WSDLs and combines them into a single WSDL so wsimport is only called once. Another one hinted at using episode files but further investigation only yielded that there were problems with using that approach.
Note: I have seen some older similar questions but none of them had any answers.
wsimport multiple generated wsdl's
How can I tell wsimport that separate WSDL files are referring to the same object classes?
First of all I would use apache cxf to do that build as it can handle multiple WSDLs at the same time and is much more modern. It will be much more efficient and generate better classes. Second of all I would stop worrying about it unless the WSDL files are changing a lot. Instead i would put them into a separate artifact and build them once and then import them into the project as their own artifact. The only thing non-generated in that archive should be test code to test endpoints. As for the build, the Maven plugin config i have used with great success is pasted below.
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${apache.cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated-sources/</sourceRoot>
<defaultOptions>
<catalog>${wsdlDir}/jax-ws-catalog.xml</catalog>
<bindingFiles>
<bindingFile>${wsdlDir}/jaxb-bindings.xml</bindingFile>
<bindingFile>${wsdlDir}/jaxws-bindings.xml</bindingFile>
</bindingFiles>
<noAddressBinding>true</noAddressBinding>
<extraargs>
<extraarg>-client</extraarg>
<extraarg>-xjc-Xbug671</extraarg>-->
<extraarg>-xjc-mark-generated</extraarg>
</extraargs>
</defaultOptions>
<wsdlOptions>
<wsdlOption>
<wsdl>${wsdlDir}/cis.wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.cxf.xjcplugins</groupId>
<artifactId>cxf-xjc-bug671</artifactId>
<version>${apache.cxf.xjc.version}</version>
</dependency>
</dependencies>
</plugin>
This is set up to generate from only one WSDL but one could easily append more WSDLs and I have done so in other circumstances.
How would you structure Freemarker (or an alternative) as a templating code generator into a Maven project? I'm pretty new to Maven and would appreciate some help.
I want to generate some code from templates in my project. [a]
Rather than write my own, googling found freemarker which appears to be used by Spring which is a good enough reference for me, though as I haven't started with it yet, any other suggestions that work well with Maven would be appreciated too.
This website tells me how to add it as a dependency to my pom.xml.
This SO question tells me where the generated sources should go. What I can't work out is how to tie it all together, so I get my generated sources generated from the templates, and then my generated sources used like regular sources for compile, test, jar, javadoc etc. Has anyone else used a template code generator for java within maven and could help?
[a] I know Generics would be the usual solution, and in fact I'm using them, but I have to use templates to cope with the primitive cases, without introducing copy/paste errors. Please trust me on this :-)
I had written a maven plugin for this purpose. It uses the FreeMarker Pre Processor.
Heres the fragment from pom.xml highlighting its usage:
<plugins>
<plugin>
<configuration>
<cfgFile>src/test/resources/freemarker/config.fmpp</cfgFile>
<outputDirectory>target/test/generated-sources/fmpp/</outputDirectory>
<templateDirectory>src/test/resources/fmpp/</templateDirectory>
</configuration>
<groupId>com.googlecode.fmpp-maven-plugin</groupId>
<artifactId>fmpp-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Here the cfgFile is the path where you keep the config file for FMPP. (if you are not using any special data passing in FreeMarker then an empty file will be enough)
templateDirectory is where you keep the FreeMarker templates.
outputDirectory is where you want the output files to be generated.
I am in process of writing a detailed documentation highlighting the plugins usage and will update the project website accordingly.
Here is another plugin for the job:
https://code.google.com/p/maven-replacer-plugin/
From the original description of the problem it sounds like you should consider creating a Maven Archetype (aka Project Template):
http://maven.apache.org/archetype/maven-archetype-plugin/
And it sounds like you might want to add some properties into the equation:
http://maven.apache.org/archetype/maven-archetype-plugin/examples/create-with-property-file.html
Maven Archetype functionality also provides a means of doing substitution using Apache Velocity (near enough the same as Freemarker) ... but I haven't worked that bit out yet.