Easier way to run a Java application from Maven? - java

If I have understood correctly, I need to type this to run my project from maven:
mvn compile
mvn exec:java -Dexec.mainClass="com.foo.bar.blah.Main"
Is there a way I can make this simpler? Optimally I would like to just do
mvn run

1) Create a new profile called "run" (or another name of your choice)
<profiles>
<profile>
<id>run</id>
2) Set the profile's default goal to "verify" (or you can choose "install", choosing a phase after compile will ensure that the code will automatically be compiled before running the class)
<profiles>
<profile>
<id>run</id>
<build>
<defaultGoal>verify</defaultGoal>
3) Add the exec-maven-plugin to this profile (see this), but configure it to run in the 'verify' phase.
<execution>
<phase>test</phase>
4) You can now run your class using the following:
mvn -Prun

A little more configuration, a little less command line parameters ;-)
using the very same exec:java plugin, you can configure your task in the pom.xml, then execute it in a simpler fashion by mapping your goal to the run step of the lifecycle, like this example shows.

As the above example shows, you can wrap that plugin into a separate profile. Take a look at the 3rd solution

Sadly, no `(as far as I know). If you ahve a web application you could use Jetty plugin to run it doing:
mvn jetty:run
but for standalone apps, you need the exec plugin.

Related

Spring boot doesn't run unit tests

How can I run unit tests for spring boot application while building and deploying using spring boot:run command.
My expectation is to have all my unit tests executed before running application, but I dont want to make another maven command like mvn test before.
My problem:
I made a simple spring boot application and I could'd find a way to run unit tests while running application from intellij or from command line. Firstly I thought that maybe I have wrong configuration or wrong names of test classess or maybe wrong project structure. So I created spring boot application from intellij template. To my happiness it had already default test written so I simply run application. Unfortunatelly test was not executed.
This is a screenshot of project structure, pom.xml, main class and unit test created by intellij.Project created by intetelij
I changed the test runner and test to fail and tried again. Same result.
unit test changed to fail
I googled what is hidden underneath spring boot:run command here
http://docs.spring.io/spring-boot/docs/current/maven-plugin/run-mojo.html
I found something interesting at the top of manual: "Invokes the execution of the lifecycle phase test-compile prior to executing itself." So my understanding is that this command only compiles tests but not run them? If So, the question is - Is it possible to add "test" phase by adding some flag to the command?
Your problem here is to do with the maven lifecycle. According to the docs for the spring-boot:run, it binds to the lifecyle phase validate by default, and invokes the phase test-compile before executing.
What you're asking for is to execute the tests before running the application. You could do this with a custom maven profile in your POM - something like the following.
<project>
<profiles>
<profile>
<id>test-then-run</id>
<build>
<defaultGoal>verify</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>spring-boot-run</id>
<phase>verify</phase>
<goals>
<goal>run</goal>
</goals>
<inherited>false</inherited>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
...
</profiles>
...
</project>
With this in your POM, you could then run the tests and start the app with:
mvn -P test-then-run
This binds the run goal to the verify phase instead of the validate phase, which means that the tests will be run first. You can see which order the phases are run here: https://maven.apache.org/ref/3.3.9/maven-core/lifecycles.html
I knew that I could use mvn test before running application. In fact it can be achieved by many ways in intellij. For me, I just add mvn goal test before launching application:
spring boot configuration in intellij.
But of course it may be done differently.
The thing is, I was just very curious whether I could somehow manipulate spring boot:run command by using some flag or sth else to get same results but its impossible.
olambert, thank You for Your answer too, it works very well.

How can I prevent tests from running during deploy?

currently I have surefire configured though Spring Boot's BOM.
I have tests running during deploy though there seems to be some issue with one of them... that said this same test passes just fine in the previous part of the pipeline. I don't actually need these tests to run twice.
I would like to do this as part of my parent BOM (has springs BOM as its parent)
How can I configure tests to not be run during the deploy phase? mvn deploy, running mvn test and mvn verify must continue to work as normal.
You can achieve this while building(install) the archive itself.
We can skip tests while building by two ways:
Using CLI:
mvn install -Dmaven.test.skip=true
Make the same change in pom.xml as:
<configuration>
<skipTests>true</skipTests>
</configuration>
Then give:
mvn install
Both will build the archive without running the testcases.
And mvn deploy, running mvn test and mvn verify will continue to work as normal. Since this command is independent of these three commands.
You can achieve it by using commands while deploying or in pom.xml
To skip the entire unit test, uses argument -Dmaven.test.skip=true
mvn install -Dmaven.test.skip=true
OR in pom.xml
<configuration>
<skipTests>true</skipTests>
</configuration>
Need to configure in skipTests in surfire plugin
<configuration>
<skipTests>true</skipTests>
</configuration>
For more details please follow
http://maven.apache.org/surefire/maven-surefire-plugin/examples/skipping-test.html

Automatically install a project in the local repository?

I'm trying to work around a maven bug MDEP-187 ( https://issues.apache.org/jira/browse/MDEP-187 ) by not using workspace resolution.
This forces me to do a mvn install for all my dependencies, I'm doing this by creating a launch configuration in eclipse with goal install.
The problem is that i have to create a launch config for every project in my multiproject workspace, in addition to install i have to manually call every launch config and run it. Which just doesn't work.
Is it possible to automatically install a project in the local repository? (whenever i update my code)
If you don't need to run dependency:copy in Eclipse, you can use following work-around:
Add a profile to your pom.xml, something like this:
<profiles>
<profile>
<id>copy</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
[...]
</executions>
</plugin>
</plugins>
<build>
<profile>
</profiles>
Enable workspace resolution in Eclipse.
Then Eclipse will not use dependency:copy, but you can use dependency:copy with command line: mvn install -P copy.
I did go with #khmarbaise solution:
But than you need to can handle the whole thing via
maven-assembly-plugin which can create archives / folders with all the
dependencies. Apart from that a swing ui must be started somehow which
will need some kind of shell script / batch file which you can create
by using appassembler-maven-plugin...And it sounds like you need to go
for a multi module project in maven..cause you might have parts like
core, ui, etc. which are needed to be combined in the end.
#khmarbaise i was in the understanding that the assembly-plugin didn't
support putting dependencies in a lib/ folder (just putting everything
in 1 big jar), but after a little bit of trying i just go myself a zip
with a runnable jar and my dependencies in a lib/ folder. Tomorrow i'm
going to read a bit more about the assembly-plugin. I'm happy ;-

Antlr4 "Test Rig" and maven

I am struggling a little bit to figure out how I can use the antlr4 maven plug in to run the TestRig class?
I've read though the output of mvn antlr4:help -Ddetail=true, which is the only documentation I have been able to find, but this doesn't mention how to use the TestRig. So, what's the recommended way of using the test rig together with maven? using the grun alias method doesn't seem very elegant here.
UPDATED - Reasoning
Hello :)
Right, don't get me wrong but I really don't understand why you wouldn't want this functionality in the maven plugin? And I don't understand why its soul purpose should be to compile grammars?
Currently, if I maintain a build with Maven, and I use the antlr4-maven-plugin , it will install both the plugin and the antlr 4.1 in my maven repository. With this already there, why would I start adding things to my classpath and creating aliases when maven can take care of that? I mean, this is what maven is for really. If I had a antlr4:TestRig goal, then all I would do was use that. No need to manually maintain the class path, or create bash aliases. It would just work.
And be far far more elegant that hard-coding elements from my local maven repository in my class path, and maintaining bash aliases. Or alternatively, maintain two installations per. version of antlr I wish to use (one maintained by me, simply to use TestRig, and one maintained by maven for everything else).
Additionally, if I wanted to use a different version of antlr, then I wouldn't need to update the classpath and my aliases, maven would simply manage all this for me :)
This is how I invoke TestRig with Maven:
mvn exec:java -Dexec.mainClass="org.antlr.v4.runtime.misc.TestRig"
-Dexec.args="<DOT_NOTATION_GRAMMAR_CLASSPATH> <START_RULE>
-gui <INPUT_FILE>"
So if you've got MyGrammar.g4 in src/main/antlr4/com/test/parser with a starting rule of startRule:
mvn exec:java -Dexec.mainClass="org.antlr.v4.runtime.misc.TestRig"
-Dexec.args="com.test.parser.MyGrammar startRule
-gui <INPUT_FILE>"
I had a similar question, in that I wanted to use the TestRig -gui option for debugging my grammar. I didn't find a way to run the GUI via the antlr4-maven-plugin, but I did manage to build a satisfactory CLASSPATH. The key was to include target/classes.
# Assuming your project is in $PROJECT ..
CLASSPATH=".:/usr/local/lib/antlr-4.1-complete.jar:$PROJECT/target/classes"
alias grun='java org.antlr.v4.runtime.misc.TestRig'
mvn -q compile
grun MyGrammer startingRule -gui < test_input
Should produce a lovely GUI view of the syntax tree.
Why would the Maven plugin run the TestRig class? The Maven plugin's job is converting the .g4 grammar files to .java source files in the proper package locations and ensuring those generated files get compiled. TestRig is not used for any part of that.
Edit: I have been using ANTLR for many years, in many applications. In all that time I have never updated my system classpath, nor operated ANTLR/gunit/TestRig from the command line or created aliases for it. Doing so is not helpful for automated testing and inevitably leads users into the problems you described. That said, the thought that TestRig needed special support in the Maven plugin also never crossed my mind, because better solutions already exist.
Some alternatives
You can use the surefire plugin, and write a JUnit test that performs operations on your grammar directly (create a lexer/parser, parse some input, and perhaps even call inspect() on the resulting parse tree.
You can use the surefire plugin, and write a JUnit test that explicitly calls TestRig.main(String[]) with the correct arguments.
You can modify the ANTLR 4 Maven plugin to add a new goal for running TestRig, and submit a pull request to the project to have it included in a future release (you would need to make a very compelling case since there are already 2 alternatives that are more suited to long-term successful testing of a project using ANTLR 4).
I like the idea of using Maven to run the TestRig. But I do not like to add the dependency org.antlr:antlr4 to my code (because I already have org.antlr:antlr4-runtime) so my solution is to configure the exec plugin with an additional dependency.
<properties>
<antlr.version>4.7.1</antlr.version>
</properties>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>TestRigGui</id>
<phase>none</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.antlr.v4.gui.TestRig</mainClass>
<arguments>
<!-- Grammar -->
<argument>de.humanfork.experiment.antlr.Hello</argument>
<!-- start rule -->
<argument>hello_rule</argument>
<!-- enable gui -->
<argument>-gui</argument>
<!-- input file -->
<argument>example.txt</argument>
</arguments>
<includePluginDependencies>true</includePluginDependencies>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>${antlr.version}</version>
</dependency>
</dependencies>
</plugin>
Then use: mvn exec:java#TestRigGui to start the GUI
BTW: in ANTLR 4.7.1 the TestRig main class is: org.antlr.v4.gui.TestRig

How can I test a maven archetype that I've just created?

I've created a few archetypes for a project that work fine for now, but I'd like to be able to verify that the code generated from the archetypes continues to work in the future.
What I'd like is a phase of the archetype build that takes the archetype just created, runs mvn archetype:generate on it, and then runs mvn verify on the generated code to verify that the generated code is actually OK. If need be I'll write my own mojo to do this, but wanted to see if a solution already exists. I see the archetype:integration-test goal, but it doesn't seem to be doing what I want.
UPDATE 2013: This is now much easier than the other answers suggest.
https://issues.apache.org/jira/browse/ARCHETYPE-334 was completed in Aug 2011
To use, simply place the word install inside the goal.txt file mentioned above, and the tests from the project you are archetyping will be invoked as part of a normal build. (And/or verify in the case of OP.)
However, if you new to making archetypes be aware that this popular mini-guide is out of date and, while it will work for making an archetype it will not work for having archetype integration tests run. You should instead be creating an archetype-metadata.xml file as described here. (This is much nicer to work with as well, as it uses file sets!)
Also note these integration tests do not respond to -DskipTests but this can be remedied as follows:
<build>
<plugins>
<plugin>
<artifactId>maven-archetype-plugin</artifactId>
<version>2.2</version>
<configuration>
<skip>${skipTests}</skip>
</configuration>
</plugin>
</plugins>
</build>
(Although this looks like it skips the entire plugin, it actually works, probably because it falls back to a legacy mode; whereas I could not find any successful way to skip just the integration-test goal execution using code above.)
beside the the approach of using the maven-invoker-plugin, we are using a different approach. With the help of the Maven Verifier you can test your maven plugins and archetypes easily.
Just add the following dependency into your pom of your maven test project:
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-verifier</artifactId>
<version>1.2</version>
</dependency>
Now you are able to use
org.apache.maven.it.Verifier
into your normal JUnit Tests. With the verifier you can run maven goals and some assertions about the result.
For a complete example just check out the integration test maven modules of our javascript-archetypes:
https://github.com/akquinet/javascript-archetypes
I was struggling a little with this myself, and figured that when using current v2.3 of the maven-archetype-plugin, in addition to a src/test/resources/projects/first/goal.txt, one also needs a src/test/resources/projects/first/archetype.properties containing something like this:
sourceEncoding=UTF-8
groupId=integrationtest.group
artifactId=integrationtest.artifactId
version=1.0.0-SNAPSHOT
package=org.eclipse.xtend.xtend-archetype.integrationtest
packageInPathFormat=org/eclipse/xtend/xtend-archetype/integrationtest
This pull request illustrates a complete working example.
I see the archetype:integration-test goal, but it doesn't seem to be doing what I want.
Unless I misunderstood what you want, the archetype:integration-test goal seems to be a very good solution:
Execute the archetype integration
tests, consisting of a creation of a
project from the current archetype
with defined properties and optional
comparison with reference copy. An IT
consists of a directory in
src/test/resources/projects
containing:
goal.txt (content actually not used, but future version should interpret it
as a goal to run against the generated
project: see ARCHETYPE-334),
archetype.properties with properties for project generation,
optional reference/ directory containing a reference copy of the
expected project created from the IT.
According to the above description, this goals allows precisely to run Integration Test(s) to check a project generated with the current archetype against an expected result and this looks like a clean, simple, self contained way to test an archetype.
Why is this approach not satisfying? What did I miss?
I guess that would be a scenario for a continuous integration server like hudson.
You'd define a job that
empties a directory (shell script)
creates a new project based on the archetype (mvn archetype:generate)
runs the project (mvn package)
While this could probably somehow be fit into one maven lifecycle, it would feel like an awful mess. Use CI instead.

Categories