Maven for building SOA services and clients? - wsdl

I changed the title to generalize this question which really isn't specific to Axis2. I eventually gave up on Axis2 altogether and switched to Metro/JAX-WS but am now seriously considering giving up on both and switching to OpenSAML. The real question I'm struggling to get answered here is, how to build complex standards-based SOA services that actually work.
The original phrasing was: Could someone paste in a working example of maven pom to invoke Axis2 java2wsdl with defaults I can live with? Here's a command line incantation that behaves sort of OK.
-o target/generated-sources/java2wsdl \
-l "http://localhost:9763/services/PolicyService" \
-tn urn:sesgg:sc:security:1.0.spec.PolicyService \
-tp ps \
-stn urn:oasis:names:tc:SAML:2.0:protocol \
-stp samlp \
-of PolicyService.wsdl \
-sn PolicyService \
-cp "../../Schema/target/Schema-1.0-SNAPSHOT.jar target/PolicyService-1.0-SNAPSHOT.jar" \
-cn com.technica.pbac.ps.PolicyService \
Everything I do winds up with really squirrely results; e.g. weird reversed namespaces (http://xmldsig._09._2000.w3.org/xsd for example). Could you explain why this is and how to stop it?
There seems to be a lot java2wsdl's out there that expect entirely different arguments, with little consistency between command line and maven pom.

No responses so I'll post current results of my own experiments to help others with
similar problems. Can't guarantee this is correct until testing is finished but at least now I'm getting results I can bear looking at in Eclipse:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.7.5</version>
<configuration>
<schemaExcludes>
<exclude>*saml*.xsd</exclude>
</schemaExcludes>
<strict>true</strict>
<extension>true</extension>
</configuration>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-java2wsdl-maven-plugin</artifactId>
<version>1.5.4</version>
<executions>
<execution>
<goals>
<goal>java2wsdl</goal>
</goals>
</execution>
</executions>
<configuration>
<id>Generate WSDL based on PolicyService Interface</id>
<serviceName>PolicyService</serviceName>
<className>com.technica.pbac.ps.PolicyServiceImpl</className>
<targetNamespace>http://sesgg/sc/security/1.0/spec/PolicyService</targetNamespace>
<targetNamespacePrefix>sesgg</targetNamespacePrefix>
<schemaTargetNamespace>http://sesgg/sc/security/1.0/spec/PolicyService</schemaTargetNamespace>
<schemaTargetNamespacePrefix>sesgg</schemaTargetNamespacePrefix>
<elementFormDefault>qualified</elementFormDefault>
<extension>false</extension>
<package2Namespace>
<property>
<name>urn:sesgg:sc:security:1.0:spec:PolicyService</name>
<value>http://sesgg/sc/security/1.0/spec/PolicyService</value>
</property>
<property>
<name>com.technica.pbac.ps</name>
<value>http://com.technica.pbac.ps</value>
</property>
<property>
<name>oasis.names.tc.saml._2_0.protocol.xsd</name>
<value>http://oasis/names/tc/saml/2.0/protocol</value>
</property>
<property>
<name>oasis.names.tc.saml._2_0.protocol</name>
<value>http://oasis/names/tc/saml/2.0/protocol</value>
</property>
</package2Namespace>
<episodes>
<episode>
<groupId>Technica-PBAC</groupId>
<artifactId>Schema-1.0-SNAPSHOT.jar</artifactId>
</episode>
</episodes>
<outputFileName>target/generated-sources/java2wsdl/PolicyService.wsdl</outputFileName>
<filename>target/generated-sources/java2wsdl/services.xml</filename>
<locationUri>http://localhost:9763/services/PolicyService</locationUri>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-wsdl2code-maven-plugin</artifactId>
<version>1.5.4</version>
<executions>
<execution>
<goals>
<goal>wsdl2code</goal>
</goals>
<configuration>
<wsdlFile>target/generated-sources/java2wsdl/PolicyService.wsdl</wsdlFile>
<packageName>com.technica.pbac.ps</packageName>
<outputDirectory>target/generated-sources/wsdl2java</outputDirectory>
<unwrap>true</unwrap>
<allPorts>true</allPorts>
<databindingName>adb</databindingName>
<generateServerSide>true</generateServerSide>
<generateAllClasses>true</generateAllClasses>
<generateServicesXml>true</generateServicesXml>
<generateTestcase>true</generateTestcase>
<overWrite>true</overWrite>
<serviceName>PolicyService</serviceName>
<syncMode>sync</syncMode>
<backwardCompatible>false</backwardCompatible>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-java2wsdl-maven-plugin</artifactId>
<version>1.5.4</version>
</plugin>
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-wsdl2code-maven-plugin</artifactId>
<version>1.5.4</version>
</plugin>
</plugins>
</pluginManagement>
</build>
One caution: I really doubt its right to be running jaxb, java2wsdl, wsdl2java and compile phases in a single pom. Currently java2wsdl runs after wsdl2java this way which obvously isn't right. This pom is doubly suspicious since java2wsdl needs a compiled jar to run, and seems to be using the one left over from previous runs. Its a bear to get working again after mvn clean. I'll probably wind up splitting it into several poms and will adjust this answer when I do.

I promised to extend this answer with something approximately "right". Here is progress to date, which I'm still not absolutely sure is 100% correct. More about that later.
This is all based on the stack of schema Oasis publishes to define the XACML and SAML-P for XACML standards. The XSD's have been gathered into a Commons-Schema module (not shown), tweaked to fix several Oasis errors, and compiled to Java classes with JAX-B. These classes are the foundation for the services described below. The schema.episode.path and schema.catalog.path properties point to files in this module.
I split each service (PolicyService in this case) into two maven modules. PolicyService-Svc is the service and its pom looks like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<id>Generate WSDL</id>
<phase>generate-resources</phase>
<goals>
<goal>wsgen</goal>
</goals>
<configuration>
<sei>com.technica.pbac.ps.PolicyService</sei>
<genWsdl>true</genWsdl>
<keep>true</keep>
<verbose>true</verbose>
<extension>true</extension>
<catalog>${schema.catalog.path}</catalog>
<xjcArg>-episode</xjcArg>
<xjcArg>${schema.episode.path}</xjcArg>
<xjcArg>-catalog</xjcArg>
<xjcArg>${schema.catalog.path}</xjcArg>
</configuration>
</execution>
</executions>
</plugin>
PolicyService-Proxy is generic proxy code that any client or service can use to invoke that service (more about problems with this below). Its pom looks like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<!-- <phase>generate-sources</phase> -->
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlFiles>
<wsdlFile>localhost_8080/PolicyService-Svc/PolicyService.wsdl</wsdlFile>
</wsdlFiles>
<wsdlLocation>http://localhost:8080/PolicyService-Svc/PolicyService?WSDL</wsdlLocation>
<sourceDestDir>${project.build.directory}/generated-sources/jaxws</sourceDestDir>
<genWsdl>true</genWsdl>
<verbose>true</verbose>
<extension>true</extension>
<catalog>${schema.catalog.path}</catalog>
<xjcArg>-episode</xjcArg>
<xjcArg>${schema.episode.path}</xjcArg>
</configuration>
</execution>
</executions>
</plugin>
Now for the problems, which I'd really appreciate advice on. Even though Commons-Schema provides compiled java classes for all schema, wsgen insists on producing a wsdl with newly-generated xsds, which are slightly different and slightly incorrect in various ways.
As one example of incorrect and different, SAML defines an Extensions element that conflicts with the same name in another schema. So I repaired it in the base Commons-Schema like this:
<element name="Extensions" type="samlp:ExtensionsType">
<annotation>
<appinfo>
<jxb:class name="Extensions-SAML"/>
</appinfo>
</annotation>
</element>
But wsgen/wsimport omits this correction so the conflict turns up again. Infuriating and absolutely fatal to the build.
Another is omitting required includes so eclipse validation reports them as errors until hand-corrected. My workaround is to periodically copy the generated wsdl and xsds from the target folder to src/main/webapp/WEB-Inf/wsdl, repair them by hand, and tweak the poms to use this folder instead of the generated one inside target. This works for invoking services from non-service clients. I copy the same wsdls and xsds to a similar client folder and ensure that the pom references these, not the ones jaxws generates in that module.
The problem I can't solve occurs when any service needs to invoke another service via its proxy. The calling service's proxy jar (with its slightly different versions of important foundation classes) is now mixed in with the calling service jars (based on Commons-Schema's JAXB-generated classes), which causes no end of trouble.
Can someone please advise? Thanks!

The ultimate answer to this question was indeed to give up on trying to fix busted schemas and tools and switch to OpenSAML, which has already done that. This worked fine for the XACML 2.0 compiler and web services based on it. But it fell flat for the XACML 3.0 compilers because OpenSAML doesn't support XACML 3.0 and has no plans to do so, so I had to handle that myself. But with experience with XACML 2.0 to build on, I eventually got both working. This project was far more painful than it had to be and "powerful" tools just made it harder.

Related

liquibase maven plugin disable checksum

I'm using liquibase with maven-3. The first run works as expected. Consecutive runs though (even if the sql files contain changes) fail, as they are viewed as equivalent from liquibase and ignored (checksum).
All the sql actions in my sql scripts have taken into account the previous runs, so I don't want this behaviour. With this setup that you see below, how can I force liquibase to always execute my scripts, no matter the changes?
As you can see below I've already tried setting clearCheckSums as a goal and indeed it clears the hash values, but still no luck (thus commented out).
This is the profile I've created
<profile>
<id>liquibase-executions</id>
<build>
<defaultGoal>process-resources</defaultGoal>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.2</version>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>update-schema</id>
<phase>process-resources</phase>
<goals>
<goal>update</goal>
<!--<goal>clearCheckSums</goal>-->
</goals>
<configuration>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://${db.url}</url>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
<changeLogFile>${basedir}/src/main/resources/liquibase.sql</changeLogFile>
</configuration>
</execution>
<execution>
<id>update-data</id>
<phase>process-resources</phase>
<goals>
<goal>update</goal>
<!--<goal>clearCheckSums</goal>-->
</goals>
<configuration>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://${db.url}</url>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
<changeLogFile>${basedir}/src/main/resources/liquibase-populate.sql</changeLogFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
And this is how I execute it
mvn process-resources -Pliquibase-executions -Ddb.url=POSTGRES_IP:5432/POSTGRES_DB -Dliquibase.username=POSTGRES_USERNAME
The Liquibase Maven plugin expects a changelog file, no plain .sql file. This file should contain your changeSets that you want Liquibase to execute. These changeSets can be instructed to be run every time you run Liquibase (by default they're only executed once). So there's no need to tamper with the checksum. For example your changelog file could look something like this:
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet id="your-id" author="msp" runAlways="true">
...
</changeSet>
</databaseChangeLog>
The important part to achieve your intended behaviour is to set the runAlways="true" attribute in your liquibase changeset.

wsimport not working

When I try to use wsimport using the below command from command prompt, it's working fine:
wsimport -d generated C:\Users\generated\wsdlfile.xml
However, when I try to use wsimport as below, it's throwing the following error:
wsimport -d generated https://example.com/exampleService.svc?wsdl
Failed to read the WSDL document: https://example.com/exampleService.svc?wsdl, because 1) could not find the document; /2) the document could not be read; 3) the root element of the document is not <wsdl:definitions>.
[ERROR] failed.noservice=Could not find wsdl:service in the provided WSDL(s): At least one WSDL with at least one service definition needs to be provided.
Failed to parse the WSDL.
I can access the URL from a browser, and the same thing is working from other systems (from my PC). What could be the reason?
I have solved this issue on Windows by disabling all proxy settings as follows:
Internet Options > Connections > Lan Settings > Disable all check boxes
NOTE: Just adding localhost or my IP address as an exception to my proxy settings didn't work for me.
I had this same issue and, in my case, the problem was the encoding of the WSDL file.
Try opening https://example.com/exampleService.svc?wsdl from a browser. If it can be completely parsed, you will see all the xml content. If not, at least Firefox will point you where the problem is.
Hope it helps someone in this situation
This seems to be an issue with the version of java that you are using...
Make sure you have java version "1.7.x" to resolve this issue.
Try setting this option to wsimport: -XdisableSSLHostnameVerification which
Disables the SSL Hostname verification while fetching the wsdls.
use below pom.xml .
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>1.9</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
<configuration>
<!-- Keep generated files -->
<keep>true</keep>
<!-- Package name -->
<packageName>org.example.echo.service.skeleton</packageName>
<!-- generated source files destination -->
<sourceDestDir>src/main/java</sourceDestDir>
<wsdlUrls>
<wsdlUrl>
**http://localhost:8080/soapWebService/services/PersonServiceImpl?wsdl**
</wsdlUrl>
</wsdlUrls>
</configuration>
</plugin>
</plugins>
</build>

Spring Boot Maven Plugin

I have two classes with main method and one loads the security configuration and the other does not. In order to create two artifacts - secure and non secure jars, I am doing something like the following :
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>1</id>
<configuration>
<mainClass>a.b.c.Secured</mainClass>
<finalName>secured</finalName>
<classifier>secured</classifier>
</configuration>
</execution>
<execution>
<id>2</id>
<configuration>
<mainClass>a.b.c.NonSecured</mainClass>
<finalName>non-secured</finalName>
<classifier>nonSecured</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
And I am seeing the exception -
java.lang.IllegalStateException: Unable to find a single main class from the following candidates.
Can you please let me know, if there is some thing wrong with the above configuration? I may be able to use maven profiles to create different artifacts. However, I wanted to understand the problem with the above configuration. Any help will be greatly appreciated.
I think both those configurations are active at the same time (otherwise how do you tell maven which one to use?). You could put them both in Maven profiles.

Does -nexclude work when using JiBX as the CXF databining?

I am trying to get CXF (2.7.7) to use JiBX (1.2.5) for databinding. The documentation is a bit sketchy, but there have been reports of success with it. One problem is that CXF does not pass configuration to the JiBX code generator, so if you need to do something that requires customization, such as mapping Joda DateTime to XML Schema date, you need to be able to tell CXF to ignore specific namespaces and then handle those with a separate call to JiBX.
The examples I have seen use the CXF -nexclude flag for this purpose, as in
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generateSources</id>
<phase>generate-sources</phase>
<goals>
<goal>wsdl2java</goal>
</goals>
<configuration>
<sourceRoot>${generated-sources.dir}/cxf</sourceRoot>
<wsdlRoot>${wsdl.dir}</wsdlRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${wsdl.dir}/GetCounters.wsdl</wsdl>
<dataBinding>jibx</dataBinding>
<extraargs>
<extraarg>-nexclude</extraarg>
<extraarg>http://www.example.com/counters/</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
</execution>
</executions>
</plugin>
I have tried both inline and imported versions of the namespace but the -nexclude flag does not appear to work with JiBX. One option might be to let JiBX do the whole WSDL without invoking the CXF plugin, but apparently this creates problems in the generated service code. An ugly workaround might be to let JiBX regenerate the code for just the classes in this namespace, overwriting the code created by CXF.
Can the -nexclude flag be made to work?
I was having a similar problem while using jaxb. This worked for me:
move the extraargs out of the wsdlOption section and into the defaultOptions section.
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cfx.codegen.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<defaultOptions>
<extraargs>
<extraarg>-nexclude</extraarg>
<extraarg>http://domain.company.org/v1/schema1</extraarg>
<extraarg>-nexclude</extraarg>
<extraarg>http://domain.company.org/v1/schema2</extraarg>
</extraargs>
</defaultOptions>
<wsdlOptions>
<wsdlOption>
<wsdlArtifact>
<groupId>org.company</groupId>
<artifactId>application-contract</artifactId>
<version>${contract.version}</version>
<type>wsdl</type>
</wsdlArtifact>
</wsdlOption>
</wsdlOptions>
<sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>

What does the "default-test" stand for in the maven-surefire plugin

I have defined the following configuration in my pom for surefire with TestNg:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<skipTests>${skip-all-tests}</skipTests>
</configuration>
<executions>
<execution>
<id>unit-tests</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>${skip-unit-tests}</skip>
<groups>unit</groups>
<excludedGroups>integration</excludedGroups>
</configuration>
</execution>
<execution>
<id>integration-tests</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>${skip-integration-tests}</skip>
<groups>integration</groups>
<excludedGroups>unit</excludedGroups>
</configuration>
</execution>
</executions>
</plugin>
But it seems the two executions are always preceded by a "default-test" run which seems to run every #test annotated method (at least I think so).
--- maven-surefire-plugin:2.12:test (default-test) # my-project
For example running "mvn test" on the project, two test executions take place. The "default-test" and the "unit-test".
Could someone explain this a little more to me?
Can this be disabled or controlled (configured what is tested and what not)?
People wanted to have a way to override the default built-in executions of plugins within Maven.
Maven 3 (or it may have been introduced as early as 2.1.0 or 2.2.0) solved this by defining a default execution id for each plugin execution added to the effective pom by the packaging's lifecycle.
The name of this implicit id is always default-_____ I cannot recall the exact rule that it is generated for.
You can therefore override the packaging's injected executions by defining a matching execution.
To solve your case I would either change <id>unit-tests</id> to <id>default-test</id> or
add
<execution>
<id>default-test</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
either will have the same effect, though the <id>unit-tests</id> to <id>default-test</id> solution will be slightly more performant as you only need to invoke two executions of surefire.
The other thing I would point out is you would probably be better off using maven-failsafe-plugin to execute your integration tests as at some point in time you may want to do some stuff pre & post integration testing, and failsafe is designed for that use case (though it should be trivial to switch further down the line)
Alternatively to the Stephen's solution, if you don't want the following message to be displayed in the log (which in fact is a bit misleading since you are not skipping tests):
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) # service-template ---
[INFO] Tests are skipped.
...then go this way:
<execution>
<id>default-test</id>
<phase>none</phase>
</execution>

Resources