Mapstruct is not generating implementation for one of my mapper interfaces. Is there a way to know the reason? - mapstruct

I am using mapstruct to map from/to domain objects to DTO
I have more than 20 mappers that are properly being generated.
One of my mappers is no longer being generated, but compilation is successful.
I use maven and i turned on showWarnings flag in the maven-compiler-plugin configuration, however i see no warnings regarding that specific mapper (I do see warnings for other mappers).
Is there a way to get some information from the annotation processor regarding mappers that are not being generated?
My mapper interface (with name changes):
#Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
PersonDTO map(Person entity);
Person map(PersonDTO dto);
}
My Maven configuration:
...
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.3.0.Final</version>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
...
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.3.0.Final</version>
</path>
</annotationProcessorPaths>
<showWarnings>true</showWarnings>
</configuration>
</plugin>

You can do basic tracing (verbose mode) in the upcoming version of MapStruct. Checkout the documentation. You can try to use the latest MapStruct master in your project and see if it gives info on why this is not working.

For me it was a dependency issue.
My Projet A, had a dependency to another jar B, which contained the object from my mapper method.
That dependency B had a dependency C offering mapstruct mapper for many of the attribut of the object.
Somehow in my project A i was overriding explicitly the version of dependency C to an older version.
So it means that some of the Obj attribute from current B version where not matching with the older C mapper.
Mapstruct said nothing, just stopped generating the impl.
Not sure if this is very clear ... But check your dependencies.

Related

How to disable derived flag on generated source code from Mapstruct and how to generate Mapstruct classes only on local PC and not on build server?

First question: Mapstruct generates code to target annotation folder which has a marker "derived". This is ignored by RTC so I'm unable to check in the generated code (don't ask me why I want to do this - I need it). Is there any chance to disable derived marker on gen-folder so generated classes (.java) could be checked into repository?
Second question: Mapstruct classes should be generated on my local machine and not on a build server. How can I configure maven to do it only local?
Thank you in advance.
Currently my pom.xml looks like this since I was not able to configure it the way I need it:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<generatedSourcesDirectory>gen</generatedSourcesDirectory>
<annotationProcessorPaths>
<path>
<groupId>de.......</groupId>
<artifactId>mapstruct_config</artifactId>
<version>${config.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<compilerArg>
-Amapstruct.suppressGeneratorTimestamp=true
</compilerArg>
<compilerArg>
-Amapstruct.suppressGeneratorVersionInfoComment=true
</compilerArg>
<compilerArg>
-Amapstruct.unmappedTargetPolicy=WARN
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
1: gen folder has no derived marker
2: annotationProcessor works only on a local machine
I presume that the dervied marker comes from Eclipse (IntelliJ also does that). Most probably you would have to manually disable that in your IDE, not sure if it will always work as usually those locations are applied from Maven itself.
In order for the Annotation Processor to run only locally I think that you would need to add a custom maven profile where you would configure the annotationProcessorPaths, the default one (on the CI) won't have the annotationProcessorPaths and thus won't run the annotation processing

Spring Cloud Contract issues retrieving stubs from Artifactory

I have tests for two consumers and a producer working fine offline but the consumer tests fail when I change them for retrieving the stubs from Artifactory.
This is the code for working offline:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = ContractTestConfiguration.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
#AutoConfigureStubRunner(ids = {"com.mycompany:service-name:+:stubs"}, workOffline = true)
#ImportAutoConfiguration(org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration.class)
#DirtiesContext
public class MyContractTest
And this is for online:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = ContractTestConfiguration.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
#AutoConfigureStubRunner(ids = {"com.mycompany:service-name:+:stubs"}, repositoryRoot = "https://artifactory.companyname.com/artifactory/artifacts-snapshot-local")
#ImportAutoConfiguration(org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration.class)
#DirtiesContext
public class MyContractTest {
I get this error:
Exception occurred while trying to download a stub for group [com.mycompany] module [service-name] and classifier [stubs] in [remote0 (https://artifactory.mycompany.com/artifactory/artifacts-snapshot-local, default, releases+snapshots)]
org.eclipse.aether.resolution.ArtifactResolutionException: Could not find artifact com.mycompany.domain:service-name:jar:stubs:1.6.0-SNAPSHOT
I have looked in Artifactory and in https://artifactory.mycompany.com/artifactory/artifacts-snapshot-local and the stubs jar appears there. I have done a mvn install of the producer and when I run the tests again I get this error "The artifact was found in the local repository but you have explicitly stated that it should be downloaded from a remote one".
I have also tried adding to the consumers a dependency on the stubs of the producer but I get similar errors. And I would prefer to avoid it because it would add a dependency with the specific version of the producer:
<dependency>
<groupId>com.companyname</groupId>
<artifactId>service-name</artifactId>
<classifier>stubs</classifier>
<version>1.6.0-SNAPSHOT</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
I have added this to the POM file of the producer:
<spring.cloud.contract.verifier.skip>true</spring.cloud.contract.verifier.skip>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>stub</id>
<goals>
<goal>single</goal>
</goals>
<phase>prepare-package</phase>
<inherited>false</inherited>
<configuration>
<attach>true</attach>
<descriptor>${basedir}/src/assembly/stub.xml</descriptor>
</configuration>
</execution>
</executions>
</plugin>
And this is the content of the file stub.xml that is under src/assembly:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>stubs</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/java</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**com/companyname/projectname/*.*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/classes</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**com/companyname/projectname/*.*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/snippets/stubs</directory>
<outputDirectory>META-INF/${project.groupId}/${project.artifactId}/${project.version}/mappings</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
<fileSet>
<directory>${basedir}/src/test/resources/contracts</directory>
<outputDirectory>META-INF/${project.groupId}/${project.artifactId}/${project.version}/contracts</outputDirectory>
<includes>
<include>**/*.groovy</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Any idea of what I am missing? Thanks in advance
I have looked in Artifactory and in https://artifactory.mycompany.com/artifactory/artifacts-snapshot-local and the stubs jar appears there. I have done a mvn install of the producer and when I run the tests again I get this error "The artifact was found in the local repository but you have explicitly stated that it should be downloaded from a remote one".
This happens when you install a stub locally, then try to download it from artifactory but SHAs are different, so Aether (engine that downloads stubs) picks the local one. In this case we throw an exception cause you wanted to download the stub from a remote location and not take it from the local one.
Exception occurred while trying to download a stub for group [com.mycompany] module [service-name] and classifier [stubs] in [remote0 (https://artifactory.mycompany.com/artifactory/artifacts-snapshot-local, default, releases+snapshots)]
org.eclipse.aether.resolution.ArtifactResolutionException: Could not find artifact com.mycompany.domain:service-name:jar:stubs:1.6.0-SNAPSHOT
This looks like in Artifactory you had the entry in some Maven metadata that the latest jar is 1.6.0-SNAPSHOT but the JAR is no longer there. Can you double check that it's actually there?
I have also tried adding to the consumers a dependency on the stubs of the producer but I get similar errors. And I would prefer to avoid it because it would add a dependency with the specific version of the producer:
That only proves that you have something messed up with your artifactory / project settings. Do things still don't work if you hardcode versions?
UPDATE:
If your artifactory instance requires credentials or is behind a proxy you can use these values:
https://github.com/spring-cloud/spring-cloud-contract/blob/v1.1.4.RELEASE/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerProperties.java#L72-L87
You can provide the stubrunner.username, stubrunner.password, stubrunner.proxyHost and stubrunner.proxyPort
Can stubrunner.username and stubrunner.password be provided in the #AutoConfigureStubRunner annotation? I have tried the following:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
#AutoConfigureStubRunner(ids = "com.mycompany.myproj:myservice:+:stubs:8100",
repositoryRoot = "http://artifactory.mycompany.com/artifactory/libs-snapshot-local",
properties = {"stubrunner.username=myusername", "stubrunner.password=mypassword"},
stubsMode = StubRunnerProperties.StubsMode.REMOTE)
#DirtiesContext
class MyApiContractsVerificationTest {
...
}
The credentials are correct, and the stubs are correctly generated and deployed into the remote Artifactory repository. The tests run fine if I configure them to look in the local .m2/repository (removing the "repositoryRoot and "properties" annotation args), but with the above configuration I get the following error:
Could not find metadata com.mycommany.myproject:myservice/maven-metadata.xml in local (/Users/myname/.m2/repository),
org.eclipse.aether.transfer.MetadataTransferException: Could not transfer metadata com.mycommany.myproject:myservice/maven-metadata.xml from/to remote0 (http://artifactory.mycompany.com/artifactory/libs-snapshot-local): **Unauthorized (401)**]
...
I do clean the local .m2/repository of the stubs before I run the tests with the remote mode enabled, so there is no conflict.
Am I incorrectly providing the username and password? Is something incorrect or missing in the configuration?

p2-maven-plugin -- bundle conflicts with other existing bundle

I’m starting to use the p2-maven-plugin in order to integrate non-OSGi JARs into our project in a (hopefully) convenient manner.
I have an artifact which I want to OSGi-ify, called com.thirdparty.artifact. I’m current using p2-maven-plugin’s standard configuration, and I list my artifact in the pom.xml like so:
<artifact><id>com.thirdparty:artifact:1.2.3</id></artifact>
This artifact has a transitive dependency called com.thirdparty:library:2.5, which exports a package com.thirdparty.library which is in turn imported by com.thirdparty:artifact. When I run mvn p2:site, I get a P2 site which contains com.thirdparty:artifact:1.2.3 and com.thirdparty:library:2.5 -- all fine so far.
Now, things are turning messy. My existing target platform already contains an artifact called com.othervendor:library (different vendor, it’s there and I cannot change that), which also exports the very same package com.thirdparty.library (but an entirely different version).
At runtime, the OSGi/Eclipse black magic (which I’ll probably never fully understand) tries to resolve com.thirdparty:artifact’s dependency on the package com.thirdparty.library using the com.othervendor:library and not my provided com.thirdparty:library:2.5 -- and I’m obviously in trouble. Here’s a visualization of my situation:
Being absolutely no OSGi rocket scientist, my first idea was to inspect the MANIFEST.MF in com.thirdparty:artifact. Beside others, this shows the following:
Import-Package: com.thirdparty.library
So, this obviously just tells com.thirdparty:artifact to import this package from some bundle, and OSGi/Eclipse thinks “okay, com.othervendor:library is more adequate than com.thirdparty:library”.
There seem to be two methods of narrowing down the dependencies to actually use. However: I’m not sure (a) how to integrate them into my p2-maven-plugin workflow, and (b) I do not understand why p2-maven-plugin does not automatically require the concrete package version in the Import-Package directive (this information is after all already specified in the source pom.xml).
Probably I’m not seeing the forest for the trees here. So any general advice beside my questions above is very welcome!
[edit] Here’s my pom.xml (the concrete library which I’m about to OSGi-ify is Selenium):
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>com.example.p2dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.reficio</groupId>
<artifactId>p2-maven-plugin</artifactId>
<version>1.2.0</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<artifacts>
<artifact><id>org.seleniumhq.selenium:selenium-java:3.4.0</id></artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
[edit2] Problem seems to be solved, it seems, the issue was an additional package which was only exported by com.othervendor:library.

Why does maven ignore the add-source-goal? [duplicate]

This is a snippet of my pom file.
....
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
......
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
I use it successfully with the command
mvn install
But, when I try to enclose it into the "pluginManagement" tag, the maven-dependency-plugin stops working when I launch the install goal.
Why does the "pluginManagement" tag change the build behavior? Or should I use another goal or option?
You still need to add
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
</plugins>
in your build, because pluginManagement is only a way to share the same plugin configuration across all your project modules.
From Maven documentation:
pluginManagement: is an element that is seen along side plugins. Plugin Management contains plugin elements in much the same way, except that rather than configuring plugin information for this particular project build, it is intended to configure project builds that inherit from this one. However, this only configures plugins that are actually referenced within the plugins element in the children. The children have every right to override pluginManagement definitions.
The difference between <pluginManagement/> and <plugins/> is that a <plugin/> under:
<pluginManagement/> defines the settings for plugins that will be inherited by modules in your build. This is great for cases where you have a parent pom file and would like to avoid having to copy the same code for the configuration of the plugin over to each of these modules.
<plugins/> is a section for the actual invocation of the plugins. It may or may not be inherited from a <pluginManagement/>.
You don't need to have a <pluginManagement/> in your project, if it's not a parent POM. However, if it's a parent pom, then in the child's pom, you need to have a declaration like:
<plugins>
<plugin>
<groupId>com.foo</groupId>
<artifactId>bar-plugin</artifactId>
</plugin>
</plugins>
Notice how you aren't defining any configuration. You can inherit it from the parent, unless you need to further adjust your invocation as per the child project's needs.
For more specific information, you can check:
The Maven pom.xml reference: Plugins
The Maven pom.xml reference: Plugin Management
You use pluginManagement in a parent pom to configure it in case any child pom wants to use it, but not every child plugin wants to use it. An example can be that your super pom defines some options for the maven Javadoc plugin.
Not each child pom might want to use Javadoc, so you define those defaults in a pluginManagement section. The child pom that wants to use the Javadoc plugin, just defines a plugin section and will inherit the configuration from the pluginManagement definition in the parent pom.
pluginManagement: is an element that is seen along side plugins. Plugin Management contains plugin elements in much the same way, except that rather than configuring plugin information for this particular project build, it is intended to configure project builds that inherit from this one. However, this only configures plugins that are actually referenced within the plugins element in the children. The children have every right to override pluginManagement definitions.
From http://maven.apache.org/pom.html#Plugin%5FManagement
Copied from :
Maven2 - problem with pluginManagement and parent-child relationship
<pluginManagement> just like <dependencyManagement> are both used to share only the configuration between a parent and it's sub-modules.
For that we define the dependencie's and plugin's common configurations in the parent project and then we only have to declare the dependency/plugin in the sub-modules to use it, without having to define a configuration for it (i.e version or execution, goals, etc). Though this does not prevent us from overriding the configuration in the submodule.
In contrast <dependencies> and <plugins> are inherited along with their configurations and should not be redeclared in the sub-modules, otherwise a conflict would occur.

AspectJ Maven Plugin <weaveDependency>

I am trying to use aspectj maven plugin in our project that has multiple modules. Following the instructions given in this link http://mojo.codehaus.org/aspectj-maven-plugin/weaveJars.html
I am using #Aspectj annotation. My aspect is in a separate maven module called
artifactId - consumer
And the class whose method i want to intercept or advice is in
artifactId - producer
I have added the following configuration in the pom file of the consumer module:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<showWeaveInfo>true</showWeaveInfo>
<weaveDependencies>
<weaveDependency>
<groupId>com.home.demo</groupId>
<artifactId>producer</artifactId>
</weaveDependency>
</weaveDependencies>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
Also added "producer" as a dependency in the same pom file.
When i am doing mvn clean install for the consumer module the following information comes in the console.
[INFO] [aspectj:compile {execution: default}]
[INFO] Join point 'method-execution(void com.home.demo.producer.messaging.MomServiceEndpointListener.handle(com.home.messaging.service.MessageContext, com.home.messaging.service.MessageContext))' in
Type 'com.home.demo.producer.messaging.MomServiceEndpointListener' (MomServiceEndpointListener.java:21) advised by before advice from 'com.home.demo.ods.app.OdsConsumer' (OdsConsumer.java:38)
But while executing the application, it's not working. The aspect is not getting invoked.
I am not able to understand whether i am missing something.
Also i am having confusion whether the plugin configuration shown above should be in which module consumer(where my aspects are) or producer.
The problem is that weaveDependencies act like sources only.
Your consumer module takes original "sources" from weaveDependencies (producer), weaves them with aspects and put weaved classes into consumer(!!!) target/classes.
Therefore, producer artifact never knows about aspects and you use it unchanged.
You have to re-build a producer jar using classes from consumer/target/classes.
I don't think it's convenient, so i left my attempts to use this plugin in this way.
Also, several weaveDependencies will be merged into one scrap-heap of classes.
You better try Aspects from your external jar dependency and plugin config that is built into producer.