How does m2e decide if project has java nature? - java

I'm using a special Maven plugin which provides a custom packaging type and defines a special lifecycle mapping. But it is still a Java-like project so I'd like Eclipse (with m2e plugin) to import the project as a Java project (With java nature in .project file). But it always imports it as a simple project without java nature. I always have to add the java nature to the .project file manually.
I also tried keeping packaging type "jar" and changed the plugin to provide a custom lifecycle mapping for "jar". But still m2e doesn't recognize it as a java project.
So how does m2e decide if it must enable the Java nature in the project or not? Or is there some special m2e configuration I can put into the Maven pom.xml to tell m2e that my project is a java project?

Found it! No need to change the packaging type to "JAR". I only need to include the maven-compiler-plugin in the lifecycle mapping:
<!DOCTYPE component-set>
<component-set>
<components>
<component>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<role-hint>custom</role-hint>
<implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
<configuration>
<phases>
<compile>
org.apache.maven.plugins:maven-compiler-plugin:compile,
my.custom.plugin:compile
</compile>
</phases>
</configuration>
</component>
</components>
</component-set>
Now m2e adds the java nature to the project when importing it and still executes the custom life cycle.

try adding maven eclipse plugin to your POM file.
> <plugin>
> <groupId>org.apache.maven.plugins</groupId>
> <artifactId>maven-eclipse-plugin</artifactId>
> <version>2.9</version>
> </plugin>

Related

Maven 3.0 Plugin - how Do I set a goal that depends on another goal

I'm working on a Maven plugin for building a custom package type.
I've got it packing and creating a fine. However, I have a previous goal that creates a library folder.
I want my build (package) goal to make sure the previous Lib goal was already run first. How can I do that?
declaring the build class like so:
#Mojo(name = "build", defaultPhase = LifecyclePhase.PACKAGE,
requiresProject = true)
#Execute(goal="lib", phase = LifecyclePhase.PREPARE_PACKAGE)
public class BuildComponent extends AbstractComponentMojo
and the lib class like so:
#Mojo(name = "lib", defaultPhase = LifecyclePhase.PREPARE_PACKAGE,
requiresProject = true)
#Execute(goal="compile", phase = LifecyclePhase.COMPILE)
public class LibComponent extends AbstractLibMojo
That worked so both goals will run. I'd like to just call
mvn groupId:build instead of mvn groupId:lib groupId:build to have a successful build.
Am I missing some annotation processing at runtime? From what I've read I think I need a custom lifecycle to make this work. I've found the Maven Lifecycle Extensions example but I'm not sure how to use it to inject goals or phases into the lifecycle maven builds up and starts out with.
I was able to get it working. However I feel like I'm doing the maven-2 approach instead of the maven-3 one. I'd love to see a Maven 3.0 answer
Basically I removed the #Execute annotations since they weren't needed anyway.
Then I added the file src/main/resources/META-INF/plexus/components.xml
<?xml version="1.0" encoding="UTF-8"?>
<component-set>
<components>
<component>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<role-hint>wcc</role-hint>
<implementation>
org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping
</implementation>
<configuration>
<phases>
<process-resources>
org.apache.maven.plugins:maven-resources-plugin:resources
</process-resources>
<compile>
org.apache.maven.plugins:maven-compiler-plugin:compile
</compile>
<process-classes>
org.ucmtwine:ucm-maven-plugin:classpath
</process-classes>
<process-test-resources>
org.apache.maven.plugins:maven-resources-plugin:testResources
</process-test-resources>
<test-compile>
org.apache.maven.plugins:maven-compiler-plugin:testCompile
</test-compile>
<test>
org.apache.maven.plugins:maven-surefire-plugin:test
</test>
<prepare-package>
org.ucmtwine:ucm-maven-plugin:lib
</prepare-package>
<package>
org.ucmtwine:ucm-maven-plugin:build
</package>
<install>
org.apache.maven.plugins:maven-install-plugin:install
</install>
<deploy>
org.ucmtwine:ucm-maven-plugin:deploy
</deploy>
</phases>
</configuration>
</component>
<component>
<role>org.apache.maven.artifact.handler.ArtifactHandler</role>
<role-hint>wcc</role-hint>
<implementation>
org.apache.maven.artifact.handler.DefaultArtifactHandler
</implementation>
<configuration>
<!--the extension used by Maven in the repository-->
<extension>zip</extension>
<!--the type used when specifying dependencies etc.-->
<type>wcc</type>
<!--the packaging used when declaring an implementation of
the packaging-->
<packaging>wcc</packaging>
</configuration>
</component>
</components>
</component-set>
And then in the application where I'm using the plugin
I set <packaging>wcc</packaging> and <extensions>true</extensions> where I declare my custom plugin.

Running Maven PMD locally using Sonar ruleset

I'm attempting to run pmd locally using Maven. In project I run
mvn jxr:jxr pmd:pmd
but receive error :
net.sourceforge.pmd.RuleSetNotFoundException: Can't find resource 'rulesets/basic.xml' for rule 'UnusedNullCheckInEquals'. Make sure the resource is a valid file or URL and is on the CLASSPATH
Here is a snippet of the rules file which was exported :
<?xml version="1.0" encoding="UTF-8"?>
<ruleset>
<rule ref="rulesets/basic.xml/UnusedNullCheckInEquals">
<priority>3</priority>
</rule>
</ruleset>
I've updated pom file to reference custom ruleset :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.2</version>
<configuration>
<linkXref>true</linkXref>
<rulesets>
<ruleset>c:\\pmd\\export.xml</ruleset>
</rulesets>
</configuration>
</plugin>
To export the ruleset so can run pmd locally using Maven is it required to export this file (basic.xml) & all other xml files which together comprise the "Sonar Way" quality profile ? If so where can these files be accessed on Sonar ?
You can access thru "Quality Profiles > Sonar Way > Permalinks > PMD", although, I think "Sonar Way" pmd rules are empty by default (all rules disabled).
Also, have in mind that version 3.2 of maven-pmd-plugin looks for rules not in rulesets but in rulesets/java, so you might have to replace that path in the exported file (at least the file that you get with Sonar 4.2).
Finally, I would recommend not using a hardcoded path to reference the ruleset file, use something like:
<ruleset>${project.basedir}/rules/pmd-rules.xml</ruleset>
Hope this helps!

How to use Maven and various application.properties for artifact generation of different testing regions in a Spring configured app

I want to use Maven to handle artifact generation for the different local and testing regions. I believe I can use different profiles but I am not certain.
In Maven can I select different directories to select files used on packaging (such as application.properties)? How would I set that up?
An idea of what I want is to have a the following folders for resources in my project
local
build server
dev
sys
prod
Each folder should contain a different version of application.resources which is a file in Spring that can be used to handle hard-coded strings for use in variables. For local builds- our developers also work on different operating systems. Should I require I want to make it seamless on different OS' also.
Key outcomes would be:
Control Maven lifecycle phases from inside the IDE (IntelliJ)
Not complicate phases and team processes
Keep things as consistent for each developer
Make the different configurations per developer/region appear invisible when running a phase e.g. install
Ideally I would have my project set up according to best practices (Duvall, Matyas, Glover).
We provide different properties currently but not by way of different folders. We do this
via a mix of
Spring's PropertyPlaceholderConfigurer
Maven profiles (something we use to build our Dev environment),
Build Server (TeamCity in our case)
Maven phases to produce the correct artifact
start-up and build arguments
My understanding of what we do is limited, but hopefully this serves as a useful example for others and maybe myself to consider.
We provide parameters, as you'll see below, to point to different property files.
Each property file has configuration for a region/environment. I'll explain the current use
as best I can in-case it provides some use to others.
To use Maven profiles we have created a profile in our pom identified as development which includes a region configuration property called env. I don't yet know entirely how that is being used yet in our project however you'll see below our POM includes the a Maven Compiler plugin and a Maven Tomcat plugin.
Day to day, as developers we run our our applications locally on Tomcat from within IntelliJ
and provide the env property. On start-up the env property is provided as an argument to
set to classpath*:dev-common.properties.
This file is a properties configuration file - setting placeholder values for our different
regions.
The value of env is made available to our PropertyPlaceholderConfigurer
Example 1 - Implementation of Maven profile in pom.xml:
The implementation of a profile in our pom is:
<profile>
<id>development</id>
<activation>
<property>
<name>env</name>
<value>development</value>
</property>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0-SNAPSHOT</version>
...
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
Example 2 - Property placeholder configurer for normal build:
We also make use ofa Spring component, a PropertyPlaceholderConfigurer. We use this in collaboration with a build argument to set up a classpath pointer to resource files.
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>
${env}
</value>
</list>
</property>
Example 3 - Property placeholder configurer for test:
We have Spring Contexts specifically set up for integration testing which also use the PropertyPlaceholderConfigurer. These are picked up by a integration testing class using a combination of #ContextConfiguration(locations = {"classpath:test-dataexchange-application-context.xml"}) and #RunWith(SpringJUnit4ClassRunner.class)).
In the testing context we configure the PropertyPlaceholderConfigurer as follows to pick up the properties of an integration testing region:
<bean id="testpropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:dev-local-common.properties</value>
</list>
</property>
Other notes:
We make use of Team City for build management but I have not seen how these settings are
used there, if they are at all. I can conceive there's an ability to combine the above approaches together to aid Continuous Integration and Delivery.
I do not see where the profile identified as development is being used. It is something I
must follow up with my fellow team members.
Resources:
Building for different environments at the Maven Project site.
Maven 3 does not allow configuration of a profile outside of a pom or settings.xml (the Maven configuration file) and says that users who used these external settings should now put them inside of settings.xml
If you are using Spring boot, there is an easy way of doing this.
Create two profiles in maven, and set a property in each profile with the name of the Spring profile you want to execute.
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!-- Default spring profile to use -->
<spring.profiles.active>dev</spring.profiles.active>
<!-- Default environment -->
<environment>develop</environment>
</properties>
</profile>
Inside your application.properties, add this property:
spring.profiles.active=${spring.profiles.active}
Create an application.property for each profile, using this pattern application-profile.properties. For example:
application-dev.properties
application-prod.properties
Be sure to active filtering in the resource plugin:
...
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
...
Another way is to create a file during the execution of maven called activeprofile.properties. Spring boot looks this file to load the active profile. You can create this file as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<configuration>
<target>
<echo message="spring.profiles.active=${spring.profiles.active}" file="target/classes/config/activeprofile.properties" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<configuration>
</configuration>
</plugin>
Aim to generate an artifact for each environment at one time on the central server (CI/Build server), aim to generate an artifact and start/test the application with one click locally, provide a consistent easy to learn way to check out and run your build, and check in and configure your CI.
You can use profiles in Maven and utilize Maven targets to achieve the right build using a build server which in our case is TeamCity.
Use property placeholder configurer in Spring context with an application.resources file for each region and a filename mask e.g. application-resources-${region}.

How to configure Checkstyle in Eclipse for an maven project automatically

I have a maven-multi project, when I create a new eclipse project from it (by M2E 1.0 "Checkout Maven Project from SCM) I want that the eclipse checkstyle plugin is configured for that project automatically.
So I added the maven-eclipse-plugin in parent pom's <pluginManagement> section and configured it to generate .checkstyle file as well as the additional project nature CheckstyleNature. In the modul poms I added the name of the maven-eclipse-plugin in the build section. But when I checkout the project nothing happend, the file is not generated and the nature is not added.
So I think I am doing something completely wrong, but how is it done correct?
Parent pom - plugin management section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<wtpversion>2.0</wtpversion>
<additionalBuildcommands>
<buildCommand>
<name>org.eclipse.ajdt.core.ajbuilder</name>
<arguments>
<aspectPath>org.springframework.aspects</aspectPath>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
</buildCommand>
</additionalBuildcommands>
<additionalProjectnatures>
<projectnature>org.eclipse.ajdt.ui.ajnature</projectnature>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
<projectnature>com.atlassw.tools.eclipse.checkstyle.CheckstyleNature</projectnature>
</additionalProjectnatures>
<additionalConfig>
<file>
<name>.checkstyle</name>
<content>
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
<fileset name="all" enabled="true" check-config-name="My Checkstyle rules" local="false">
<file-match-pattern match-pattern="." include-pattern="true"/>
</fileset>
<filter name="FilesFromPackage" enabled="true">
<filter-data value="target" />
<filter-data value="src/main/resources"/>
<filter-data value="src/test/java"/>
<filter-data value="src/test/resources"/>
<filter-data value="src/main/webapp" />
</filter>
</fileset-config>
]]>
</content>
</file>
</additionalConfig>
</configuration>
</plugin>
Module pom - plugins section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
</plugin>
There are detailed answers to this topic in Can I Configure m2eclipse through pom.xml?:
Completely automatic configuration of the Eclipse Checkstyle Plugin can only be achieved with a ProjectConfigurator, e.g. m2e-code-quality or m2e-extensions.
For m2e as of version 1.0, you can install them via the m2e marketplace under Preferences->Maven->Discovery->"Open Catalog". For details see the bug tracking for integration of m2e-code-quality into the m2e marketplace.
There is a also solution based on AntRun and XMLTask even for FindBugs and Sonar. It needs manual triggering only once after checkout.
The maven eclipse plugin is not the same thing as the m2e plugin for eclipse, which I'm assuming you are trying to use. Basically you shouldn't use both at the same time.
You can use mvn eclipse:eclipse from the command line to generate project files and then you can import the projects into eclipse. M2e works very differently and instead uses the pom files when you import projects as maven plugins. Probably what you want is to configure the checkstyle plugin and hopefully eclipse would pick up the settings. Same for findbugs and other maven plugins.
However, I actually prefer using mvn eclipse:eclipse and haven't actually verified the above works as expected. M2e is just too much of a time waster for me and seems to go off and do the wrong things frequently. I particularly hate how it has a habit of basically rebuilding everything after command line interaction with maven. But lots of people seem to like m2e.
One must install the "Checkstyle m2e" connector
applies configuration form the maven-checkstyle-plugin to the eclipse checkstyle Plugin
Under window\preferences\Maven\Discover\Open Catalog
And of course one has to change the pom, so that the check style plugin is configured, instead of the eclipse plugin.
Unfortunately it does not working for me! (I will not delete the answer because it may work for somebody else.)

How to attach a maven plugin to a phase by default?

I have a maven plugin that should run in the compile phase, so in the project that consumes my plugin, I have to do something like this:
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>my-goal</goal>
</goals>
</execution>
</executions>
What I need is to by default attach my-goal to the compile phase if the user has included my plugin already (ideally the above part wouldn't be necessary, just the plugin declaration).
Is this possible?
Put an #phase annotation in your Mojo classdef annotations.
The doc says:
#phase <phaseName>
This annotation specifies the default phase for this goal. If you add an execution for this goal to a pom.xml and do not specify the phase, Maven will bind the goal to the phase specified in this annotation by default.
If this doesn't work, I guess a JIRA is warranted.
Create an instance of src\main\resources\META-INF\plexus\components.xml in your plugin.
In there create a LifeCycle mapping for the artifact types that your want your Mojo to support. Make sure that it lists all the phases and plugins you want to support. Probably best to copy from the one from maven-core.jar.
Then add your plugin in to the appropriate LifeCycle(s) at the phase at which you want them built.
Eg the consume-aar Mojo added into the compile phase of the aar lifecycle.
<!-- Android archive (aar) support -->
<component>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<role-hint>aar</role-hint>
<implementation>
org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping
</implementation>
<configuration>
<phases>
<generate-sources>
com.jayway.maven.plugins.android.generation2:android-maven-plugin:generate-sources
</generate-sources>
<process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
<compile>
com.jayway.maven.plugins.android.generation2:android-maven-plugin:consume-aar,
org.apache.maven.plugins:maven-compiler-plugin:compile
</compile>
This is possible, but it is an undocumented maven feature.
Use this components.xml:
<component-set>
<components>
<component>
<role>org.apache.maven.lifecycle.Lifecycle</role>
<implementation>org.apache.maven.lifecycle.Lifecycle</implementation>
<role-hint>myplugin</role-hint>
<configuration>
<id>accurest</id>
<phases>
<phase>my-plugin-not-used-phase</phase>
</phases>
<default-phases>
<compile>
my.package:my-plugin:${project.version}:my-goal
</compile>
</default-phases>
</configuration>
</component>
</components>
but your plugin need to be added with <extensions>true</extensions> to modify existing lifecycle.
More: How to bind plugin mojos (goals) to few phases of default lifecycle?
Real project: https://github.com/spring-cloud/spring-cloud-contract/blob/master/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/resources/META-INF/plexus/components.xml
You associate plugin to maven lifecyle goal. The plugin configuration should be declared in phase.
For example if you wan to run some plugin during build phase you'll need to do something like this :
<project>
...
...
<build>
<plugin>
**Configuration of plugin**
</plugin>
</build>
</project>
Please read carefully about maven lifecycles here (it is fundamental for understanding of maven):
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
And then read about how to configure a plugin : http://maven.apache.org/guides/mini/guide-configuring-plugins.html
P.S. Getting into logic of maven is not easy at the beginning. But it is rewarding afterwards.

Categories

Resources