How to send out email notification for Maven build - java

Is there a simple way to send out email notifications in Maven for each build without outside CI tools, just like Ant?

If CI is not an option I would use a simple script wrapper:
mvn install 2>&1 | tee build.log && cat build.log | mail -s 'Maven build output' user#example.com && rm -f build.log
If you do decide to use a CI tool, I would strongly recommend Hudson. The installation page shows how easy it is to run. Continuous integration server sounds pompous and enterprisey, but Hudson is dead-simple.

I'd strongly recommend using a CI tool to manage this for you, I personally like to configure which emails are to be sent on the build to avoid spamming. For example only notify when the build starts failing, or starts working again, not on every failure.
If you're sure this is the right approach, you can use the maven-changes-plugin to send an email on each build. You can customise the mail template with velocity, and bind the execution of the goals to an appropriate phase so it is sent when you want it.
I'd also put the configuration in a profile so it is sent when you want it to be (i.e. when the profile is active).
The configuration looks something like this:
<profiles>
<profile>
<id>notify</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-changes-plugin</artifactId>
<executions>
<execution>
<!--send an email in the install phase,
could be changed depending on your needs-->
<phase>install</phase>
<goals>
<goal>announcement-mail</goal>
</goals>
</execution>
</executions>
<configuration>
<smtpHost>mail.yourhost.com</smtpHost>
<smtpPort implementation="java.lang.Integer">25</smtpPort>
<toAddresses>
<toAddress implementation="java.lang.String">
someones#email.com</toAddress>
<toAddress implementation="java.lang.String">
someoneelse#email.com</toAddress>
</toAddresses>
<!--using a custom velocity template in
src/main/resources/mailTemplate/announcement.vm -->
<template>announcement.vm</template>
<templateDirectory>mailTemplate</templateDirectory>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

Though the question is a bit older, it might be possible that someone still needs a different solution: I have created a plugin for just that purpose. Have a look at the plugin's page at github.com.
Multipart-alternative MimeMessages aren't implemented (have a look at the FAQ for the reasons), as well as a decent templating, but as long as you simply want to send a text mail with attachements it should do the trick.
I plan to submit it to mojo.codehaus.org, hence the gId. For now, you have to compile it yourself - sorry for that inconvenience.

There is also a highly customizable Postman mail plugin which gives you options to send test results or even an arbitrary html specifying a source file. Here's a good thread explaining how it should be configured.

I don't use Maven, but I think you can do this with a plugin.

Related

How to debug a Maven application in Eclipse

Let me start by clarifying I have check every possible resource, tutorial, video, other stackoverflow questions that I could get my hands on that are related in order to try and find an answer to this. I'm using java 8 and Eclipse Luna Service Release 2 (4.4.2) with m2e plugin, It's quite hard to believe but it seems there isn't a single example that clearly explains how you actually debug a Maven Java application USING ECLIPSE. There are no less than 40 different sources here are some
Debugging with exec-maven-plugin
https://blog.jooq.org/how-to-debug-your-maven-build-with-eclipse/
Eclipse not stopping at java breakpoints during remote debug
https://github.com/howlger/Eclipse-IDE-improvements-videos/tree/2022-03/sample_code
IntelliJ IDEA Maven project StackOverflowError when running debug configuration
Debugging in Maven?
What I'm trying to do is click the debug button in eclipse and run a debug configuration that allows me to hit my breakpoints.
I have the following configuration in Eclipse
this runs the exec:exec goal from my pom.xml which looks like this
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<classpath />
<argument>core.app.server</argument>
<argument>-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address=*:49875 </argument>
</arguments>
<workingDirectory>${project.build.outputDirectory}</workingDirectory>
</configuration>
</plugin>
Ok, so far so good. At this point if I run the debug configuration the app launches and then hangs which I'm assuming it is waiting for the debugger to remotely connect based on the arguments in my pom.xml. So the app starts hangs and in Eclipse at this point I'm looking at this
At this point I've tried everything I can imagine. I notice the exec plugin launcher starts on a random port which in the picture is 51661, when in my exec arguments in the pom.xml I have it set to 49875 so this seems off. Another thing I noticed if I removed the <argument>-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address=*:49875 </argument> line from my pom.xml the app launches completely , runs fine but this gets me no where. I have tried to connect using a "Remote Java Application" configuration after the app launches this also does not work. I normally use IntelliJ which makes it an absolute breeze since everything is handled OOTB, unfortunately I have to get this working in Eclipse as well in a similar fashion.
How do I configure the Debug Configuration in a way that will allow me to launch the app and hit my breakpoints?
EDIT 1
When setting suspend=n the app still hangs when launching with the argument agentlib:jdwp
EDIT 2
In an effort to get this figured out without wasting another day on something that should be effortless, I tested running a clean install from and debug configuration and then tested using the run as commands provided by m2e shown below and the m2e commands work perfectly where as the same exact commands ran with a debug configuration fail for missing references.
EDIT 3
Reading the documentation on the exec maven plugin here https://www.mojohaus.org/exec-maven-plugin/index.html it says the difference between exec:exec and exec:java is that the ladder execute programs and Java programs in a separate process and the former execute Java programs in the same VM. I think this might be somewhat related to the issue I'm having. This should be really easy to test for someone familiar with MAven/Eclipse I would think, is anyone able to create a super basic hello world app maven project and see if they can set and hit a break point in the main method, should take but 5-10 min?
I got it working like so:
Download, extract (latest!?) Luna SR2 JavaEE Edition
set (correct) JAVA_HOME/vm in eclipse.ini (oracle-8 latest)
Welcome Screen, create new Maven project, simple, skip achetype...
(So with fresh defaults, simple project):
With the following pom section :
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>C:\Program Files\Java\jdk1.8.0_333\bin\java.exe</executable>
<arguments>
<argument>-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address=49875</argument>
<argument>-classpath</argument>
<classpath />
<argument>com.example.Demo</argument>
</arguments>
<workingDirectory>${project.build.outputDirectory</workingDirectory>
</configuration>
</plugin>
</plugins>
</build>
(very similar to yours, only significant difference: address, server is crucial in this approach, suspend either)
With the same (Maven) Run configuration, as you show:
We now additionally need:
"Debug Configurations..."
Remote Java Application(! ..because we chose "server"..)
we select the (sources) project as "Project"
Connection Type: attach
Host: localhost
Port: the one configured in jdwp
Looks like:
Set "my" breakpoint in:
package com.example;
public class Demo {
public static void main(String[] args) {
int x = 0;
x++; // just to set breakpoint somewhere
System.out.println(x);
}
}
"Run" "Exec_Java" (suspend, and server flags (and all) have effect!)
Console(Exec_Java) should report:
...
[INFO] --- exec-maven-plugin:3.0.0:exec (default-cli) # luna-res ---
Listening for transport dt_socket at address: 49875 //!!
"Debug" "New_Configuration".
..and the breakpoint halts(, and we get the "switch perspective dialog";)

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

Log statements in pom.xml or Tracking flow of Maven

I am new to Maven and I am trying to get strong hold of it. I have gone through the beginner's tutorials and I am able to understand the basic stuff, but I have a complex pom.xml file in my project and my next goal is to understand that.
With the limited knowledge acquired from beginner's guide it is not possible for me to understand that complex pom.xml, so i was thinking of adding some sort of log statements in pom.xml or looking for an alternative via which i could track the flow of execution in pom.xml, since that would help me in knowing how things are moving.
You could printout some log messages to maven console using the maven-antrun-plugin, you can also specify the phase you want to print the message in, see the code below (it goes to the plugins section)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>print-log</id>
<phase>initialize</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo message="Your log message for project ${project.artifactId}" />
</target>
</configuration>
</execution>
</executions>
</plugin>
I believe that output generated by debug option in maven can be quite huge and time consuming for reading. I use it only for some specific problem analysis.
For me it allways worked to go through complicated pom.xml files by reading and try to understand intent of the author of the particular section (I think good reference for the pom.xml elements can be found on: http://maven.apache.org/pom.html).
Once you run build afterwards, you can see what and when is it executed and you can find mapping between what you've learned before and how it really works :)
You can start by issuing
mvn -X install
That will give you the flow of execution.
According to mvn --help:
-X,--debug Produce execution debug output
An alternative if you want to see all your dependencies, properties, plugins, directories etc. the try this:
mvn help:effective-pom
I would recommend to read more about Maven build lifecycle. Maven is not a script-like build automation tool (like ant or make). It's a different approach. Logs should be less important than output artifacts produced in ./target directory.

maven test behind proxy (squid)

I'm having a problem with Maven behind a squid proxy server.
I have a module of my system that depends external communication with a remote webservice.
I have my maven proxy configurations under ~/.m2/settings.xml, but apparently, these information are been used just for dependencies downloads.
When I run 'mvn test', these configurations aren't used on command line execution call. This is the instruction echoed on console:
${JAVA_HOME}/bin/java -jar /tmp/surefirebooter4156656684210940660.jar /tmp/surefire2646147996861949548tmp /tmp/surefire3498083351425809633tmp
There's a way to pass arguments to JVM during tests and other maven method executions?
Perhaps this can be of interest to you: How do I configure proxy settings for Java. Alternatively you can try these startup parameters:
-Dhttp.proxyHost=url
-Dhttp.proxyPort=port
-Dhttp.proxyUser=user
-Dhttp.proxyPassword=pass
[EDIT]
These properties can also be set in MAVEN_OPTS. This post describes how this would work for the test-profile.
To fix some arguments on pom.xml, we can configure -DforkMode=never directly on surefire plugin configuration. i.e.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<argLine>-DforkMode=never</argLine>
</configuration>
</plugin>
The solution based on -DforkMode was suggested by this post, referenced by #johan-sjoberg on comments posted here

Easier way to run a Java application from Maven?

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.

Categories