How to get rid of duplicate class errors in Intellij for a Mavenized project using Lombok - maven

I have a Maven managed Lombok project and I use Intellij. After building, I always get lots of errors in Intellij about duplicate classes because of the generated sources in target/generated-sources/delombok. Is there something I can do to git rid of these errors? Right now I just delete the target folder, but this is really irritating to have to do.
I have the standard configuration in Maven and the Lombok source code in is in src/main/lombok:
<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>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.8.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
</plugin>
<profiles>
<profile>
<id>lombok-needs-tools-jar</id>
<activation>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.8.0</version>
<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>1.8</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>

According to delombok goal documentation: the default output directory is:
${project.build.directory}/generated-sources/delombok
I have found an JetBrains Team member comment stating that:
IDEA automatically excludes the build 'target' folder, providing that there are no generated sources under it, otherwise it excludes all sub-folders but the generated.
If you have some generated code or build artifacts that you want being excluded, you may put it under the 'target' folder.
This means that /generated-sources directory is by default not excluded and if you intend on excluding some files you should place them under parent /target directory and NOT under /generated-sources.
To achieve this you should configure the plugin and provide non-default <outputDirectory>:
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.18.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDirectory>src/main/java</sourceDirectory>
<outputDirectory>${project.build.directory}/delombok</outputDirectory>
<addOutputDirectory>false</addOutputDirectory>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
This will stop IDEA from yielding Duplicate class found in (...) warnings.

I tried Krzusiek's solution but IntelliJ would still mark my source files from src/main/java as duplicated.
After many failed attempts to tweak the lombok-maven-plugin I eventually decided to get rid of the delombok folder after compilation. That folder only server as an intermediary stage for compilation (in my case I needed it to use lombok with AspectJ compiler via the aspectj-maven-plugin) and there's no real need to keep it once your source files have been compiled.
Manually removing the delombok folder after each compilation is a real bummer, so I just configured an additional execution of the maven-clean-plugin which would specifically target the delombok folder.
Your POM should contain:
<build>
<sourceDirectory>${project.build.directory}/generated-sources/delombok</sourceDirectory>
<plugins>
<!-- will delombok source files into /target/generated-sources/delombok -->
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.16.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
<configuration>
<addOutputDirectory>false</addOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
</configuration>
</plugin>
<!-- other plugins bound to compile phase should go here -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<executions>
<execution>
<id>delombok-removal</id>
<phase>compile</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>${project.build.sourceDirectory}/com</directory> <!-- assuming your root package is something like com.mycompany -->
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

The idea is to remove generated-source from sources. I could do it from Project Structure -> Select from the list of packages and in right hand side find the folders that are being used to derive sources for that package. If you find generated-source in that list remove it.

you just need to unmark the folder with generated sources in Intellij and will be fine.

Firstly, you have to apply to Krzysiek's answer - move generated_sources directory under target so it will be /target/generated_sources. The next step is to unmark given directory as generated sources root. Then you have to right click on given project in Intellij, select Maven and then Reload project. After that do the same but this time go Maven -> Generate Sources and Update Folders. If you have multi module project and one module depends on each other i.e. module A depends on B then you have to start with B first.

This solution suggested by Andrey Dernov here worked for me with Maven.
Enable Settings (Preferences on macOS) > Build, Execution, Deployment > Build Tools > Maven > Runner > Enable "Delegate IDE build/run actions to maven" option

Related

Generate Javadoc for multimodule project

I have read everything I can find on solving this and my attempts still fail. The best I can do is to get the Javadoc of exactly one module to show up--the last one built. (For now, I'm not trying to bundle Javadoc into any JARs. I'm also not trying to do anything "site".) I just want to put Javadoc for easy access into a subdirectory under the project root.
Here's what's in my parent pom.xml:
<build>
<plugins>
.
.
.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<noqualifier>all</noqualifier>
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
<destDir>javadoc</destDir>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
What I'm putting into subordinate pom.xml files is identical to the above except for
<goals>
<goal>javadoc</goal>
</goals>
I have played with replacing the <execution> in the parent and sometimes subordinate pom.xml files with:
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
but it makes no difference.
I think the following configuration is the reason your reports get overwritten:
<configuration>
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
</configuration>
All module builds will be written to the same directory, hence overwriting the previous build.
The solution is to use the default output directory and configure the output directory for the aggregated javadoc instead. This way the reactor build will create javadoc output files in each module's target directory. These can then be used by the aggregate goal to be combined.
This can be done by configuring your parent POM as follows:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<!-- Default configuration for all reports -->
<noqualifier>all</noqualifier>
<destDir>javadoc</destDir>
</configuration>
<executions>
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
<configuration>
<!-- Specific configuration for the aggregate report -->
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
<destDir>javadoc</destDir>
</configuration>
</execution>
...
</executions>
</plugin>
...
</plugins>
</build>
(there is no need for any additional configuration in the module POM files)
The aggregated javadoc can now be created by running
mvn compile javadoc:javadoc javadoc:aggregate
(note that the compile or package goal is required for reactor to resolve inter-module dependencies)

Where do generated DEPENDENCIES files come from?

In quite a lot of Apache project there is a file called DEPENDENCIES which is generated from the POM and all POMs of transitive dependencies. However I couldn't find any information about how these files are generated. I suspect there is a Maven plugin for this...
Here is an example:
https://raw.githubusercontent.com/sonatype/maven-demo/master/DEPENDENCIES
How can I generate such a file?
I have made an example to show how this works:
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<resourceBundles>
<resourceBundle>org.apache:apache-jar-resource-bundle:1.4</resourceBundle>
</resourceBundles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The tricky plugin is the maven-remote-resouces-plugin which can handle velocity templates which will to the trick here.

how to run maven war dependency using tomcat:run?

I am using maven for my current projects. Now, I have a war dependency:
<dependency>
<groupId>org.dojotoolkit</groupId>
<artifactId>dojo-war</artifactId>
<version>1.8.1</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
I don't have any problem when I built the war artifact. For this, I have added this plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<overlays>
<overlay>
<groupId>org.dojotoolkit</groupId>
<artifactId>dojo-war</artifactId>
<targetPath>js/dojo-1.8.1</targetPath>
<excludes>
<exclude>WEB-INF/**</exclude>
<exclude>META-INF/**</exclude>
</excludes>
</overlay>
</overlays>
</configuration>
</plugin>
But, when I run the following mvn command mvn tomcat7:run I can not see any javascript resource. It looks like war dependency had not been added.
Could someone help me with that?
Thanks in advance.
Welcome to Stack Overflow Emelendez.
You should read this post : http://webtide.intalio.com/2008/07/dojo-toolkit-maven-repository/
Indeed, the dojo-war dependencies allows you to add some files to your sources, but you must specify some extra actions to include it in the final war.
Dependencies, in Maven, can only be in the language you try to compile (well it's not really exact, but this is enough here). If you want to add other resources (files, images, javascript), contained in a zip/war/targz, you must explicitely extract them. This is what is mentionned in the link I provided previously :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack dojo</id>
<phase>generate-sources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.dojotoolkit</groupId>
<artifactId>dojo</artifactId>
<version>${project.version}</version>
<type>zip</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/dojo</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
(Be careful, I'm not sure that this configuration is exact, your dependencie seems to be dojo-war according to your pom.xml, and not dojo as per doc said)
This will extract dojo libs into output directory, and then into your war.

Maven and copying at test time

How can I have maven copy some resource files from another project right before the junit test cases are run?
I want this because the json files are maintained by the ui team for their testing purposes, so I want to use those same files to run against our layers so that we know we don't break the expected output when we change our code.
One option is to use the maven dependency plugin to selectively "unpack" the files from the project which has those files.
For example say the project in which the resource file is com.foo.bar:myArtifact:jar, so you can do something like
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>unpack</id>
<!-- You could a phase of your choice based on needs -->
<phase>compile</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.foo.bar</groupId>
<artifactId>myArtifact</artifactId>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}</outputDirectory>
<includes>*.json</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
This will copy all .json files (just an example) to the current project's build output directory.
You can refer to the dependency plugin for more configuration options.
Hope this helps.

Maven: JspC should use external JSP-files

We're using Maven 3 and I'm facing a project that has JSP-files and also uses "global" JSP-files stored in a different project. This works nicely when using maven-war-plugin and webResources. All JSP-files find their way into the WAR-file.
The new idea is to pre-compile all the JSPs. The obvious choice is to use jspc-maven-plugin. However, that doesn't include the external JSPs when it compiles the project-local JSPs.
Here's the snippet from the pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jspc-maven-plugin</artifactId>
<executions>
<execution>
<id>jspc</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<warName>${pom.groupId}.${pom.artifactId}-0.0.1-SNAPSHOT</warName>
<webXml>${basedir}/target/jspweb.xml</webXml>
<webResources>
<resource>
<directory>../name.of.external.project/src/global/webapp</directory>
</resource>
</webResources>
</configuration>
</plugin>
The error is
[ERROR] Failed to execute goal org.codehaus.mojo:jspc-maven-plugin:1.4.6:compile (jspc) on project internal.project: JSPC Error: file:C:/workspace/name.of.internal.project/src/main/webapp/WEB-INF/views/show.jsp(2,0) File "/WEB-INF/views/../jspGlobal/jsp-declaration.jspf" not found -> [Help 1]
The jspGlobal-directory would get copied with the <directory>../name.of.external.project/src/global/webapp</directory>-line above.
What's missing to include the external JSPs in JspC?
EDIT: Thanks to prunge's and Raghuram's input I looked deeper into sources and JavaDocs. I noticed that the mentioned sources requires a FileSet which does NOT allow a list of directories. And since sources is also not a list, I see no chance how I can specify more than one JSP-source directory. I even tried to copy the <plugin>-element, but that didn't help. My current situation is this:
<plugin>
<groupId>org.codehaus.mojo.jspc</groupId>
<artifactId>jspc-maven-plugin</artifactId>
<version>2.0-alpha-3</version>
<executions>
<execution>
<id>jspc</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<directory>${basedir}/../name.of.external.project/src/global/webapp</directory>
</sources>
<!-- the later mentioned <sources> gets picked
<sources>
<directory>${basedir}/src/main/webapp</directory>
</sources>
-->
<!-- 1.6 doesn't work!? Something lower than 1.5 seems to be the default -->
<source>1.5</source>
<target>1.5</target>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo.jspc</groupId>
<artifactId>jspc-compiler-tomcat6</artifactId>
<version>2.0-alpha-3</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<warName>${pom.groupId}.${pom.artifactId}-0.0.1-SNAPSHOT</warName>
<webXml>${basedir}/target/jspweb.xml</webXml>
<webResources>
<resource>
<directory>../name.of.external.project/src/global/webapp</directory>
</resource>
</webResources>
</configuration>
</plugin>
Now the external JSPs are compiled into the target-path of the current project. Now I need a way to compile the JSPs of the current project. How do I do this?
BTW, if I switch the <sources> to the line for the current project I get the same error as mentioned earlier.
Perhaps you could try with the latest version of jspc-maven-plugin, which is 2.0-alpha-3. Do note that the usage is a little different from the earlier version.
Looking at the source code of CompilationMojoSupport, I see a sources property of type FileSet. You might be able to configure this in the configuration of the plugin to add additional source directories. It looks like by default it uses ${project.basedir}/src/main/webapp regardless of the configuration of the WAR plugin.

Resources