Generated code is not compiled - maven

I wrote a Mojo that creates a new Java class and puts it in /target/generated-sources/annotations. in addition, I have configured build-helper-maven-plugin to declare that folder as source folder.
The problem is when I do: mvn clean install from CLI it generates the source file but it doesn't compile it.
Note, if I run Maven Install from within Eclipse (using the m2e connector) then it works fine.
What am I missing?

Without an actual plugin definition, we can only speculate.
I can't comment on m2e, I see one obvious difference that you state by yourself: mvn clean install vs mvn install, but from the "bare" maven's standpoint,
here is one possible reason:
Maven has a concept of phases that comprise the lifecycle. An information about phases of default lifecycle is available here
Plugins (more precisely the "goals" of plugins) are something that usually gets attached to a particular phase.
Maven compiler plugin is attached to the compile phase, for example.
So, maybe the plugin that you've developed runs later than the compiler plugin.
Usually, source generation plugins are attached to generate-resources phase.
Its possible to run a full lifecycle in maven, in fact its what people usually do, for example, running mvn test actually means, run all phases of the default lifecycle up-to (including) phase test.
It's also possible however to run a particular plugin goal "directly" without attaching it to the phase. Of course, in this case, its pre-conditions should be met.
For example, mvn surefire:test means that we should invoke the surefire plugin directly. Of course the source code and test code should be compiled beforehand (bytecode has to exist in the target directory)
So I suggest you to run the following series of commands (Adjust if you have tests):
Run mvn clean install on the plugin project to place it to local m2 repo
Run the plugin directly: mvn ::: and check
whether the source is generated in the target folder
Make sure in pom.xml of the project that the source folder are configured correctly
Run mvn compile (phase up-to, including, compile) on pom even without the plugin
After this phase, there will be compiled sources in the target directory. Don't run
clean because it will wipe out all the target directory
This will effectively help to make sure that plugin does the job right

Related

Why 'mvn install' war projects?

My maven project packages a war, which only gets deployed and is itself not a dependency to other projects (in other words is a final deployable).
Questions:
is there any reason to ever run mvn install on that package, which, in addition to mvn package only puts it in the localRepository?
Why should a final deployable be installed if nothing ever depends on it?
For a final deployable artifact indeed there may be no reason to invoke the install phase instead of the package phase: you want to build the .war file and you don't need to install it in your local repository indeed.
However, you may want as an habit to always run integration tests, if any. Looking at the default Maven lifecycle these phases happen after the packaging:
package take the compiled code and package it in its distributable format, such as a JAR.
pre-integration-test perform actions required before integration tests are executed. This may involve things such as setting up the required environment.
integration-test process and deploy the package if necessary into an environment where integration tests can be run.
post-integration-test perform actions required after integration tests have been executed. This may including cleaning up the environment.
verify run any checks to verify the package is valid and meets quality criteria.
install install the package into the local repository, for use as a dependency in other projects locally.
Hence, by invoking install you would make sure to always execute integration tests as well. Indeed a shorter invocation would be
mvn clean verify
Less popular but more effective in these cases.

Why should run first mvn clean clover2:setup install clover2:clover, then: mvn sonar:sonar

Based on the question Sonar + Clover only runs on src-instrumented, it is suggested using first mvn clean clover2:setup install clover2:clover, then: mvn sonar:sonar.
Just wonder why we cannot use mvn clean clover2:setup install clover2:clover sonar:sonar?
In the past it was the recommended way to run goal sonar:sonar alone. This is no more the case since SonarQube Scanner for Maven stopped trying to run unit tests + collect coverage for you by forking a new Maven lifecycle.
General advice is now to run goals in a single command. For example mvn clean package sonar:sonar
In the case of Clover the clover:setup goal will alter the Maven Model to make all other plugins (like surefire) use instrumented classes instead of original source code. This is indeed a problem because it will prevent SonarQube to match class files. So in your case you should either stick with two separate goals, or manually configure sonar.sources to refer to original source code.
Compared the maven logs and found the possible reason:
The "mvn clean clover2:setup install clover2:clover sonar:sonar" seems having issue to find the Source dirs. The log shows it uses ${project}\target\clover\src-instrumented and ${project}\target\generated-sources\annotations as the source dirs.
If explicitly specify src/main/java, then this single command works well. The only tricky thing is why running the goals separately doesn't need to specify sonar.sources but the plugin can still find the right folder for source dirs.

Can I get the phase/plugin:goal used in the maven command?

We use maven for our build process and are now modifying it to use grunt to build the client side files. We have maven kick off the grunt task, but similar to maven, there are some things that we want to do only if a certain phase is run. For example, if the deploy phase is run on my maven project, I want to tell grunt to also deploy the js artifact I am creating. Otherwise, if something like compile was run in the maven project, I don't want to deploy my js artifact through grunt.
I can pass properties just fine into grunt, but I don't know how to get a property that can tell me what phase was run. Is it possible to get the phase or the plugin:goal that was run? Or even the command that was run?
The way I have seen other Maven plugins handle this is to use different mojos, bound to the desired phases. For your example, you'd write a deploy mojo and bind it to the 'deploy' phase.
The maven-resources-plugin does this. It has both Resources and TestResources mojos. One is bound to the process-resources phase, the other to process-test-resources. So, if I was to run mvn compile the Resources mojo would execute, but the TestResources mojo would not, as process-test-resources occurs after the compile phase.
Source code for resource plugin

Avoiding circular dependencies between Maven plugin build and test

I have a project with the following subprojects:
foo-codegen
...which, as the name implies, performs code generation...
foo-maven-plugin
...which invokes foo-codegen during the build process.
Generally speaking, this works fine. The problem, though, is when I want to test foo-codegen: foo-maven-plugin isn't yet available during foo-codegen's build cycle if we're putting things together in dependency order, but the build process for the tests invokes that plugin to actually perform the necessary code generation.
What's the right way to break this chain? Should I move foo-codegen's tests into a third subproject? Use the Maven Invoker plugin rather than foo-maven-plugin for doing code generation during the test phase? Something else?
If you do a mvn install or mvn deploy to a repository on the plugin first, then you can run them any order and do a mvn compile separately.

Maven plugin execution change Maven properties or skip build lifecycle steps

When I build my application with maven, I run mvn clean install. As a part of the install lifecycle, I run appengine:devserver_start from Google's GAE Maven plugin. This appears to be already bound to a step in the lifecycle and therefore it reruns some build steps from the beginning, even though me running mvn install did those. For example, the resources step is rerun. I had my own Java script run to download the latest resources for my build. But because of appengine:devserver_stop, I need to uselessly run this cript again because the resources step is re-executed.
I can think of two ways I can avoid this, but I'm not sure how to configure both ways. The first would be to somehow skip re-running build steps that I've already run. The other way would be to change the Maven POM properties just for the plugin execution. I have a Maven property set, either to true or false, that I can use to set the skip setting for the Java script I use during resources (because I run this script using the exec-maven-plugin). Think of this as a Maven property that can be set with the -D flag. Can I have this property changed just for the plugin?
If you are having trouble thinking about my scenario, consider what happens when you run mvn compile install. All build lifecycle steps until compile will run, then all compile steps until install will run, including compile.
A common/easy way to solve this kind of problems is to use maven profile. Just create a new profile that includes the plugin with preferred phases.
You should probably don't fight with it and just run clean appengine:devserver_start instead of clean install. Read my answer here for a more detailed explanation:
https://stackoverflow.com/a/17638442/2464295

Resources