Maven, Lombok and Eclipse - Meaningful Integration Pattern - java

So, I've been wanting to use Lombok for a while - and I'm finally starting a project where I will be able to use it. The important thing to note is that this will be a large, enterprise-grade application and thus the integration patterns used have to be meaningful, with as few hacks as possible.
So I've taken a look at the lombok-maven-plugin, and the whole delombok fudge. I understand this is going to duplicate all my code, and expand the lombok annotations where present. This gives me a second set of generated .java files that need to be used by maven during compilation.
However, by generating these new source files - eclipse picks them up and attempts to pull them into my project. Thus it fires off a million (OK, slight exaggeration) errors about duplicate classes.
Some solution suggest I change the <sourceDirectory> in my POM. This makes things no better, as a mvn eclipse:eclipse will now completely omit my src/main/java java directory from the project - only showing me the output from the delombok process.
Then come the suggestions that I need to use one profile to compile / package the project, and another to mvn eclipse:eclipse. This is not an acceptable solution, as I’m having to spend enough time maintaining / explaining my already complex maven setup – without having to introduce an entire new profile (in addition to my existing profiles).
I’m hoping for some inspiration to save me from writing off Lombok for my project. It’s a great tool to reduce boilerplate code, but it simply doesn’t seem ready for prime-time enterprise usage – which I find very disappointing :-(
The following is my current POM:
<build>
<sourceDirectory>target/generated-sources/delombok</sourceDirectory>
<testSourceDirectory>target/generated-test-sources/delombok</testSourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.12.2.0</version>
<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>1.7</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
<executions>
<execution>
<id>delombok</id>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
<configuration>
<encoding>UTF-8</encoding>
<addOutputDirectory>false</addOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
</configuration>
</execution>
<execution>
<id>test-delombok</id>
<phase>generate-test-sources</phase>
<goals>
<goal>testDelombok</goal>
</goals>
<configuration>
<encoding>UTF-8</encoding>
<addOutputDirectory>false</addOutputDirectory>
<sourceDirectory>src/test/java</sourceDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Which is currently only putting the delomboked code in my eclipse project.
Final note - I'm also quite frustrated that I have to manually install lombok on all the eclipse instasnces we're going to use. Mostly because it's me who will get the phonecall from all the developers that can't get it working. I get why it's not as simple as mvn eclipse:eclipse but I still wanted to note my dissapointment. If we had to manually set up every library for use on each developer's machine, we'd be back in the pre-maven days.

We are successfully using lombok in our project for 1.5 years now. We're not using any delombokification, but instead have lombok as a provided dependency like so
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>0.11.0</version>
<scope>provided</scope>
</dependency>
That's all it needs. We can use the lombok annotations and they are recognized by both eclipse and maven builds. This is even compatible with EclEmma in eclipse, which marks the annotations as (un)covered, when the respective generated code is(n't).
You have to install it on every Eclipse instance manually, since most of the JDT isn't open for eclipse plugins to modify. That's a technical restriction the lombok developers cannot lift. Anyways, the installer is quite simple and never failed me so far.

You don't necessarily need to use lombok-maven-plugin to take advantage of Lombok. As I understand, the delombofication that the plugin does is meant to allow things like code coverage and javadoc to have a full version of the code. Even then, the process would only occur at, say, Javadoc building time.
The question is if your project can live without that. If yes, then just adding lombok as Maven dependency is all you need.
In Eclipse you'll indeed need to install it. Note that the fact the Lombok is still kind of experimental, is perhaps of the reasons it's not included in Eclipse by default.

Related

How to reference dependencies in license documentation

I'm working on a commercial project which uses many open source libraries as its foundation. It's a Java project and we use maven to resolve dependencies. This is great but ... the companies to whom we want to sell our software are traditionally conservative about what they allow to run on site and will want a full inventory of all third party libraries used. Now I can get the list by looking at our project's pom files to find our first order dependencies and then I suppose use the magic of maven to trace all the transitive dependencies. It will be a long list however and one which is likely to change as we move from version to version of any of the third party packages.
Is there an established approach to documenting this kind of dependency tree?
Is there an accepted "lawyer friendly" form of describing software dependencies that I should be adopting?
Any suggestions would be most welcome!
Cheers
Rich
http://maven.apache.org/plugins/maven-project-info-reports-plugin/license-mojo.html
(a part of http://maven.apache.org/plugins/maven-project-info-reports-plugin/_ )
and
Use license-check-maven-plugin
<build>
<plugins>
<plugin>
<groupId>org.complykit</groupId>
<artifactId>license-check-maven-plugin</artifactId>
<version>0.5.3</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>os-check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Reference: https://github.com/mrice/license-check

How do I fail a Maven build from inside Java logic?

I am developing a project in which I would like to use Maven to execute a Java Main class as part of the build process. The Main class's job is to validate that some given (currently hardcoded) files are valid RAML files. In a perfect world, I would like the build to be able to fail the build from within this class's logic, if they are invalid, and have that failure report back to the terminal with the "[BUILD FAILURE]" message just like maven does natively.
I added tho org.codehaus.mojo.exec-maven-plugin plugin to my POM, which is allowing me to execute the Java Main class I mentioned earlier. That section of the POM looks like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.example.ubunfu.MainClass</mainClass>
<arguments>
<argument></argument>
</arguments>
<cleanupDaemonThreads>false</cleanupDaemonThreads> <!-- Prevents thread hanging -->
</configuration>
</execution>
</executions>
</plugin>
However, I'm not sure how to signal from the logic inside of MainClass that the build should fail - if that's necessary. I read about the org.apache.maven.plugins.MojoFailureException in the Maven - Guide to Developing Java Plugins. There it seems to say that I can throw one of these and it will fail the build like I'm hoping for.
I'm not sure what I need to do in order to have the MojoFailureException class available to me inside MainClass. I haven't been able to find a JAR or anything, but if I understand how Maven works, this should be fixed with some kind of addition to the POM, not a JAR.
If you have any insight for me on this, I'd really appreciate it.
-Ryan
It appears that throwing any exception will cause the build to fail. See this answer.
To get access to MojoFailureException, add the following dependency:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.3.3</version>
</dependency>
Hint: According to Exec Maven Plugin, Usage <configuration> resides outside of <executions>.
"I would like the build to be able to fail the build from within this class's logic" → Simply throw new RuntimeException().

IntelliJ IDEA - Error: java: package foo does not exist

I have a project in IntelliJ IDEA that consists of both Java and Groovy classes. These classes are contained in folders "groovy" and "java" that I've marked as source folders. I have many Java classes that import classes from the "groovy" source folder, but when I try running them, I consistently get the error "java: package foo does not exist". Package "foo" exists directly under the "groovy" folder, so this should be working. I included a visual below. (I'm trying to avoid any specific details. I may or may not be working on a top secret Area 51 project.)
Structure visual:
project-folder
|
-src
|
-main
|
-groovy (marked as source)
||
|-foo
| |
| -bar.groovy
-java (marked as source)
|
- java class that imports "foo.bar"
Error:
java: package foo does not exist
Things that don't work:
Taking everything under "framework" and placing them directly under "groovy" folder. Results in "Cannot resolve symbol bar"
Unmavenizing project and rebuilding
You should not have to "unmavenize" your project. (Although I understand the troubleshooting reasoning for suggesting you do such.) I suspect the issue is a corrupted cache or index. Go to File > Invalidate Cache. Select to invalidate the cache and then restart IDEA. Let IDEA re-index the project. Things should be fine. If not, check that 1) you are using the latest version of IDEA (12.1.5) and 2) the latest version of the Groovy plug-in (File > Settings > [IDE Settings] > Plugins).
When you do use maven, you will need to identify the "groovy" directory as an additional source directory in your POM. If you do not, when IDEA re-imports the project (i.e. re-syncs to the POM), it will drop the groovy directory as a source since by default maven does not consider it a source. How you do this depends on what plugin you use. Since GMaven is no longer maintained, I've been using the groovy-eclipse-compiler plugin. If you use that plug-in, the plug-in will automatically include src/main/groovy as a source (as long as there is at least one java or groovy file in src/main/java). However, IDEA does not pick that directory up and include it as a source as well. That means if you manually (or IDEA automatically) runs a maven re-import, your src/main/groovy directory will get unmarked as a source, and IDEA will show compile errors. You need to specify the additional directory. You can use the build-helper-maven-plugin to do this as the groovy-eclipse-compiler documentation recommends.
Here's the meat & potatoes of a POM for a working Java/Groovy project:
<properties>
<groovy.version>2.1.5</groovy.version>
<groovy-eclipse-compiler.version>2.8.0-01</groovy-eclipse-compiler.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<compilerId>groovy-eclipse-compiler</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-compiler</artifactId>
<version>${groovy-eclipse-compiler.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-batch</artifactId>
<version>2.1.5-03</version>
<scope>compile</scope>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/groovy</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/groovy</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy.version}</version>
</dependency>
</dependencies>
Restart IntelliJ :-) Dumb, but that's what worked for me. No idea what was causing the issue, but I'm glad it's fixed. Hopefully that helps someone else too.
I had the similar problem. In my case, groovy compilation logged RuntimeException as warning. This is because of No suitable classloader found for grab.
After I fixed this issue, groovy sources were successfully compiled and Java classes were able to see them on the classpath.

How to check project boundaries access in Maven projects

I have a set of Maven projects and I'd like to define access rules.
For example, projects Database and Cache may only be accessed by project DataLayer, but not from project UiLayer. I'm speaking in terms of maven projects, but a package level access verification may also work, as long as it's easy to integrate into maven projects.
I've looked at Macker, which has a nice set of features such as access control b/w java packages, style checking etc, but have been having hard time tying that into a set of maven projects.
There's the macker-maven-plugin, which is still under development, and I've been able to make it work for me, but I'm afraid it's not going to serve me well.
This plugin runs verifications on all project's classes.
This means that I'll have to have macker-rules.xml defining access rules in each and every maven project from now on in order to make sure rules are not broken. This looks like a maintenance nightmare.
So - did I miss something with usage of macker-maven-plugin? Perhaps I'm not using it correctly.
I have no experience with JDepend, but from short reading it looks like the thin version of macker. There is a jDepend maven plugin, but it's functionality is merely generating reports about usage and statistics, but what I really need is something else, an access check which fails the build if it fails.
Can someone suggest a better alternative for project access checks or package access checks for maven projects?
Thanks
I think you are looking for banned dependencies from maven-enforcer-plugin.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<exclude>org.apache.maven</exclude>
<exclude>org.apache.maven:badArtifact</exclude>
<exclude>*:badArtifact</exclude>
</excludes>
<includes>
<!--only 1.0 of badArtifact is allowed-->
<include>org.apache.maven:badArtifact:1.0</include>
</includes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
If you split your Maven project into subprojects and structure the APIs right, it might be possible to implement your access constraints as a side-effect of the subproject dependencies.

In Maven2, is there a way to scope a dependency to "package only" and keep it off the test classpath?

Setup
I'm packaging a WAR with a number of legacy jar dependencies in it (for the sake of keeping this simple, they can not possibly be altered or excluded from the deployed WAR).
Issue
Including either or both of two of these jars will cause inexorable errors at test-time. If I exclude the dependencies altogether, the tests pass happily, but the WAR will lack real-world runtime classes it needs.
Hope
Maven2 offers compile, test, runtime, system, and provided scopes. Sadly, none of these will be included in the assembly but kept off the test classpath. My hope is that I'm missing some obvious way to handle this case entirely within the dependency management feature.
Fear
I'll have to use the assembly plugin to copy these problem jars into the target. I don't want to have to skirt the dependency management system to copy jars in the clear into the target, as I don't want to manage these jars outside the internal repository.
Thoughts? Alternatives?
Of course it figures that I'd come across a potential solution to this moments after posting a question. It appears that the copy goal of the dependency plugin may handle this. Going to try this out now: http://maven.apache.org/plugins/maven-dependency-plugin/usage.html
Edit: Turns out that this worked fine for my needs, snippet below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactItems>
<artifactItem>
<groupId>group</groupId>
<artifactId>artifact</artifactId>
<version>version</version>
<type>jar</type>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</plugin>
Break the test classes out of the jar file into a separate jar which is only for tests, and add an exclusion to the dependency on the jar with the legacy dependencies.

Categories

Resources