Hi all,
I'm working on a small-ish multi-module project in Maven. We've separated the UI from the database layer using Web Services, and thanks to the jaxws-maven-plugin, the creation of the WSDL and WS client are more or less handled for us. (The plugin is essentially a wrapper around wsgen and wsimport.) So far so good.
The problem comes when I try to layer WSIT security into the picture. NetBeans allows me to generate the security metadata easily, but wsimport seems completely incapable of dealing with anything beyond a Basic-auth level of security.
Here's our current, insecure way of calling wsimport during a Maven build:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlUrls>
<wsdlUrl>${basedir}/../WebService/target/jaxws/wsgen/wsdl/WebService.wsdl</wsdlUrl>
</wsdlUrls>
<packageName>com.yourcompany.appname.ws.client</packageName>
<sourceDestDir>${basedir}/src/main/java</sourceDestDir>
<destDir>${basedir}/target/jaxws</destDir>
</configuration>
</execution>
</executions>
</plugin>
I have tried playing around with xauthFile, xadditionalHeaders, passing javax.xml.ws.security.auth.username and password through args. I have also tried using wsimport from the command line to point to the Tomcat-generated WSDL, which has the additional security info. Nothing, however, seems to change the composition of the wsimport-generated files at all.
So I guess my question here is, to get a WSIT-compliant client, am I stuck abandoning Maven and the jaxws plugin altogether? Is there a way to get a WSIT client to auto-generate? Or will I need to generate the client by hand?
Let me know if you need any additional info beyond what I've written here. I'm deploying to Tomcat, although that doesn't seem to be an issue, as Maven seems happy to pull Metro into the deployed WAR file.
Thanks in advance!
EDIT: After a lot of playing around with WSIT, here's what worked for me.
For starters, use Netbeans to generate a WSIT client. Test it to make sure it works, and then move the WSIT configuration files (wsit-client.xml and [your web service name].xml) to the META-INF directory of the WS client project.
The relevant addition to your project, from a security standpoint, is the tag in the web service xml:
<wsp:Policy wsu:Id="WebPortBindingPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sc:CallbackHandlerConfiguration wspp:visibility="private">
<sc:CallbackHandler default="wsitUser" name="usernameHandler"/>
<sc:CallbackHandler default="changeit" name="passwordHandler"/>
</sc:CallbackHandlerConfiguration>
<sc:TrustStore wspp:visibility="private" location="C:\Apps\apache-tomcat-6.0.24\certs\client-truststore.jks" type="JKS" storepass="changeit" peeralias="xws-security-server"/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Obviously, there are some hard-coded dependencies in here that we'll need to manage during our build. The user, password, location of the truststore, and the peeralias are all development defaults, and will change as the system moves from dev into testing and production. We're playing around with a few different strategies for managing this, but we'll probably end up setting environment variables in Hudson for build-out to each environment.
Fiddle with the configuration of Maven's jaxws plugin a little. We generate the WSDL as part of the build, so we don't need to reference it locally. Here is the plugin tag for the wsimport command in our WS client target:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>1.12</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlUrls>
<wsdlUrl>${basedir}/../WebService/target/jaxws/wsgen/wsdl/WebService.wsdl</wsdlUrl>
</wsdlUrls>
<staleFile>${project.build.directory}/jaxws/stale/WebService.stale</staleFile>
<packageName>com.yourcompany.appname.ws.client</packageName>
<sourceDestDir>${basedir}/src/main/java</sourceDestDir>
<destDir>${basedir}/target/jaxws</destDir>
</configuration>
<id>wsimport-generate-WebService</id>
<phase>generate-sources</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>webservices-api</artifactId>
<version>2.0-b30</version>
</dependency>
</dependencies>
<configuration>
<sourceDestDir>${project.build.directory}/generated-sources/jaxws-wsimport</sourceDestDir>
<xnocompile>true</xnocompile>
<verbose>true</verbose>
<extension>true</extension>
</configuration>
</plugin>
And finally, of course, make sure that all your projects that will need to call web services have the Metro dependency properly set up.