Running Spring Boot "context loads" test in maven causes OutOfMemoryError - maven

I have a multi-module Maven project with two modules being Spring Boot applications. Each of them has a simple test that the Spring application context loads successfully (my tests are very similar to this one). I run this tests with the following command in project root:
mvn -P IntegrationTests clean test
During context initialization things go out of my control, the application "eats" memory (heap size grows quickly to 4 gigabytes) and then the context fails to start with java.lang.OutOfMemoryError: PermGen space error (yes, I run it in Java 7).
Monitoring task manager during testing I noticed that maven spawns two new processes that have something to do with surefire plugin. I have no idea where it comes from, because I don't add the surefire plugin in my pom.xml.
Previously when encountered the same error somewhere I specified VM options (-Xmx256m -Xms128m -XX:MaxPermSize=256m -XX:PermSize=128m for example) and the problem was solved.
This time I tried to
set MAVEN_OPTS environment variable
set VM options (when running mvn test in IntelliJ IDEA) - it affected main java process but not its children
add -Drun.jvmArguments="..." in command line
but the problem persists.
Please help me to fight the OutOfMemoryError in tests.

Add Surefire plugin explicitly to module-specific pom.xml and configure VM options there. I like this solution because this way VM options are
passed to the spawned surefire processes (which should solve your problem)
affect only test application builds
shared between developers in your team
configurable independently for every module
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xmx256m -Xms128m -XX:MaxPermSize=256m -XX:PermSize=128m</argLine>
</configuration>
</plugin>
<!-- your other plugins go here -->
</plugins>
</build>

Related

How to debug a Maven OpenJFX application in IntelliJ

Since JavaFX has become OpenJFX and needs to be added as a dependency to your Maven project, debugging a OpenJFX application has become complicated. In this question it is already answered how to solve it for NetBeans. But IntelliJ works slightly different. The Ppom.xml has been setup according to this example.
How can you run an OpenJFX (JavaFX) application which is configured as a Maven project in debug mode in IntelliJ?
If you would copy the addition of VM options in the pom.xml for javafx-maven-plugin as given by José Pereda here, you can run the application with 'mvn javafx:run#debug' and then manually attach it to the IntelliJ Debugger by go to the menu 'Run - Attach to process...' and the select your application.
However, if you want debugger and application to be started with a single click, IntelliJ is a but troublesome. You can create a Remote Debug configuration which first launches your application and the debugger serially. Or have Compound Configurations which does both in parallel. The problem is to get them synchronized.
I found the following solution. Make your application run as debug client and the IntelliJ debugger as server. The VM options for the javafx-maven-plugin in the pom.xml file should have 'server=n':
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.4</version>
<executions>
<execution>
<!-- Default configuration for running -->
<id>default-cli</id>
<configuration>
<mainClass>org.waninge.test.JFXTest</mainClass>
</configuration>
</execution>
<execution>
<!-- Configuration for debugging -->
<id>debug</id>
<configuration>
<options>
<option>-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:8000,suspend=y</option>
</options>
<mainClass>org.waninge.test.JFXTest</mainClass>
</configuration>
</execution>
</executions>
</plugin>
Create a Maven Run Configuration in IntelliJ with 'javafx:run#debug' in the 'Command line'.
Create a Remote Run Configuration with the following settings:
Debugger mode: 'Listen to remote JVM';
Transport: 'Socket';
Host: as in the pom
Port: as in the pom
Now the Remote Run Configuration will start a debug server waiting for clients. The Maven Run Configuration will connect to the debug server, or fail if the debug server isn't online.
Now, to get everything started with a single click, you can create a Compound Run Configuration and add the Maven and the Remote Run Configuration to it. Starting this configuration will launch the two in parallel, and you can debug your application.

autoweaving AspectJ fails during unit tests in IntelliJ

We have a series of unit tests and they were passing fine prior to me trying to add some aspects for dependency injection and logging duration of methods being called in our rest end points.
In the unit tests prior to the tests failing, we get two odd errors:
[AppClassLoader#14dad5dc] error aspect 'com.lutherconsulting.aphirm.log.DurationLoggingAspect' woven into 'com.lutherconsulting.aphirm.rest.ClientRest' must be defined to the weaver (placed on the aspectpath, or defined in an aop.xml file if using LTW).
and
[AppClassLoader#14dad5dc] error aspect 'com.lutherconsulting.aphirm.log.DurationLoggingAspect' woven into 'com.lutherconsulting.aphirm.log.DurationLoggingAspect' must be defined to the weaver (placed on the aspectpath, or defined in an aop.xml file if using LTW).
We are using the aspectj maven plugin to just let it autoweave the aspects into the web application. The configuration for that from our pom.xml for Maven is below.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<goals>
<goal>test-compile</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
The strange thing is that this all works perfectly fine if I build the war file and deploy it to a Tomcat instance, or if I run all of our cucumber feature tests. When I do either of those, The aspect weaves fine and I get data on the duration of the rest methods I annotated logged to a database correctly. If I run a specific test package from intelliJ or try to run all junit tests in intellij, it fails with those two errors
Is this something I'm just missing in Intellij as a run/debug configuration in the way it executes unit tests? I didn't think our structure of our app was different than any normal web app
- src
| - main
| - java
| - packages
| - resources
| - test
| - java
| - packages
| - resources
- pom.xml
I appreciate any ideas on
In the end, what turned out to fix this was to go into the project structure in IntelliJ, on the AspectJ settings there is a check box for Post-Compile Weave Mode. Checking this made sure weaving occurred in Intellij prior to the tests executing.
As far as I understand you are running your tests from IntelliJ using its own runner and not maven.
Therefore you have configured the weaver to be run using maven through the aspectj-maven-plugin. The problem is that your IntelliJ runner is not running maven, hence its weaver plugin is not being run either.
I can come up with an idea and you could run your maven test goal within IntelliJ to run all your tests with the maven configuration, so it will detect aspectj-maven-plugin and run the weaver too. Here you can check how to run maven goals:
https://www.jetbrains.com/idea/help/executing-maven-goal.html
On the other hand, according to this link you have to enable Load Time Weaving in IntelliJ
http://www.aspectprogrammer.org/blogs/adrian/2006/02/a_practical_gui_2.html
Quoting the link it says:
Open the "Run/Debug Configurations" dialog using the drop-down in the
toolbar. Click the "+" icon to create a new configuration and name it
e.g. "tests".
For this project, I've selected "All in package" and search for tests
"In whole project".
Now all you have to do is add the VM startup parameter that brings in
the AspectJ LTW agent:
-javaagent:lib/aspectjweaver.jar
The part after the ":" should be the path to your copy of aspectjweaver.jar. In this case, I've copied the
aspectjweaver.jar from the Spring distribution into the lib directory
of my project (it doesnt' need to be on the project's classpath). You
can use the jar from AspectJ 5 final release too if you want to.
Also, you can check to configure AspectJ facet, check this link to read about it
https://www.jetbrains.com/idea/help/aspectj.html

System brokes when start single test in InteliJ

I have complex web application using Spring,Hibernate, Maven joint build(Java+Groovy) with test in Spock and different Maven profiles. All source files are in Java. I have Maven configuration(part of it) for local testing:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<path>/services</path>
<port>8062</port>
<contextReloadable>true</contextReloadable>
<backgroundProcessorDelay>2</backgroundProcessorDelay>
<contextFile>../context.xml</contextFile>
</configuration>
</plugin>
So when I have changes in the bytecode maven contextReloadable triggers redeploy of the app. That is the desire state. When I run some test with maven configuration usingin InteliJ, in my system I see that redeploy is triggered.
I have no changes in the files or in the tests. But redeploy is triggered and everything is OK. But there is a problem for the same test when I click right button and click run on UploadTest using InteliJ 14.0.3 Community Edition
Redeploy happens but the profiles are not taken under consideration and the environment variables are not set. If I add them
org.apache.catalina.core.ContainerBase backgroundProcess WARNING: Exception processing loader WebappLoader[/services] background process java.util.ConcurrentModificationExceptio
And my backendSystem crashes. So my questions are:
Why InteliJ triggers redeploy when run Spock test without changes in the code/tests?
Why starting a single Spock test using InteliJ, cause my backednSystem brokes(I need to restart it)(what can be the source of the problems?? InteliJ runs the test with diferent parameters, profiles are not taken or ...).
Does inteliJ start compilation of the test with different eviroment variables set? (I see that inteliJ start its own launcher for the test).

How to defer Maven test goal after deployment?

I'm using the JBoss and WildFly Maven plugin to deploy my applications.
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>1.0.0.Beta1</version>
</plugin>
</plugins>
The problem that I have found is that if I have some Junit test in my project they are executed before application deployment, leading to a test with an inconsistent application state. Is it possible to configure somehow this plugin to kick-in before the test phase ?
Thanks
This plugin by default executes alongside the package phase and you'll probably have issues attempting to run the plugin before your application is packaged. As an alternative, you could override the maven-surefire-plugin to run your tests in a later phase, such as integration-test, which would be executed after your application has been packaged.
A practical example can be found on this Maven tutorial where it's show how to include failsafe plugin and bind it to the executions of the integration-test and verify phase. This way tests which are engineered as integration test (e.g ending in *IT) will execute only during the integration-test phase.

Intellij-idea Debugger disconnected when debugging maven test

I have followed this link to debug maven test via Intellij Idea : http://www.grygoriy.com/2012/01/how-to-debug-tests-maven-test-via.html
When reaching the third step and starting debugging, It's connected but quickly disconnected and isn't stopped in breakpoints. I had in Intellij :
Connected to the target VM, address: 'localhost:5005', transport: 'socket'
Disconnected from the target VM, address: 'localhost:5005', transport: 'socket'
Any idea ?
The only thing that prevents Idea from debugging Maven's goals is forking.
Plugins such surefire and spring-boot are using forking by default.
So, when you start debuging maven goal from IDEA it connects to maven, but process that you are really want to debug distincts from maven process, so it doesn't connected.
To prevent such behavior in surefire plugin you should read this article: http://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html
In short:
If you use old surefire:
<configuration>
<forkMode>never</forkMode>
</configuration>
In new surefire:
<configuration>
<forkCount>0</forkCount>
</configuration>
But it's not much clear:
in case of CI (i wish you are using CI tools) you are not have prevent forking while it's much slow
if you ship your project to others - they will not be happy if some of modules behave in not default way
So if you want to please CI, IDEA, co-developers and yourself you should provide more smart way to allow debugging you build.
My suggestion:
default behavior is forked because build process is very often thing, while debugging it - is exception
debugger behavior is isolated with simple to use "switch on"
My variant:
<properties>
<test.forkCount>1</test.forkCount>
</properties>
<profiles>
<profile>
<id>debug</id>
<properties>
<test.forkCount>0</test.forkCount>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<!-- surefire -->
<configuration>
<forkCount>${test.forkCount}</forkCount>
</configuration>
</plugin>
</plugins>
</build>
So, in IDEA you just require to create named Run configuration with goal test and include debug to profile list.
But in other contexts - maven behaves still by default.
Where is addition profit - you can incapsulate whole debug behavior in single profile.
For example in my real project debug profile:
swith off forking on spring-boot:run
switch off JaCoCo coverage (it requires forking on surefire)
keep building Docker images locally but prevents pushing to registry
keep full packaging process but prevents publication to nexus
redirects SOAP UI functional tests to specital URL for local debugging
redirects DBCONFIG to docker-based Postgres that is "always empty"
downgrades loglevel for log4j to DEBUG
So if I use mvn <any> -P debug i'm sure that my environment and process is really debug
But if i ran mvn deploy on CI - i will get full stack of my building process.
This can also happen if e.g. the annotation BeforeAll is incorrectly used. IntelliJ swallows problem during the test initialization.
In my case the BeforeAll method was not static:
Incorrect:
#BeforeAll
private void beforeAll() {
}
It can also happen if the BeforeAll method is failing and the test is not started. Using mvn verify should print the error message in these cases.

Resources