Using DB unit to load DEMO data - maven

I'm using the Maven DBUnit plugin to load test data for unit tests. I'd also like to use it for loading a different set of data to a different db for demo purposes. The dbunit plugin only allows for a single execution. Should I just create a separate pom or is there some trick that I can do to make this happen. (I.e., I'd like to simply do something like mvn load-demo-data).

you can execute a plugin several times if you like it depends just on the configuration you give in the pom:
<plugin>
<artifactId>maven-whatever-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>execution1</id>
<phase>test</phase>
<configuration>
....
</configuration>
<goals>
<goal>WhatEverGoalYouHave</goal>
</goals>
<phase>...</phase>
</execution>
<execution>
<id>execution2</id>
<configuration>
....
</configuration>
<goals>
<goal>WhatEverGoalYouHave</goal>
</goals>
<phase>...</phase>
</execution>
</executions>
</plugin>
You can also define a profile to control the execution which might the right choice for your demo data. The call you described mvn load-demo-data is not possible with maven, cause maven calls only a goal or lifecycle.

Use properties when configuring the database credentials
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>dbunit-maven-plugin</artifactId>
<version>${dbunit.plugin.version}</version>
<configuration>
<url>${db.url}</url>
<driver>${db.driver}</driver>
<username>${db.username}</username>
<password>${db.password}</password>
</configuration>
..
Then add a profiles section to your POM, controling the setting of these properties:
<profiles>
<profile>
<id>db1</id>
<properties>
<db.url>jdbc:h2:target/db1;AUTO_SERVER=TRUE</db.url>
<db.driver>org.h2.Driver</db.driver>
<db.username>user</db.username>
<db.password>pass</db.password>
</properties>
<profile>
<profile>
<id>db2</id>
<properties>
<db.url>jdbc:h2:target/db2;AUTO_SERVER=TRUE</db.url>
<db.driver>org.h2.Driver</db.driver>
<db.username>user</db.username>
<db.password>pass</db.password>
</properties>
<profile>
..
The profile cane be activated as follows to update two different databases
mvn -Pdb1 clean test
mvn -Pdb2 clean test

Related

Duplication in maven: are profiles additive to project, or do they replace declared items?

Provided you have the following defined in your POM.xml:
<project>
<!-- ... -->
<build>
<plugins>
<plugin>
<artifactId>plugin-X</artifactId>
<!-- plugin config -->
</plugin>
<plugins>
</build>
<profiles>
<profile>
<id>foo</id>
<build>
<plugins>
<plugin>
<artifactId>plugin-X</artifactId>
<!-- plugin config -->
</plugin>
<plugins>
</build>
<profile>
</profiles>
</project>
If the plugin config for plugin-X is exactly the same for profile foo as it is for a build without a selected profile, do you have to redeclare the plugin at all on the profile level? If so, do you also have to redeclare all config settings for it?
If you declared plugin-Y in project.profile.build.plugins instead of plugin-X (but left it declared on the project level), which plugins would be run when you run mvn -P foo? Only plugin-Y, or also plugin-X?
More generally speaking, are profiles additive to what is declared on the project level, or do they override it? (If they are additive, how do you "remove" entities that were declared on a project level when you run a build profile and don't want them for that specific profile?)
I know profile configuration gets inherited from parent pom files ("from either the build/plugins or pluginManagement sections of the parent") with options "merge", "append", and "override". I think what I really want to know is: how does maven behave when the same/similar information is defined on the project and profile levels in the same pom file...
This isn't a full answer, but another piece of the puzzle - in addition to my earlier comments, and maven's Guide to Configuring Plug-ins.
Given the following pom.xml file:
</profiles>
<properties>
<foo>main</foo>
<bar>main</bar>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>validate</phase>
<configuration>
<target>
<echo>${foo}</echo>
<echo>${bar}</echo>
<echo>${baz}</echo>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>p</id>
<properties>
<bar>prof</bar>
<baz>prof</baz>
</properties>
</profile>
</profiles>
</project>
When I run mvn validate, I get the following output:
[echo] main
[echo] main
[echo] ${baz}
Running mvn validate -P p however yields:
[echo] main
[echo] prof
[echo] prof
That means that properties at least are merged, appending new items and replacing those that are redefined.
Also, if I add another plugin to the profile (such as surefire), it will execute when running the profile with mvn <phase> -P p, so the profile inherits antrun and adds surefire. Plugin re-definitions however replace the original; adding
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>validate</phase>
<configuration>
<target>
<echo>Tada!</echo>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
only prints Tada!, but no longer the original antrun output (even when changing the new addition's phase to initialize. Adding <inherited>true</inherited> to any of the two plugin definitions doesn't make a difference. The behaviour might be plugin-specific, though.

How can I specify the path in tomee-maven-plugin such that both deploy and undeploy works?

I'm trying to build a pom.xml to handle the deployment and undeployment to a remote TomEE (PluME 7.0.3) server. However, I cannot figure out the correct value to use in the path configuration tag. Here's a working plugin configuration for deploying my application (full-blown EAR, for educational purposes) to the remote TomEE:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>7.0.3</version>
<configuration>
<context>someear</context>
<tomeeClassifier>plus</tomeeClassifier>
<tomeeHost>192.168.100.100</tomeeHost>
<debugPort>8000</debugPort>
<tomeeAjpPort>8009</tomeeAjpPort>
<tomeeHttpPort>8080</tomeeHttpPort>
<tomeeShutdownPort>8005</tomeeShutdownPort>
<path>target/someear-1.0-SNAPSHOT.ear</path>
<useBinaries>true</useBinaries>
</configuration>
</plugin>
</plugins>
</build>
Whereas to undeploy, I would have to configure the plugin like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>7.0.3</version>
<configuration>
<context>someear</context>
<tomeeClassifier>plus</tomeeClassifier>
<tomeeHost>192.168.100.100</tomeeHost>
<debugPort>8000</debugPort>
<tomeeAjpPort>8009</tomeeAjpPort>
<tomeeHttpPort>8080</tomeeHttpPort>
<tomeeShutdownPort>8005</tomeeShutdownPort>
<path>someear-1.0-SNAPSHOT</path>
<useBinaries>true</useBinaries>
</configuration>
</plugin>
</plugins>
</build>
Notice the difference in the path configuration. From the command line, this behaves similarly; when the path tag in the pom.xml is omitted, I can deploy and undeploy like this:
mvn tomee:deploy -Dtomee-plugin.archive=target/someear-1.0-SNAPSHOT.ear
mvn tomee:undeploy -Dtomee-plugin.archive=someear-1.0-SNAPSHOT
Has anybody experienced the same behaviour, and found a way to mitigate this? I'd like to have both deploy and undeploy configured completely in the pom.xml without specifying additional parameters when calling mvn. But, as of now, I cannot do that, since tomee:deploy seems to expect a different path than tomee:undeploy.
EDIT
Ok, based on #Old School's edited answer, I can do something like this:
<profiles>
<profile>
<id>deploy</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<my-tomee-maven-plugin-path>target/someear-1.0-SNAPSHOT.ear</tomee-maven-plugin-path>
</properties>
</profile>
<profile>
<id>undeploy</id>
<properties>
<my-tomee-maven-plugin-path>someear-1.0-SNAPSHOT</tomee-maven-plugin-path>
</properties>
</profile>
</profiles>
Then, specify path in tomee-maven-plugin's configuration section like this:
...
<path>${my-tomee-maven-plugin-path}</path>
...
Then, execute maven like this:
mvn tomee:deploy
mvn tomee:undeploy -Pundeploy
Which I consider more convenient than specifying some -D parameters at execution time (YMMV).
However, the perfect solution in my opinion would be if you could configure path in tomee-maven-plugin's configuration such that both tomee:deploy and tomee:undeploy work without further ado.
EDIT2
I discovered another possibility without profiles which I was seemingly unable to find before (based on: http://tomee-openejb.979440.n4.nabble.com/Deployment-to-TomEE-7-0-0-using-tomee-maven-plugin-error-Cannot-open-input-stream-to-server-tp4679142p4679282.html):
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>7.0.3</version>
<configuration>
<context>${project.artifactId}</context>
<tomeeClassifier>plus</tomeeClassifier>
<context>someear</context>
<tomeeClassifier>plus</tomeeClassifier>
<tomeeHost>192.168.100.100</tomeeHost>
<debugPort>8000</debugPort>
<tomeeAjpPort>8009</tomeeAjpPort>
<tomeeHttpPort>8080</tomeeHttpPort>
<tomeeShutdownPort>8005</tomeeShutdownPort>
<!-- no <path> tag -->
<useBinaries>true</useBinaries>
</configuration>
<executions>
<execution>
<id>deploy-it</id>
<phase>none</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<path>target/someear-1.0-SNAPSHOT.ear</path>
</configuration>
</execution>
<execution>
<id>undeploy-it</id>
<phase>none</phase>
<goals>
<goal>undeploy</goal>
</goals>
<configuration>
<path>someear-1.0-SNAPSHOT</path>
</configuration>
</execution>
</executions>
</plugin>
Usage:
mvn tomee:deploy#deploy-it
mvn tomee:undeploy#undeploy-it
I use glassfish, not tomcat, but I think the same principles apply here. In GF, deploy requires the full path and the undeploy requires only the package name. For example, glassfish goes something like:
asadmin deploy C:\Projects\Java\helloworld\helloworld.war
and
asadmin undeploy helloworld
There is no path required on undeploy because the file is on the server and once you name it, glassfish/tomcat knows where it is.
EDIT based off comments: My apologies for the glassfish stuff, I wasn't paying attention to you mentioning tomcat and I've edited a bit to reflect that somewhat.
I do understand now, I think, what you're looking for. Check out:
Maven Resource Filtering
It's another SO answer where he does a fantastic job of explaining exactly what you're looking for, I think. I hope that works.

maven release:prepare junit

I have a need to only run a specific jUnit when the mvn release:prepare is executed. I don't want this to run under mvn install or any other goal as this jUnit is designed to see if the developer has executed a database activity first.
Is there any way to either have the junit know, by parameter(?), that the process under execution is release:prepare?
Or, is there a way to define within the pom.xml that this jUnit only runs on that goal?
I've been doing some searching on this and I cannot seem to find a solution as I'm not that good at maven as of yet. Any help is appreciated!
I haven't done exactly what you want but the key is to use the <executions> section under the SureFire :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
... exclude the test from normal execution ...
</configuration>
<executions>
<execution>
<id>release-phase</id>
<phase>release-prepare</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
... fill this in to include the tests you want ...
</configuration>
</execution>
</executions>
<plugin>
You will also want to exclude that test in the normal <configuration> section.
There is some related information HERE
Others are close... but no cigar.
When Maven runs a release, there are no special phases for the release process. What you want to do is add a profile that is configured to include the test you want, e.g.
<profiles>
<profile>
<id>release-preflight-checks</id>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>release-preflight-checks</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
.. include your test here
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Then you need to configure surefire by default to not execute your preflight check
<build>
<plugins>
...
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
.. exclude your test here
</configuration>
</plugin>
...
</plugins>
</build>
And then finally, you need to tell Maven that this profile should be active only during release:prepare's forked execution
<build>
<plugins>
...
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
...
<preparationGoals>clean verify -P+release-preflight-checks</preparationGoals>
...
</configuration>
</plugin>
...
</plugins>
</build>
Note: it is vitally important to have the + in front of the profile name so that you are adding the profile to the list of active profiles otherwise your release:prepare step will not be validating that the build works with the release profile active and you can have a subsequent release:perform fail.
Note: A less complex route would be to just put the surefire configuration into the release profile that you are using (by default that has the id of release but that is more error prone as you could change that via the parent pom - e.g. if you decide to push your project to central, the sonatype-oss-parent changes the release profile to sonatype-release - and then you won't see the build being failed as the test would not be executed until you change your pom to match new the release profile's id... using the -P+release-preflight-checks ensures that the profile is always active for release:prepare and additionally has the benefit of meeting the requesters original requirement completely - i.e. only runs for release:prepare and doesn't run for release:perform which would be the case if the execution was added to the release profile)

Configuring Javadoc aggregation in Maven

I'm trying to create an aggregate Javadoc site for all the modules in my project, but I can't seem to configure the plugin in a way that is satisfactory. Mainly, I can't seem to get it to aggregate the javadocs all the while detecting links and excluding certain packages. Essentially, it appears the configuration of the plugin is ignored entirely.
I have a root pom.xml that refers to a bunch of submodules and contains the following configuration:
<modules>
<module>foo</module>
<module>bar</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.maven.apache.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>aggregate</id>
<phase>site</phase>
<goals>
<goal>aggregate</goal>
</goals>
<configuration>
<links>
<link>http://docs.oracle.com/javase/6/docs/api</link>
<link>http://static.netty.io/3.5/api</link>
<link>http://google-guice.googlecode.com/git/javadoc</link>
<link>http://docs.guava-libraries.googlecode.com/git-history/release/javadoc</link>
<link>http://fasterxml.github.com/jackson-databind/javadoc/2.0.4</link>
<link>https://developers.google.com/protocol-buffers/docs/reference/java</link>
</links>
<bootclasspath>${sun.boot.class.path}</bootclasspath>
<additionalJOption>-J-Xmx1024m</additionalJOption>
<detectJavaApiLink>true</detectJavaApiLink>
<detectLinks>true</detectLinks>
<excludePackageNames>*.testing.*</excludePackageNames>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
But when I run mvn javadoc:aggregate with this setup, I end up with a javadoc site that has no links to any of the referenced libraries and still includes all the testing classes.
I don't even see the plugin attempting to download the package-list for each declared link source.
On the other hand, generating the javadoc for each individual module works well and as expected.
What am I getting wrong?
Plugin configurations can be placed on two levels; inside the execution tag or outside of it ("global").
When the configuration is inside the execution tag it belongs to that particular execution. In your case you will have to run mvn site for it to execute since it is bound to that phase.
When the mvn javadoc:aggregate command is used it looks for the "global" configuration. In your pom there is no such configuration and thus it uses the default configuration.
Change your plugin configuration to this instead:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration>
<links>
<link>http://docs.oracle.com/javase/7/docs/api</link>
<link>http://static.netty.io/3.5/api</link>
<link>http://google-guice.googlecode.com/git/javadoc</link>
<link>http://docs.guava-libraries.googlecode.com/git-history/release/javadoc</link>
<link>http://fasterxml.github.com/jackson-databind/javadoc/2.0.4</link>
<link>https://developers.google.com/protocol-buffers/docs/reference/java</link>
</links>
<bootclasspath>${sun.boot.class.path}</bootclasspath>
<additionalJOption>-J-Xmx1024m</additionalJOption>
<detectJavaApiLink>true</detectJavaApiLink>
<detectLinks>true</detectLinks>
<excludePackageNames>*.testing.*</excludePackageNames>
</configuration>
<executions>
<execution>
<id>aggregate</id>
<phase>site</phase>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
You can place a configuration inside the execution part to override and specialize the configuration for that execution.
BTW The <groupId> is wrong in your pom. It should be
<groupId>org.apache.maven.plugins</groupId>
and not
<groupId>org.maven.apache.plugins</groupId>

Plugin.xml configuration of phase doesn't seem to work for my custom maven plugin

I'm playing around with writing a maven plugin for the first time. I've written a simple plugin with a goal that writes a hello world message to the output. I've also used the #phase annotation to create a default binding to the install lifecycle phase. This shows up in my plugin.xml as install element of my mojo element.
My understanding is that I can now simply add this to my build.plugins section, without specifying any execution, and my plugin goal will execute during the install phase. This doesn't happen though. Here's the configuration that doesn't create any exeuction of my goal:
<build>
<plugins>
<plugin>
<groupId>com.emc.chad</groupId>
<artifactId>hello-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
</plugin>
</plugins>
</build>
However, if I change this to specify an execution explicitly, it works:
<plugin>
<groupId>com.emc.chad</groupId>
<artifactId>hello-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<id>test</id>
<phase>install</phase>
<goals>
<goal>hello</goal>
</goals>
<configuration>
</configuration>
</execution>
</executions>
</plugin>
I understand why this works of course, but shouldn't the first work as well, considering my plugin.xml phase specification?

Resources