Spring Maven mutimodule project with common test resources not picking up properties - spring

I have a multimodule Spring Maven project with structure:
Parent
Child_A
Child_B
In Child_A I create a common test-jar as follows:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
and I want to use it in Child_B and Parent so I added the dependency as follows:
<dependency>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>1.0.0</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
Now in Child_B I can access the classes which are in the test-jar, but for some reason, I can't access the properties file. I looked in the jar and the properties file was there.
I Child_A I have a common test class which has the following annotations:
#RunWith(SpringRunner.class)
#WebAppConfiguration
#SpringBootTest
#Transactional
#Getter
and also I have TestMainClass there which is same as normal Spring main class what extends SpringBootServletInitializer.
I have read many post here and they all refer to creating the test-jar and all should work but still for some reason I cannot access the properties.
What am I missing?

Related

Using Spring Boot without the parent POM [duplicate]

Is there a specific recommended approach to the inclusion of the spring-boot parent pom into projects that already have a required parent POM?
What do you recommend for projects that need to extend from an organizational parent (this is extremely common and even something many/most projects published to Maven central depending on the feeder repos they come from). Most of the build stuff is related to creating executable JARs (e.g. running embedded Tomcat/Jetty). There are ways to structure things so that you can get all the dependencies without extending from a parent (similar to composition vs. inheritance). You can't get a build stuff that way though.
So is it preferable to include all of the spring-boot parent pom inside of the required parent POM or to simply have a POM dependency within the project POM file.
Other options?
TIA,
Scott
You can use the spring-boot-starter-parent like a "bom" (c.f. Spring and Jersey other projects that support this feature now), and include it only in the dependency management section with scope=import.That way you get a lot of the benefits of using it (i.e. dependency management) without replacing the settings in your actual parent.
The 2 main other things it does are
define a load of properties for quickly setting versions of dependencies that you want to override
configure some plugins with default configuration (principally the Spring Boot maven plugin). So those are the things you will have to do manually if you use your own parent.
Example provided in Spring Boot documentation:
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Update 2022-05-29 with 1.5.9.RELEASE.
I have full code and runable example here https://github.com/surasint/surasint-examples/tree/master/spring-boot-jdbi/9_spring-boot-no-parent (see README.txt to see that you can try)
You need this as a basic
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springframework.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
But that is not enough, you also need explicitly define goal for spring-boot-maven-plugin (If you use Spring Boot as parent, you do not have to explicitly define this)
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${springframework.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Otherwise you cannot build as executable jar or war.
Not yet, if you are using JSP, you need to have this:
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
Otherwise, you will get this error message:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.2:war (default-war) on project spring-boot-09: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executi
ng in update mode) -> [Help 1]
NO NO , this is still not enough if you are using Maven Profile and Resource Filter with Spring Boot with "#" instead of "${}" (like this example https://www.surasint.com/spring-boot-maven-resource-filter/). Then you need to explicitly add this in
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
And this in
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<delimiters>
<delimiter>#</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
See the example in the link https://www.surasint.com/spring-boot-with-no-parent-example/.
As per Surasin Tancharoen's answer, you may also want to define maven surefire plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
and possibly include fail-fast plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>

Entity mapping to DTO with DI with MapStruct

I am new in mapstruct and I am using spring as DI I follow up MapStruct documentation page regarding DI containers section 4.2 I tried to map my entity to dto as below :
#Mapper(componentModel = "spring")
public interface CustomerMapper {
#Mapping(source = "registered",target = "activeProfile")
CustomerDto customerToCustomerDto(Customer customer);
}
when i run mvn install i got this error :
java:27: error: No property named "registered" exists in source parameter(s).
#Mapping(source = "registered",target = "activeProfile")
my entity using lombok and I am sure there is registered field
please help
You don't have to to remove Lombok.
You can setup it to work before MapStruct as was described here by ahus1
https://github.com/mapstruct/mapstruct/issues/510
<!-- first de-lombok the sources to make getters/setters visible for mapstruct,
but *DON'T'* add the output directory to the sources, as we will only need it for mapstruct processing -->
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>${org.projectlombok.maven.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
<configuration>
<sourceDirectory>src/main/java</sourceDirectory>
<addOutputDirectory>false</addOutputDirectory>
<outputDirectory>${project.build.directory}/delombok</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- use the de-lomobok files to create the necessary mappers -->
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>2.2.4</version>
<configuration>
<defaultOutputDirectory>
${project.build.directory}/generated-sources/mapstruct
</defaultOutputDirectory>
<processors>
<processor>org.mapstruct.ap.MappingProcessor</processor>
</processors>
<sourceDirectory>
${project.build.directory}/delombok
</sourceDirectory>
</configuration>
<executions>
<execution>
<id>process</id>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- now take the original sources together with the created mappers to the compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<annotationProcessors>
<annotationProcessor>lombok.launch.AnnotationProcessorHider$AnnotationProcessor</annotationProcessor>
</annotationProcessors>
</configuration>
</plugin>
I've solved the problem using annotationProcessors in pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
I removed lombok from Entity and created setters /getters manually and worked well
Neither you have to remove lombok from your project nor you have to mess up the maven compiler plugin. You just have to declare the lombok dependency before you declare the mapstruck dependency in your pom. With this order maven is able to de-lombok your classes, before mapstruct referes to the getters and setters. This is possibly a feature of maven's dependency mediation.
Dependency mediation - this determines what version of a dependency
will be used when multiple versions of an artifact are encountered.
Currently, Maven 2.0 only supports using the "nearest definition"
which means that it will use the version of the closest dependency to
your project in the tree of dependencies. You can always guarantee a
version by declaring it explicitly in your project's POM. Note that if
two dependency versions are at the same depth in the dependency tree,
until Maven 2.0.8 it was not defined which one would win, but since
Maven 2.0.9 it's the order in the declaration that counts: the first
declaration wins.
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Transitive_Dependencies
The issue is, that Lombok generated properties are not visible to JSR-269 annotation processors. It uses internal api to modify the source elements directly instead of generating new artifacts from the annotated source files Therefore any annotation processor that relies on existence of getter/setter methods will not see them in the source code when it gets executed. Javac will pass the ,,original" source code to the annotation processor(in our case Mapstruct) without any modifications done by Lombok.
Right now the most clean solution how to get both of them working side-by-side is to move the Lombok annotated types and mappers into 2 separate projects. See an official example in Mapstruct repo.

Junit test cases for multiple dependent project in POM.xml

I have a project Test-A, in this I have junit test class for the application.
Now, I have another project called Test-B, in this I have junit test class for the application.
Test-B, I have included project-A i.e modified POM.xml and included as:
POM.xml:
<dependency>
<groupId>com.abc.test-A</groupId>
<artifactId>TestA</artifactId>
<version>1.7</version>
<scope>test</scope>
</dependency>
question:
When I run mvn test for Test-B project, this has to run Test-A junit test files also. how can I run this kind of tests?
I am junit 4.9 version.
You will have to use the Maven Source Plugin to package the test source.
Here is an example for the build plugin to package the test source when you install or deploy the project:
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>test-jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
You will have to add the dependency for the tests as a test-jar type:
<dependency>
<groupId>com.abc.test-A</groupId>
<artifactId>TestA</artifactId>
<version>1.7</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
Now you have access to the tests from artifact TestA that you can run directly.
Running tests for your project B will not run tests for any dependency. For example your project would also have a dependency to junit. You don't expect those tests to run.

Maven failsafe plugin will not run test classes annotated with JUnit Category

I have an interface like this:
public interface IntegrationTest {
}
I configure the failsafe plugin like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.14</version>
<configuration>
<groups>acme.test.IntegrationTest</groups>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
If I then create an integration test like this
#Category(IntegrationTest.class)
public class ExampleClassIntegrationTest {
#Test
public void slow_and_painful_test() {
This test will not run.
If I however name the class according to the Inclusions and Exclusions of Tests
**/IT*.java
**/*IT.java
**/*ITCase.java
Like so:
#Category(IntegrationTest.class)
public class ExampleClassIT {
#Test
public void slow_and_painful_test() {
The test runs fine. Why do I have to name the test AND have an annotation when i use the groups-tag? Am I missing something? The documentation on using JUnit states that you can use the Category annotation at the class level.
Thats because these are the default java classes which fail safe plugin includes when executed.
You can however over ride this in your pom with tag :
E.g
<includes>
<include>**/*.java</include>
</includes>
To include all the java files.
You should either add JUnit as a dependency (>4.8) which is already done or in particular add the following to your failsafe-plugin configuration:
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.14.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
</plugin>
[...]
</plugins>
But i assume it will not change the situation.

"test-utils" project with maven - how to manage dependencies

Let's suppose that I have a bunch of code that I need across a lot of projects, but just in tests.
So, I want to create a separated maven project for it, for example, carlos-test-utils, and ad it as a test dependency in my projects.
But, in my carlos-test-utils project, I also need JUnit. So, I add it as a test dependency, which obviously doesn't work, because I put my code in src/main/java.
I would like to hear which is the best way to deal with this kind of thing.
Put deps as provided?
Some dirty tricky thing to copy .java files across the projects?
Any other thing?
You can manage that via the maven-jar-plugin which should be used for such cases in the following way:
This should be done in the module/project which should provide the test classes and
the code should be put in the usual folder for test code src/test/java and not in src/main/java. All the dependencies your Test code needs should be added as usual dependencies with scope test.
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
...
</project>
In the project you like to use the test dependencies just use it like this:
<project>
...
<dependencies>
<dependency>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<type>test-jar</type>
<version>version</version>
<scope>test</scope>
</dependency>
</dependencies>
...
</project>

Resources