TypeNotPresentExceptionProxy error at integration-test with maven-failsafe-plugin spring-boot 1.4 - spring-boot

I'm getting ArrayStoreException: TypeNotPresentExceptionProxy when running integration-test with maven-failsafe-plugin and spring-boot 1.4.
You can see this error if you run joinfaces-example with
mvn -Pattach-integration-test clean install
I realized that the error does not occur if I change spring-boot-maven-plugin to run at pre-integration-test phase instead of package one.
More, this error started when I upgraded spring boot to 1.4. No error occurs if I change jsf-spring-boot-parent version to 2.0.0 which uses spring boot 1.3 version.

I actually found the answer in Spring Boot 1.4 release notes, short answer is that maven-failsafe-plugin is not compatible with Spring Boot 1.4's new executable layout. Full explanation below :
As of Failsafe 2.19, target/classes is no longer on the classpath and
the project’s built jar is used instead. The plugin won’t be able to
find your classes due to the change in the executable jar layout.
There are two ways to work around this issue:
Downgrade to 2.18.1 so that you use target/classes instead
Configure the spring-boot-maven-plugin to use a classifier for the
repackage goal. That way, the original jar will be available and used
by the plugin. For example :
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>

An alternative is documented here: https://github.com/spring-projects/spring-boot/issues/6254
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<!--
Make failsafe and spring-boot repackage play nice together,
see https://github.com/spring-projects/spring-boot/issues/6254
-->
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
</configuration>
</plugin>
This worked better for me, because when I used the "exec" solution, Spring failed to find my configuration files when starting the container. Which could probably be fixed by adding some further configuration parameters, I suppose, but this solution works "out of the box" for me.

Related

Does flyway support sql migrations under test folder?

I am migrating a project from Spring Boot 1.5.21 to 2.2.5. I have followed all instructions in the guide. However, I have an issue with flyway (upgrading from 4.2.0 to 6).
Previously, when I had sql migration files under src/test/resources/db/migration, flyway would run them as part of the mvn clean install command. Now, for some reason, it stopped running these migrations (Just to clarify, I'm talking about maven build and not while running the app).
I'm using maven 3.6.3 and flyway-maven-plugin version 6.0.8 with the following configuration (some values are tokens which are irrelevant for this question):
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>${flyway.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>migrate</goal>
</goals>
</execution>
</executions>
<configuration>
<skip>${db.skip}</skip>
<url>${db.url}</url>
<user>${db.username}</user>
<password>${db.password}</password>
<locations>
<location>classpath:db/migration</location>
</locations>
<schemas>public,downstream</schemas>
<outOfOrder>true</outOfOrder>
<callbacks>
db.migration.callback.PopulateControlFieldsFlywayCallback,db.migration.callback.UpdateReplicaIdentityFlywayCallback,db.migration.callback.UpdateSchemaHistoryTableFlywayCallback
</callbacks>
</configuration>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
</dependencies>
</plugin>
Why did the behaviour changed? How to revert to old behaviour? Am I missing something?
I have dug in the flyway and flyway-maven-plugin sorces. I have found that the path from classpath location tag is searched by ClassRealm in class. And there is exist two classpathes: ClassRealm[plugin>org.flywaydb:flyway-maven-plugin:5.0.0, parent: jdk.internal.loader.ClassLoaders$AppClassLoader#1f89ab83]. ClassRealm is a classloader that is used in Maven.
I have executed classLoader.getResources('/db/migration')and found that it returns 2 paths (target/classes/db/migration and target/test-classes/db/migration) for mave-plugin version 4.2.0, but returns only 1 path (target/classes/db/migration) for version5.0.0`.
Also I have found that there was a commit in flyway-maven-plugin repository for using maven 3 instead of 2 between maven-plugin version 4.2.0 and 5.0.0.
I haven't found an exact reason, but, summarizing all, I guess that there were some changes in maven-plugin (I guess some maven core library version) as a result of which the finding path in classpath was changed.
I have tried several options for returning the old behavior, but all of these not so good. These are work:
Stay on 4.2.0 maven-plugin version (I have a pet project where
I specified flyway 5.0.0 in <dependencies> and use maven-plugin
4.2.0 and it works correctly for you);
Specify a path to test-migration via <location>filesystem:target/test-classes/db/migration</location> or <location>filesystem:src/test/resources/db/migration</location>
I hope it will help you.
P.S. By the way, why do you use migration under test folder for generating classes by jooq? It looks very strange to me. You generate classes from one DB model, but in PROD you will have another DB model (since migrations only under main are used). Maybe you should think about it and using only migration under main folder? If you have some exceptions while jooq generatinig, try to fix it without test migrations.

Maven + AspectJ/SpringAOP + Lombok + Surefire = test broken in a specific scenario

I have an interesting problem in a project where all of the technologies mentioned in the title are used. I've been able to track it down up to the diagnosis (the test classpath prepared by Surefire), but I don't understand whether it can be fixed and how. It's not a showstopper, indeed it's a minor issue for me, but I'd like to solve it anyway.
First a rough description.
The problem is related to executing tests in a specific module of the project, and only in a specific way.
Everything works (tests pass) when I run from the master pom level:
cd ${projHome}
mvn install
Everything works (tests pass) when I run:
cd ${projHome}/modules/CoreImplementation/
mvn test
That means that I can build and test with no problems, the same for my Jenkins, and NetBeans can run tests from the IDE when I need them.
But that module fails testing when I run from the master pom level:
cd ${projHome}
mvn test
with this error:
java.lang.NoSuchMethodError: it.tidalwave.northernwind.profiling.RequestProfilerAspect.aspectOf()Lit/tidalwave/northernwind/profiling/RequestProfilerAspect;
at it.tidalwave.northernwind.frontend.ui.spi.DefaultSiteViewController.processRequest(DefaultSiteViewController.java:82) ~[classes/:na]
at it.tidalwave.northernwind.frontend.ui.spi.DefaultSiteViewControllerTest.must_call_some_RequestProcessors_when_one_breaks(DefaultSiteViewControllerTest.java:161) ~[test-classes/:na]
Running mvn test as a second pass (after a mvn install -DskipTests) happens to be the way Drone.io and Travis do their job. While I could change their configuration, I'd like to stay with the standard configuration and fix the problem if possible.
The diagnosis in short and my question.
Now, the question in short (details are further below). I was able to track down the problem to different ways in which Surefire prepares the classpath to execute the tests.
When I run mvn install the classpath is:
${repo}/org/apache/maven/surefire/surefire-booter/2.16/surefire-booter-2.16.jar
${repo}/org/apache/maven/surefire/surefire-api/2.16/surefire-api-2.16.jar
${projHome}/modules/CoreImplementation/target/test-classes
${projHome}/modules/CoreImplementation/target/classes
${projHome}/modules/Core/target/it-tidalwave-northernwind-core-1.1-ALPHA-37-SNAPSHOT.952b0c8bdc77.jar
${repo}/it/tidalwave/thesefoolishthings/it-tidalwave-role/3.0-ALPHA-1/it-tidalwave-role-3.0-ALPHA-1.jar
${projHome}/modules/Profiling/target/it-tidalwave-northernwind-core-profiling-1.1-ALPHA-37-SNAPSHOT.952b0c8bdc77.jar
${repo}/org/apache/commons/commons-math3/3.0/commons-math3-3.0.jar
…
When I run mvn test (from the project home) the classpath is:
${repo}/org/apache/maven/surefire/surefire-booter/2.16/surefire-booter-2.16.jar
${repo}/org/apache/maven/surefire/surefire-api/2.16/surefire-api-2.16.jar
${projHome}/modules/CoreImplementation/target/test-classes
${projHome}/modules/CoreImplementation/target/classes
${projHome}/modules/Core/target/unwoven-classes
${repo}/it/tidalwave/thesefoolishthings/it-tidalwave-role/3.0-ALPHA-1/it-tidalwave-role-3.0-ALPHA-1.jar
${projHome}/modules/Profiling/target/unwoven-classes
${repo}/org/apache/commons/commons-math3/3.0/commons-math3-3.0.jar
…
The different portions are the indented ones. In the former case, SureFire uses the classes directory (forget for a moment that in my case they are named unwoven-classes) only for the module under test, and the installed jar files for every dependency. In the latter case, it seems to be using classes for all dependencies in the reactor.
The reason for which this difference in the classpaths gives me troubles is explained below in the "Gory details" section. In short, that unwoven means that they contain bytecode not augmented by AspectJ, hence the methods that can't be found at runtime.
I'm running with SureFire 2.16, but I've also tried the latest 2.19 with no changes. Being able to force SureFire to always use jar files for dependencies would fix my problems. If you have the answer, you can stop reading my post here.
Gory details (just for curiosity).
The faulty module artifactId is it-tidalwave-northernwind-core-default and it depends on aspects available in it-tidalwave-northernwind-core-profiling - that's where the offending RequestProfilerAspect is. The aspect library dependency is both in the regular dependencies of the faulty module and in the configuration of the aspectj plugin:
<dependency>
<groupId>it.tidalwave.northernwind</groupId>
<artifactId>it-tidalwave-northernwind-core-profiling</artifactId>
</dependency>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<aspectLibraries combine.children="append">
<dependency>
<groupId>it.tidalwave.northernwind</groupId>
<artifactId>it-tidalwave-northernwind-core-profiling</artifactId>
</dependency>
</aspectLibraries>
</configuration>
</plugin>
</plugins>
</build>
AspectJ integration is by means of the following profile in a Super POM, which is activated in the build, whose relevant part is:
<profile>
<id>it.tidalwave-aspectj-springaop-v1</id>
...
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<configuration>
<outputDirectory>target/unwoven-classes</outputDirectory>
</configuration>
</execution>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<configuration>
<outputDirectory>target/unwoven-test-classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
...
The aspectj plugin is configured in the profile to statically weave binaries in the unwoven-test-classes directories. The reason for this approach is that it's the only feasible solution AFAIK to have both Lombok and AspectJ work together.
Now, back to the two classpaths described above: the fact that SureFire is using unwoven-classes means that it's pointing to bytecode that has not been augmented with AspectJ methods, hence the error.
References
The project is a FLOSS one and can be found at
https://bitbucket.org/tidalwave/northernwind-src
or
https://github.com/tidalwave-it/northernwind-src
A changeset where the problem can be reproduced is f98e9a89ac70138c1b6bd0d4570a22d59ed71be6. JDK 1.8.0 is required to build the project (even though it doesn't use Java 8 code yet).
The SuperPOM can be found here:
https://bitbucket.org/tidalwave/thesefoolishthings-superpom-src

mvn clean tomcat:run command

When I run "mvn clean tomcat:run" (without specifying any tomcat version) command from command prompt for running my web application, it download tomcat 6.0.29 version dependency as shown below:
org/apache/tomcat/juli/6.0.29/juli-6.0.29.pom
org/apache/tomcat/annotations-api/6.0.29/annotations-api-6.0.29.pom
org/apache/tomcat/catalina-ha/6.0.29/catalina-ha-6.0.29.pom
org/apache/tomcat/coyote/6.0.29/coyote-6.0.29.pom
org/apache/tomcat/tribes/6.0.29/tribes-6.0.29.pom
org/apache/tomcat/jasper-el/6.0.29/jasper-el-6.0.29.pom
org/apache/tomcat/dbcp/6.0.29/dbcp-6.0.29.pom
pom.xml file of the application does not contain any tomcat version it require to run
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
<finalName>esa</finalName>
</build>
So my query is how does it decide to download particular this tomcat version dependency.
Probably the default settings of the tomcat plugin you run.
Try running mvn tomcat:help -Ddetails to see what version of the plugin you use, and how it can be configured.
I think it is an earlier version of the plugin, and you can now use explicit versions, such as
mvn org.apache.tomcat.maven:tomcat6-maven-plugin:2.0:run
mvn org.apache.tomcat.maven:tomcat7-maven-plugin:2.0:run
(or the shorter form)
Seems, you are running the tomcat-maven-plugin from codehaus, whihc has tomcat 6.0.29 built-in. (Seems there was no activity since 2010.)
You should try the tomcat7 plugin from apache.
Regards
Tibor
In command line for maven use --debug option to get explanation of build process. For our case output looks like:
...[DEBUG] Resolving plugin prefix tomcat from [org.apache.maven.plugins, org.codehaus.mojo]
...
[DEBUG] Resolved plugin version for org.codehaus.mojo:tomcat-maven-plugin to 1.1 from repository central (http://repo.maven.apache.org/maven2, releases)...
Actually to explain why we've got tomcat v1.1 without specifying anything about tomcat, remember that maven build process has been customized with build plugins. And each build plugins has own build plugins. So it is enough to examine effective pom file to get clear understanding that almost empty initial pom.xml has quite big effective pom.xml.
To overcome issue just use explicit version of the tomcat plugin.

how to deploy Maven dependencies automatically into JBoss as OSGI bundles?

I have a project that deploys an standalone OSGí Apache ServiceMix application. It has tons of dependencies and it is built with Maven. Now I want to deploy this application into a JBoss AS. I found an interesting Maven plugin called jboss-as-maven-plugin (org.jboss.as.plugins) to deploy anything. I use maven-bundle-plugin (org.apache.felix) to construct my bundles and it works fine, but when I deploy the project bundles, the deployment fails because dependencies are not satisfied.
How can I automatically bundle and deploy all the dependency tree with a Maven goal? Is it possible? My project has dozens of dependencies declared on the pom.xml and some of them are other projects in my workspace.
Currently the only solution to this I know are the Karaf features. You can create a feature file out of your pom dependencies.
I found that jboss seems to support subsystems. That may help to specify the bundles required to run your application. It does not seem to be the OSGi subsystem spec but for jboss this may already help. For OSGi spec 5 there is the standardized subsystem spec which may provide a standard way to do this across containers.
If jboss supports OBR (OSGi bundle repository) then you can limit the number of dependencies you have to specify.
If your application do not use OSGi per see, you may consider packing your application as a WAR which is deployable in JBoss.
Then you would need to use web.xml to bootstrap your application, such as using a Spring XML file.
There is a Camel example as a WAR here: http://camel.apache.org/servlet-tomcat-example.html
You can autoinstall your bundles with org.apache.sling plugin
<plugin>
<groupId>org.apache.sling</groupId>
<artifactId>maven-sling-plugin</artifactId>
<executions>
<execution>
<id>install-bundle</id>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
<configuration>
<slingUrl>http://localhost:8181/system/console/install</slingUrl>
<user>karaf</user>
<password>karaf</password>
</configuration>
</plugin>
you can find detailed pom.xml from Adobe website :https://docs.adobe.com/docs/en/cq/5-6-1/developing/developmenttools/how-to-build-aem-projects-using-apache-maven.html
or http://www.cqblueprints.com/tipsandtricks/build-and-deploy-osgi/build-deploy-osgi-1.html

Generated project with gwt-maven-plugin : eclipse

I created a GWT project with
mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo -DarchetypeArtifactId=gwt-maven-plugin -DarchetypeVersion=2.5.0
Imported the project in eclipse juno.
First error I get is this :
Plugin execution not covered by lifecycle configuration: org.codehaus.mojo:gwt-maven-
plugin:2.5.0:i18n (execution: default, phase: generate-sources)
In the pom file.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test</goal>
<goal>i18n</goal>
<goal>generateAsync</goal>
</goals>
</execution>
</executions>
<!-- Plugin configuration. There are many available options, see
gwt-maven-plugin documentation at codehaus.org -->
<configuration>
<runTarget>dashboard.html</runTarget>
<hostedWebapp>${webappDirectory}</hostedWebapp>
<i18nMessagesBundle>com.farheap.jsi.dashboard.client.Messages</i18nMessagesBundle>
</configuration>
Also the code contains a GreetingServiceAsync that can not be found.
private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
You have two options:
You can add special (non-trivial) org.eclipse.m2e:lifecycle-mapping plugin
configuration to your POM. See here: Why am I receiving a "Plugin execution not covered by lifecycle configuration with GWT" error?
Or mark this issue as to be ignored in Eclipse POM editor, and then call mvn gwt:i18n. You can create a handy short cut launcher for it. Eclipse remembers your decisions what to ignore, it stores it into .settings directory permanently for the project.
In course of typical development localization messages do not change often so the second option is usually more convenient and speeds up build.
This applies for most GWT plugin goals! Even GWT compilation is rarely necessary as DevMode works directly with Java code and not generated JavaScrips. So in practice, you have to call all the goals at least once on the beginning and then live weeks without them; basic Eclipse JDT compilation is sufficient.
If you later decide not to use GWT localization framework in your real app then you can remove goal i18n completely from POM. Calling goal i18n generates file {project}/target/generated-sources/gwt/my/code/client/Messages.java which is required by (vanilla) Sample.java.
Also the code contains a GreetingServiceAsync that can not be found.
Run the build mvn install from command line or Eclipse Run as -> Maven install menu.
In case of command line mvn gwt:generateAsync should be enough. This goal generates {project}\target\generated-sources\gwt\my\code\client\GreetingServiceAsync.java and that is what you missing. Eclipse did not do it for you automatically because it was blocked by previous issue of i18n not being covered by lifecycle configuration. So yes, issues you mention are correlated.

Resources