Run Integration tests isolated from each other - maven

is there a way to run integration tests independently?
I got a few selenium tests (reworked in java) in "integration" group, in pre-integration-test phase tomcat runs the webapp and in post-integration-test it shuts down. But the problem is I need the tests to be independent on each other. For example when first test runs, it creates a few posts here and there. I need to reset the webapp (clean everything that the first test did) before running the second test (on a default webapp). All of this needs to be automatic...
Here's my failsafe plugin config from pom.xml.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19</version>
<configuration>
<groups>integration</groups>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
And this is the part with the integration phases and tomcat init...
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.190</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>tomcat-run</id>
<goals>
<goal>run</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<webapps>
<webapp>
<groupId>...webapp...</groupId>
<artifactId>...webapp...</artifactId>
<version>${webapp.version}</version>
<type>war</type>
<asWebapp>true</asWebapp>
<contextPath>/</contextPath>
</webapp>
</webapps>
<fork>true</fork>
<port>${tomcat.port}</port>
</configuration>
</execution>
<execution>
<id>tomcat-shutdown</id>
<goals>
<goal>shutdown</goal>
</goals>
<phase>post-integration-test</phase>
</execution>
</executions>
</plugin>

Unfortunately I do not know of any tools out there that simplifies this and a solution will be very specific to the technologies your using (e.g. Tomcat/Jetty/etc., Jersey/Spring/etc., H2/MySQL/etc., etc.) but here are two options:
Do setup/teardown of your web-app from your Java code using a Tomcat Container Java API (instead of using a Maven plugin, e.g. Cargo supports Tomcat and has a Java API (start here although I doubt this will be easy but probably worth it)). This will let you use Before/After methods to set-up and tear-down web-apps on the fly and give you the control you're looking for (you might reuse the same web-container and just reinstall the app, reinitialize the database, etc. or you might tear everything down and start over, your call). This may even allow you to run multiple instances of your web-app at once (assuming you can do this with app) and then run integration tests independently in parallel.
Use the maven plug-in to install multiple instances of your app accessible from different base urls and/or ports.

Technically you'd need to add multiple executions each of which would need to restart app server, deploy the app and run the tests. Which you won't be able to do by standard Maven means. Though you always can write your own plugin.
The issue with your approach though is that it's very complicated (as you already noticed) and very ineffective since you'd need to do multiple deployments. I'd advice to change the approach, here are some suggestions:
Randomize data to isolate tests. In most cases it's possible to prepare and randomize data for tests. E.g. if you create posts on behalf of some user, you can create that user (with random name) for that particular test and create a randomly generated post. This way 2 tests will be isolated from each other. It's not always possible (e.g. you test global configuration of the app), but in 99% of cases it is.
Don't write many System Tests that require real deployment (like those that use Selenium). In most cases it's enough to write Unit tests or Component Tests. E.g. initialize several Spring contexts (or whatever DI you use) and test services/controllers directly. A lot of REST or MVC frameworks have ability to invoke services/controllers directly without real deployments (e.g. Spring MVC has MockMvc). If you still want to deploy the app in tests consider Arquillian instead of Tomcat, but it's still going to be slow. The only case where you need real deployment is when you want to test UI - that requires a full blown app server and browsers.
In general to get testing optimal and isolated you need to build a Test Pyramid where you've got a plenty of unit tests, many component tests and a small number of system tests (which are hard to isolate and take a lot of efforts anyway). See in this article how you can do this in Java apps.

Related

Is it possible to run in parallel mode integration tests written in Spock Framework for Spring Boot

Base Spock specification is:
#SpringBootTest(classes = ApplicationTestConfig.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#TestPropertySource("/application.properties")
abstract class SpringBootTestSpecification extends Specification {
Project is building by maven 3.3.9 with failsafe-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<id>integration-tests</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<skip>false</skip>
<includes>
<include>**/*SpecIT.java</include>
</includes>
<argLine>-Dfile.encoding=UTF-8</argLine>
</configuration>
</execution>
</executions>
</plugin>
I want to run my test in parallel mode but I want to be sure that one won't affect others (application runs with embedded DB and prepares different data for different tests).
If the embedded DB would be the same (same file / url / name) for every test, even though it probably gets truncated or recreated, parallelize the tests might not work as expected as one test might be running while another might attempt to reseed the data.
If somehow each test connects to a unique DB, my guess is that tests could be parallelized.
http://maven.apache.org/components/surefire/maven-failsafe-plugin/examples/fork-options-and-parallel-execution.html
Make sure JUnit4 is configured to parallelize them by method, class, etc..
And if you feel curious, a few months ago I published a blog post Integration Testing using Spring Boot, Postgres and Docker where each test connects to a Postgres DB running in a different container. I don't remember covering running the tests in parallel but that would be doable.

Integration testing with client server application in Maven multi-modules project

I have a project composed of several modules that uses maven and is automatically uploaded and deployed to a Jenkins application that runs the build and its tests.
There is for example an API module, a server and a client.
Both client and server use the API as dependency to be able to work correctly.
The client connects to the server's web-services through HTTP(s) in normal use.
To be able to function, the server needs to be run on Jetty.
I have unit testing that works and test the client by calling the server's functionality with mocked HTTP requests.
I would like to be able to do some integration testing, to test for example the HTTP (and HTTPS) connection between the 2 entities, testing for timeouts and such, and reproducing the unit testing without resorting to mocked request, to be closer to real use cases.
It seems like such a thing should be easy to do, but I can't find a way to do it simply and in a way that could be automated.
For example, testing manually in my IDE is done by clicking on "run war" on the server project, and "run tests" on my application.
Is there a way to reproduce this simple process in Jenkins so it is done automatically, by Maven configuration or even a Jenkins plugin ?
UPDATE :
I'm trying to make another module that would use the war resulting from the packaging of my server, and run it with Jetty.
Since my server's Jetty configuration is quite complicated, using Spring and https configuration filtered by Maven, I've some problems making it work in my new module because of missing classes and relative paths not working in that context.
Is it possible to run that war like it would have been started in the other module without jumping through hoops of duplicating resources and other dirty tricks ?
For information, the specific Jetty war part of my pom.xml is :
<configuration>
<contextHandlers>
<contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext">
<war>${project.parent.basedir}/cmp-service/cmp-webapp/target/cmp-webapp-1.0-SNAPSHOT.war</war>
<contextPath>/cmp</contextPath>
<persistTempDirectory>true</persistTempDirectory>
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
</contextHandler>
</contextHandlers>
</configuration>
UPDATE 2 :
I managed to build a functioning module that starts jetty and run my integration test with this pom.xml.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>com.project.test</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.project.test.integration-testing</groupId>
<artifactId>integration-testing</artifactId>
<packaging>jar</packaging>
<name>integration-testing</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.0.M2</version>
<configuration>
<contextHandlers>
<contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext">
<war>
${project.parent.basedir}/myserver/myservice/target/myservice-${project.parent.version}.war
</war>
<contextPath>/cmp</contextPath>
<persistTempDirectory>true</persistTempDirectory>
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
</contextHandler>
</contextHandlers>
<contextXml>
${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty-context.xml
</contextXml>
<jettyXml>
${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty.xml,${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty-ssl.xml,${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty-http.xml,${project.parent.basedir}/myserver/myservice/src/test/resources/jetty/jetty-https.xml
</jettyXml>
<systemProperties>
<systemProperty>
<name>scsf.configuration.file</name>
<value>
${project.parent.basedir}/myserver/myservice/src/main/resources/config/cmpserver.properties
</value>
</systemProperty>
<systemProperty>
<name>org.eclipse.jetty.annotations.maxWait</name>
<value>180</value>
</systemProperty>
</systemProperties>
<systemPropertiesFile>
${project.parent.basedir}/myserver/myservice/src/main/resources/config/cmpserver.properties
</systemPropertiesFile>
<daemon>true</daemon>
<stopKey>STOP</stopKey>
<stopPort>10001</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
...
</dependencies>
</project>
You need to add the dependency to your war as provided too.
But (there's always a but) there is a problem when running the verify goal.
When I run verify in my integration-test module, it kind of works.
But when I run the verify goal in the parent, which is supposed to call that exact same verify goal of my integration-test module (if I understand correctly how it works), some paths are treated differently and are resolved as, for example, parent/src/... instead of parent/integration-test/src...
It seems that when running my goal from the parent, the context of the execution changes and causes my application to break when looking for resources and such.
Is there something I didn't understand about how the whole process works and is there a way to make it work ?
UPDATE 3
I've resolved to hack my way into making all my paths into absolute paths, it works, but it doesn't explain that behavior.
You already figured out the basic steps yourself:
create a separate module for integration tests
start an application- or web-server (e.g.jetty) via a suitable maven-plugin (e.g. cargo, wildfly-maven-plugin, etc.) in the pre-integration-test phase
run tests via the maven-failsafe-plugin:integration-test mojo
verify results via the maven-failsafe-plugin:verify mojo
Stephen Connolly, a maven developer, already wrote a great answer about this topic on stackoverflow.
I don't know the jetty-maven-plugin very well, but it seems it doesn't support deploying an existing artifact. Specifying relative or absolute path is definitively not the way to go here. You should probably use cargo instead to deploy to jetty. The cargo configuration could look like this:
<configuration>
<configuration>
<type>runtime</type>
<properties>
<cargo.hostname>testserver</cargo.hostname>
<cargo.servlet.port>8080</cargo.servlet.port>
</properties>
</configuration>
<container>
<containerId>jetty9x</containerId>
</container>
<deployables>
<deployable>
<groupId>your.group.id</groupId>
<artifactId>your-war</artifactId>
<type>war</type>
<properties>
<context>/cmp</context>
</properties>
</deployable>
</deployables>
<deployer>
<type>remote</type>
</deployer>
</configuration>
The cargo documentation has more details.
hth,
- martin
Hello Jay,
Would really like to simplify things in here, why don't you run these jobs in succession? First would be your compile, unit-tests and deploy tasks using Maven. For your integration testing, create another job that would use of plugins like Selenium ( for your web application) and JMeter (for your web services). You can also try other license testing suite like Openscript.
The web service testing will be tricky, since your web service consumer runs on another client. Do you have any slave agents running on the client application? If you have one, run those jobs inside the slave.

Maven - deploy webapp to tomcat before JUnit test

I have webapp which provides web service. I want to perform JUnit tests with SoapUI to check if this service is working properly.
But to test web service application has to be deployed to my Tomcat 7 server.
I have no idea how to configure maven to build war, then deploy it to tomcat (ideally: to run separate tomcat instance for this) and then to run JUnit tests.
I will appreciate any help.
I am using maven 2.2.1
There are a number of schools of thought as to how to handle this type of integration test with Maven.
I should point out that when you are deploying an application to an application server, you are not in the realm of unit testing any more. Because the entire application is being deployed within a container, you are testing the integration of those two components.
Now there is nothing wrong with using JUnit for running integration tests (though there are some limitations that you may hit, for example unit tests should not care about the sequencing of individual tests - assuming you are writing them correctly - so JUnit enforces this by not guaranteeing any sequence of execution... prior to Java 1.7 the execution order was accidentally implied by the order of test methods within a class, but it was not part of the JUnit contract... Some people switch to other testing frameworks for their integration tests, e.g. TestNG, if they find the unit test focus of JUnit is getting in the way of their test development)
The key point to keep in mind is that the Maven lifecycle uses the test phase for the execution of unit tests.
When it comes to integration tests there are two (and a half) schools of thought as to the right way to handle the tests with Maven.
School 1 - Failsafe and integration-test/verify
This school of thought uses the phases after package to start up a container, run the integration tests, tear down the container, and finally check the test results and fail the build in the event of test failures.
NEVER EVER RUN mvn integration-test as that will not tear down the container correctly, any time you think you want to type mvn integration-test you actually want to type mvn verify (oh look, it's shorter and easier to type also... bonus)
So with this you do the following:
Bind tomcat7:run to the pre-integration-test phase with fork=true
Bind failsafe:integration-test to the integration-test phase
Bind tomcat7:shutdown to the post-integration-test phase
Bind failsafe:verify to the verify phase.
For extra brownie points you would use build-helper-maven-plugin:reserve-network-port bound to the validate phase to ensure that the test server is started on an unused network port and then either use resource filtering against the test resources to pass the port through to the tests or use a system property passed through systemPropertyVariables to make the port number available to the tests.
Advantages
Clean Maven build
If the tests fail, you cannot release the project
Can move the integration tests into a separate profile (by convention called run-its) if the tests are too slow to run every build.
Disadvantages
Hard to run the tests from an IDE. All the integration tests start/end in IT and while Maven knows to run tests starting/ending in Test with Surefire and run tests starting/ending in IT with Failsafe, your IDE probably doesn't. Additionally, your IDE is not going to start the container for you, so you have to do a lot of work by hand to actually run the tests manually.
Debugging the tests potentially requires attaching two debuggers, e.g. one to debug the application running in container and the other to debug the test cases.
mvnDebug -Dmaven.failsafe.debug=true verify
Couples your tests to the Maven build process.
School 2 - Separate module
This school of thought moves the integration tests into a separate module that depends on the war module and copies the war into the test resources using, e.g. dependency:copy-dependencies bound to the generate-test-resources phase coupled with a Tomcat7 dependency to test against.
The test cases themselves start up the Tomcat7 container using embedded mode
Advantages
Tests can run in IDE
Integration tests are separated from Unit tests, so asking the IDE to run all tests will not kick off the slower tests
Disadvantages
The war artifact is only rebuilt if you go past the package phase, consequently, you need to run at least mvn clean package periodically to refresh the code under test when using the IDE.
The failure of the integration tests does not break the build of the war module, so you can end up releasing a broken war artifact and then have the reactor build fail for the integration test module. Some people counteract this issue by having the integration test module within src/it and using Maven Invoker Plugin to run the tests... though that provides a poorer IDE integration, so I do not recommend that line.
Hard to get a consolidated test coverage report from Maven.
Have to code the container start/stop yourself from within your test cases.
School 2.5 - Failsafe with the test cases starting their own Tomcat7 server
This is a kind of hybrid of the two approaches.
You use Failsafe to execute the tests, but the tests themselves are responsible for starting and stopping the Tomcat7 container that you want to test in.
Advantages
Don't have to configure the server start/stop in Maven pom
IDE can safely run all tests (though the integration tests may be slower and you may want to not run them, but it's not like they will all fail unless there is a test failure)
Easier to debug the tests from your IDE (only one process to attach against, and the IDE usually makes it easy to debug tests by providing a special test runner)
Disadvantages
Have to code the container start/stop yourself from within your test cases
I hope the above helps you understand the options you have. There may be other tweaks but in general the above are considered the best practice(s) for integration testing with Maven at present.
#Stephen Connolly - your answer above was really good. I thought I'd kick in and show a full configuration for what you termed a School 1 response.
This configuration:
runs unit tests separately from integration tests. It uses the #Category annotation on the root classes that unit tests and integration tests extend.
before integration tests it starts the dependent application (loaded as a maven dependency at runtime) on the local machine, by finding an open port
after integration tests it tears down the dependent application
There's other stuff in there like how to set certain system properties on the dependent application only.
So far this configuration is working awesome..
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>reserve-network-port</id>
<goals>
<goal>reserve-network-port</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<portNames>
<portName>tomcat.maven.http.port</portName>
</portNames>
</configuration>
</execution>
<execution>
<id>get-local-ip</id>
<goals>
<goal>local-ip</goal>
</goals>
<configuration>
<!-- if not given, 'local.ip' name is used -->
<localIpProperty>local.ip</localIpProperty>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- http port from reserve-network-port-plugin-->
<port>${tomcat.maven.http.port}</port>
<!-- application path always starts with /-->
<path>/</path>
<webapps>
<webapp>
<groupId>com.company.other.app</groupId>
<artifactId>web-rest</artifactId>
<version>1.0.1-SNAPSHOT</version>
<type>war</type>
<contextPath>/webapi-loopback</contextPath>
<asWebapp>true</asWebapp>
</webapp>
</webapps>
</configuration>
<executions>
<execution>
<id>start-server</id>
<configuration>
<fork>true</fork>
<skip>${skipTests}</skip>
<systemProperties>
<spring.profiles.active>test,h2</spring.profiles.active>
</systemProperties>
</configuration>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>stop-server</id>
<configuration>
<skip>${skipTests}</skip>
</configuration>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<configuration>
<excludedGroups>com.company.app.service.IntegrationTestRootClassAnnotatedWithAtCategory</excludedGroups>
</configuration>
<executions>
<execution>
<id>unit-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<argLine>-Xmx1024m -XX:MaxPermSize=256m #{jacocoArgLine}</argLine>
<excludedGroups> com.company.app.service.IntegrationTestRootClassAnnotatedWithAtCategory </excludedGroups>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.18</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>start-integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<argLine>-Xmx1024m -XX:MaxPermSize=256m #{jacocoArgLine}</argLine>
<groups>com.company.app.IntegrationTestRootClassAnnotatedWithAtCategory</groups>
<includes>
<include>**/*.java</include>
</includes>
<systemPropertyVariables>
<program.service.url>
http://${local.ip}:${tomcat.maven.http.port}/webapi-loopback
</program.service.url>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
As Stephen Connolly explains there is no a direct way to configure this. I will explain how to solve this using failsafe plugin. In the maven lifecycle type of test can be tested. Unit testing one of them and another one is integrate testing. Unit testing can be run in the test stage of maven lifecycle. When you want to do integrate test it can be done in verify stage. If you want to know the difference between unit testing and integrate testing, this is a good one. By default unit test classes should be in ***/*Test.java, and **/*TestCase.java this format. The failsafe plugin will look for **/IT*.java, **/*IT.java, and **/*ITCase.java.
Here is an example.
Here I have one unit test class and one integrate test class. Now I will explain, how should be the looks like maven pom.xml. Build section of maven configuration should look like this.
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
<warName>${name}</warName>
<outputDirectory>/home/jobs/wso2/wso2as-5.3.0/repository/deployment/server/webapps</outputDirectory>
<goal>
</goal>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.12.4</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Unit tests are run before deploying the web app(war file). But integrate tests are run in verify stage. I hope your requirement is satisfied in this stage.

Changing when maven runs integration tests

We have unit tests (mockito) and integration tests (in-memory database)
We'd like maven to not run the integration tests as part of 'mvn install'.
Basically I think this means reconfiguring the lifecyle so that integration-test
comes between install and deploy. Is this possible?
The reason for this would be that the integration tests are somewhat time consuming
and so we don't want them to run every time a developer does an install. But we would
like them to be run before the project can be released, for example.
Check the docs for the plugin you use for running integration tests (possibly Failsafe) - simply exclude the tests, or set the plugin execution to false.
Does integration-tests just execute a single plugin (like surefire)? If so, it is probably easier to just bind the plugin execution to a different phase:
<project>
...
<build>
<plugins>
<plugin>
...
<executions>
<execution>
<id>execution1</id>
<phase>install</phase>
<configuration>
...
</configuration>
<goals>
<goal>test</goal>
</goals>
</execution>

Jboss Maven JdocBook Plugin, Multiple Executions

My team is working on a webservice project, and I am working on creating the documentation for the web service API. I have used a custom JavaDoc doclet to create two xml outputs of the available methods, one for internal developers and one for external developers.
Now, we are using the Jboss Maven Jdocbook plugin to create a DocBook output, along with other xml files, to create a users guide for our webservices.
What I want to do is run the Maven JdocBook plugin twice, once using the internal methods and once on the external methods, to create two separate users guides for either internal or external developers, using two different master.xml files. The pom file:
<build>
<defaultGoal>generate</defaultGoal>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<extensions>true</extensions>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<formats>
<format>
<formatName>html</formatName>
</format>
<format>
<formatName>html_single</formatName>
</format>
</formats>
</configuration>
<executions>
<execution>
<id>internal</id>
<phase>compile</phase>
<configuration>
<baseOutputDirectory>../../Test/JavaDocTest/internal/</baseOutputDirectory>
<sourceDocumentName>masterInternal.xml</sourceDocumentName>
</configuration>
</execution>
<execution>
<id>external</id>
<phase>compile</phase>
<configuration>
<baseOutputDirectory>../../Test/JavaDocTest/external/</baseOutputDirectory>
<sourceDocumentName>masterExternal.xml</sourceDocumentName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-style-plugin</artifactId>
<version>1.0.0</version>
<extensions>true</extensions>
</plugin>
</plugins>
The problem I am running in to is that unless I put the sourceDocumentName in the base configuration (outside of the execution section and in the section with the formats) the build does not recognize the different source document name. The standard master file is called master.xml, and on compiling in NetBeans, it says it is looking for master.xml, which it can't find because it does not exist, and then skips the generation.
It is appearing to just skip the execution sections altogether, as when I try to run the build with multiple executions (such as above) it still just runs once. Any ideas why it's skipping the execution sections?
I believe it might have something to do with the phase tag of the execution, but according to http://www.jboss.org/maven-jdocbook-plugin/ there are only a few phases (process-resources, compile, package, install, deploy), and I've tried all of them and none of them seem to work.
Thanks in advance.
My group figured out that you need to set sourceDocumentName in the main configuration area. It turns out that the docbook is generated once using the main config section, and then it looks for any other executions and runs those using the specific sub-configuration for that execution.
Hope this helps someone in the future.

Resources