Run Maven tests with -Dmaven.surefire.debug and -DforkMode=never - java

I am working on a project with Maven and Surefire plugin v. 2.11.
To run single tests I am using -Dtest=TestClass#testMethod and -DforkMode=never (without DforkMode=never I can't run tests because of lack of space for object heap). I got used to it and it was working for me fine.
So I am running:
mvn -Dtest=TestClass#testMethod test -DforkMode=never
and test is run fine.
But when I am running
mvn -Dtest=TestClass#testMethod -Dmaven.surefire.debug test -DforkMode=never
it just skips debug "waiting" part and the test is being executed (I am unable to connect using IDE).
mvn -Dmaven.surefire.debug test works for me fine with other project (where I don't need to care about fork mode).
Any ideas why the combination of forkMode=never and -Dmaven.surefire.debug doesn't work as expected?

The property maven.surefire.debug is setting the debugForkedProcess parameter of the surefire plugin.
The documentation for this parameter reads as follows:
Attach a debugger to the forked JVM. If set to "true", the process will suspend and wait for a debugger to attach on port 5005. If set to some other string, that string will be appended to the argLine, allowing you to configure arbitrary debuggability options (without overwriting the other options specified through the argLine parameter).
So it will only debug forked JVMs, which explains why it doesn't work when the tests aren't being forked. It isn't able to setup the debugging of a non-forked JVM process that is already running.
Use mvnDebug
What you can do instead is use mvnDebug, which allows you to debug the maven process itself - and as your tests are not being forked those as well.
i.e. instead of mvn -Dtest=TestClass#testMethod test -DforkMode=never you would execute mvnDebug -Dtest=TestClass#testMethod test -DforkMode=never. By default it will listen on port 8000 when it starts maven.

Related

mvnDebug tomcat7:run don't suspend

I have a project which I run on local by
mvnDebug tomcat7:run
Now, I know that mvnDebug is equivalent to
MAVEN_DEBUG_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
Here, suspend=y and I want the suspend=n. Basically, with suspend=y , I have to start the remote debugger in between as the process halts for it. I dont want that. Hence, suspend=n.
So, I ran
mvn tomcat7:run -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
But I am getting this error:
[ERROR] No plugin found for prefix 'runjdwp' in the current project
and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo]
available from the repositories...
Even if I run above command with suspend=y , still same error.
What should I do ?
I am running Java 8
Just use -Dexec.args to pass your arguments to java rather than maven itself.
This should work
mvn tomcat7:run -Dexec.args="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000"

How to run spring-boot application using GitLab runner?

I have a spring-boot maven application I've been running locally as:
mvn spring-boot:run
I want to be able to run this in GitLab runner so that when I push the code to master, it automatically copies the latest up there and runs the application.
My GitLab runner is configured in shell mode right now, and I have inside of the .gitlab-ci.yml file a deploy task that runs just that:
mvn spring-boot:run
The issue I am running into is after the application starts, I can see that it is running... but it never shows as success or completed. It just hangs there (because the terminal is still running when you execute that command?)
Question is, is there an alternate set of commands I should be running to get my spring-boot application to update and run each time I push to master? What is it i should be putting into my gitlab-ci.yml (or other files). Note that I am not using docker or kubernetes... just shell.
Sample gitlab CI:
run-deploy:
stage: deploy
script:
- mvn $MAVEN_CLI_OPTS spring-boot:run
Trying nohup with that also fails.
- nohup mvn $MAVEN_CLI_OPTS spring-boot:run &
I believe you can use the run stage for this. It would look something like
run:
stage: run
script:
- mvn $MAVEN_CLI_OPTS spring-boot:run
You can see an example of this here.
Make sure you also define the stages to include run as the docs state
If no stages are defined in .gitlab-ci.yml, then the build, test and deploy are allowed to be used as job’s stage by default. (see stages)
Is the sample file you provided above your entire configuration file or only a snippet of it? If so, I can adjust my answer to fit your needs. Thanks!
I'm sorry this is so late. I've recently just had the same problem. Gitlab runner blocks on child processes, and any process in the child tree. This makes the disown command impossible since you can't get to it. Forking, and nohup also don't work.
The only solution I could figure out was using the at command https://linux.die.net/man/1/at
Basically I put my command in a script then did:
at now < my_blocking_command_script.sh
That successfully complete the runner and kicked off my program in the background.

Not able to remote debug tests in Intellij when executing tests using gradle test task

I have a spring boot project (Java 8, JUnit 4). I am using IntelliJ for IDE. My test passes when I run from within IntelliJ but fails when I run it from command line using gradle test command. So I am trying to remote debug my Junit test. I have breakpoints set. But when the test is executing the debugger is not stopping at the breakpoints. This is what I have done so far:
I have created a remote debug configuration in IntelliJ with port as 5005
I am running this command: gradle test -Dtest.debug on command line
I see build output that the build is waiting for the debugger to connect to port 5005 and the process suspends
At this point I run my remote debug configuration and it successfully connects to port 5005
After this the JUnit test is executed but the debugger does not stop at the breakpoints.
In fact when the test is running the breakpoints on the junit test are changing to lite gray color. This tells me that the JVM IntelliJ debugger got connected to did not have the executable code for my test. Gradle is spinning off multiple JVMs I believe and IntelliJ is connecting to the wrong one. How can I validate this?
How to make debugger stop at the breakpoints? Really appreciate someone's help.

Maven: configure parallel build in pom.xml

Maven has a capability to perform parallel builds:
https://cwiki.apache.org/confluence/display/MAVEN/Parallel+builds+in+Maven+3
mvn -T 4 clean install # Builds with 4 threads
mvn -T 1C clean install # 1 thread per cpu core
mvn -T 1.5C clean install # 1.5 thread per cpu core
Is it possible to specify this arguments in pom.xml or settings.xml? Repeating this options could be annoying.
This solution is a bit of a hack but worked for me. It involves specifying a new environment variable, assigning the value -T3 to it and adding this variable to the Maven launch script.
For Windows (Linux in parens):
Open the Environment Variables window: Computer -> Properties -> Advanced System settings -> Environment Variables
Add the property MAVEN_CMD_LINE_OPTS with your desired value. In my case -T 3 as I want Maven to use 3 threads to build in parallel.
Edit the mvn.cmd file (In Linux: the mvn file). Find the part where the Java command is actually executed, the line starting with %MAVEN_JAVA_EXE% (In Linux: generally after the line defining the main class: org.codehaus.plexus.classworlds.launcher.Launcher)
Add %MAVEN_CMD_LINE_OPTS% to the end of the line (In Linux: $MAVEN_CMD_LINE_OPTS)
When you run mvn compile on a Maven project you will now see the following line:
Using the MultiThreadedBuilder implementation with a thread count of 3
This has the advantage of the user being able to 'override' this value. So if the user executes mvn -T4 compile, then 4 threads are used instead of the default 3.
Note:
I tried this on Maven 3.3.9 but the concept should work on any Maven
version.
Multi-threaded builds can suffer from issues where plugins
especially custom plugins are not thread safe. So use with care and
consider disabling this as a fix in case of issues.
I could not find a way to configure this in the pom.xml or settings.xml There is a good solution on unix systems, edit your .bashrc and add an alias.
alias mvnp='mvn -T 4'
now from the terminal run maven using mvnp
mvnp clean install
You are able to specify the option in the MAVEN_OPTS environment variable (see http://maven.apache.org/guides/mini/guide-configuring-maven.html). Once this is done, you don't have to repeat it. Configuring the environment variable depends on your system. However this will affect all maven runs within your environment. Maybe it's possible for you to enable different environments, so that only the project you actually want to build in parallel is running in such an environment.

Debugging in Maven?

Is it possible to launch a debugger such as jdb from Maven? I have a pom.xml file that compiles the project successfully. However, the program hangs somewhere and I would really like to launch jdb or an equivalent debugger to see what's happening.
I compile using mvn compile and launch using:
mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
I was expecting something like:
mvn exec:jdb -Dexec.mainClass="com.mycompany.app.App"
to launch the debugger but, as usual, my expectations are incongruent with maven's philosophy.
Also, I couldn't find any documentation (on Maven's website or google) to describe how debugging works. I suspect that I have to use some plugin.
If you are using Maven 2.0.8+, run the mvnDebug command in place of mvn and attach a debugger on port 8000.
For Maven <2.0.8, uncomment the following line in your %M2_HOME%/bin/mvn.bat (and maybe save the modified version as mvnDebug.bat):
#REM set MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
More details in MNG-2105 and Dealing with Eclipse-based IDE.
Just as Brian said, you can use remote debugging:
mvn exec:exec -Dexec.executable="java" -Dexec.args="-classpath %classpath -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044 com.mycompany.app.App"
Then in your eclipse, you can use remote debugging and attach the debugger to localhost:1044.
I thought I would expand on these answers for OSX and Linux folks (not that they need it):
I prefer to use mvnDebug too. But after OSX maverick destroyed my Java dev environment, I am starting from scratch and stubbled upon this post, and thought I would add to it.
$ mvnDebug vertx:runMod
-bash: mvnDebug: command not found
DOH! I have not set it up on this box after the new SSD drive and/or the reset of everything Java when I installed Maverick.
I use a package manager for OSX and Linux so I have no idea where mvn really lives.
(I know for brief periods of time.. thanks brew.. I like that I don't know this.)
Let's see:
$ which mvn
/usr/local/bin/mvn
There you are... you little b#stard.
Now where did you get installed to:
$ ls -l /usr/local/bin/mvn
lrwxr-xr-x 1 root wheel 39 Oct 31 13:00 /
/usr/local/bin/mvn -> /usr/local/Cellar/maven30/3.0.5/bin/mvn
Aha! So you got installed in /usr/local/Cellar/maven30/3.0.5/bin/mvn.
You cheeky little build tool. No doubt by homebrew...
Do you have your little buddy mvnDebug with you?
$ ls /usr/local/Cellar/maven30/3.0.5/bin/mvnDebug
/usr/local/Cellar/maven30/3.0.5/bin/mvnDebug
Good. Good. Very good. All going as planned.
Now move that little b#stard where I can remember him more easily.
$ ln -s /usr/local/Cellar/maven30/3.0.5/bin/mvnDebug /usr/local/bin/mvnDebug
ln: /usr/local/bin/mvnDebug: Permission denied
Darn you computer... You will submit to my will. Do you know who I am? I am SUDO! BOW!
$ sudo ln -s /usr/local/Cellar/maven30/3.0.5/bin/mvnDebug /usr/local/bin/mvnDebug
Now I can use it from Eclipse (but why would I do that when I have IntelliJ!!!!)
$ mvnDebug vertx:runMod
Preparing to Execute Maven in Debug Mode
Listening for transport dt_socket at address: 8000
Internally mvnDebug uses this:
MAVEN_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE \
-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"
So you could modify it (I usually debug on port 9090).
This blog explains how to setup Eclipse remote debugging (shudder)
http://javarevisited.blogspot.com/2011/02/how-to-setup-remote-debugging-in.html
Ditto Netbeans
https://blogs.oracle.com/atishay/entry/use_netbeans_to_debug_a
Ditto IntelliJ
http://www.jetbrains.com/idea/webhelp/run-debug-configuration-remote.html
Here is some good docs on the -Xdebug command in general.
http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html
"-Xdebug enables debugging capabilities in the JVM which are used by the Java Virtual Machine Tools Interface (JVMTI). JVMTI is a low-level debugging interface used by debuggers and profiling tools. With it, you can inspect the state and control the execution of applications running in the JVM."
"The subset of JVMTI that is most typically used by profilers is always available. However, the functionality used by debuggers to be able to step through the code and set breakpoints has some overhead associated with it and is not always available. To enable this functionality you must use the -Xdebug option."
-Xrunjdwp:transport=dt_socket,server=y,suspend=n myApp
Check out the docs on -Xrunjdwp too. You can enable it only when a certain exception is thrown for example. You can start it up suspended or running. Anyway.. I digress.
I found an easy way to do this -
Just enter a command like this -
>mvn -Dtest=TestClassName#methodname -Dmaven.surefire.debug test
It will start listening to 5005 port. Now just create a remote debugging in Eclipse through Debug Configurations for localhost(any host) and port 5005.
Source - https://doc.nuxeo.com/display/CORG/How+to+Debug+a+Test+Run+with+Maven
If you are using Netbeans, there is a nice shortcut to this.
Just define a goal exec:java and add the property jpda.listen=maven
Tested on Netbeans 7.3
If you don't want to be IDE dependent and want to work directly with the command line, you can use 'jdb' (Java Debugger)
As mentioned by Samuel with small modification (set suspend=y instead of suspend=n, y means yes which suspends the program and not run it so you that can set breakpoints to debug it, if suspend=n means it may run the program to completion before you can even debug it)
On the directory which contains your pom.xml, execute:
mvn exec:exec -Dexec.executable="java" -Dexec.args="-classpath %classpath -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044 com.mycompany.app.App"
Then, open up a new terminal and execute:
jdb -attach 1044
You can then use jdb to debug your program!=)
Sources:
Java jdb remote debugging command line tool
Why not use the JPDA and attach to the launched process from a separate debugger process ? You should be able to specify the appropriate options in Maven to launch your process with the debugging hooks enabled. This article has more information.
I use the MAVEN_OPTS option, and find it useful to set suspend to "suspend=y" as my exec:java programs tend to be small generators which are finished before I have manage to attach a debugger.... :) With suspend on it will wait for a debugger to attach before proceding.
I couldn't make any of the other solutions work and then I tried starting maven with the following.
mvn exec:exec -Dexec.executable="java" -Dexec.args="-classpath %classpath -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000 com.example.Main"
This worked for me and then I searched some more and found this other answer. IntelliJ can run Maven project in debug mode but ignores breakpoints
The fact is that my application is a spring-boot application. Now, the link referred to above may be right and the problem is that the spring-boot plugin creates a new fork that somehow invalidates the interaction between debugger and target app. I'm saying this because I got some info on how this may work from here
In any case, I don't know how the two solutions are related to each other. Is the first solution also preventing spring-boot from creating a fork??
Sadly I have no clue at the moment.
Here is how I do it.
For example:
mvn clean azure-functions:run -DenableDebug
Then, after it starts up, you'll see a link in the Terminal that says "Attach Debugger".
To me, that is the easiest way to do it.

Categories

Resources