Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Critical
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: None
-
Component/s: None
-
Labels:None
-
Number of attachments :
Description
Basically I use the assembly plugin in a module under the reactor project.
I attach the assembly plugin to the verify phase (because of MNG-1311), but somehow when my module is being processed, the plugin is executed for the package phase and it
forks the full project lifecycle, because it is an aggregator.
This triggers the rebuild all my reactor projects.
This happens twice (I have 2 modules which use the assembly plugin),
making my build 3 times too long.
Now investigating the issue.
The stack trace looks like:
private void executeGoalAndHandleFailures( String task, MavenSession session, MavenProject project,
EventDispatcher dispatcher, String event, ReactorManager rm,
long buildStartTime, String target )
private void executeGoal( String task, MavenSession session, MavenProject project )
private void executeGoalWithLifecycle( String task, MavenSession session, Map lifecycleMappings,
MavenProject project, Lifecycle lifecycle )
private void executeGoals( List goals, MavenSession session, MavenProject project )
throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
private void forkLifecycle( MojoDescriptor mojoDescriptor, MavenSession session, MavenProject project )
throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
which creates the redundancy here:
private void forkLifecycle( MojoDescriptor mojoDescriptor, MavenSession session, MavenProject project )
throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
{
PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
getLogger().info( "Preparing " + pluginDescriptor.getGoalPrefix() + ":" + mojoDescriptor.getGoal() );
if ( mojoDescriptor.isAggregator() )
{
for ( Iterator i = session.getSortedProjects().iterator(); i.hasNext(); )
}
else
}
The redundancy appears because the assembly plugin is an aggregator so if forked it will fork all reactor projects.
It is forked in my case because the execute phase is not null.
In DefaultLifeCycleExecutor:
private void executeGoals( List goals, MavenSession session, MavenProject project )
throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
{
for ( Iterator i = goals.iterator(); i.hasNext(); )
{
MojoExecution mojoExecution = (MojoExecution) i.next();
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
if ( mojoDescriptor.getExecutePhase() != null || mojoDescriptor.getExecuteGoal() != null )
{ forkLifecycle( mojoDescriptor, session, project ); }and getExecutePhase() is "package"
Now before executing this:
Map lifecycleMappings = constructLifecycleMappings( session, task, project, lifecycle );
executeGoalWithLifecycle( task, session, lifecycleMappings, project, lifecycle );
my lifecycleMappings contains 3 entries each with a list of single MojoExecution instances
install -> ME21
verify -> MJ17
test -> MJ20
Then when this mappings are processed as a goal chain:
List goals = processGoalChain( task, lifecycleMappings, lifecycle );
The goals have been sorted so that:
(MJ20, MJ17, MJ21) which looks OK to me.
which were constructed by:
private Map constructLifecycleMappings( MavenSession session, String selectedPhase, MavenProject project,
Lifecycle lifecycle )
throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
{
// first, bind those associated with the packaging
Map lifecycleMappings = bindLifecycleForPackaging( session, selectedPhase, project, lifecycle );
// next, loop over plugins and for any that have a phase, bind it
for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
return lifecycleMappings;
}
Links to a somewhat related issue: http://jira.codehaus.org/browse/MNG-1311
Now a little chat with jdcasey conclude that a new Mojo needs to be created:
(18:02:35) jdcasey: CoffeeBre: it doesn't seem to have anything to do with it being an aggregator...it's all based on that @execute phase="package" annotation
(18:02:48) jdcasey: that prompts the lifecycle executor to fork the lifecycle, and re-run package
(18:02:50) jdcasey: hmm
(18:03:49) jdcasey: looks like this mojo isn't designed to be integrated into the lifecycle
(18:04:13) jdcasey: it looks like you'd have to write another mojo front-end for the assembly process, which doesn't specify @execute phase="package" in it.
(18:04:49) jdcasey: the mojo could be a thin wrapper around the real guts, which would be in a separate class
(18:05:15) jdcasey: I think that would be the simplest way around.
(18:05:43) ***jdcasey thinks the @execute annotation is poorly named...
(18:05:46) CoffeeBre: what about removing the @execute phase instaed?
(18:06:02) jdcasey: well, then you lose the ability to call 'mvn assembly:assembly'
(18:06:10) jdcasey: because it requires the package phase.
(18:07:04) jdcasey: something like assembly:attached would be good, IMO...that's what you want to do, right? attach them to the main project artifact so they're installed/deployed too?
(18:07:27) jdcasey: that new mojo could reference the same code, which would be factored into a general case api in that plugin
(18:07:34) CoffeeBre: and with regard to the aggregator, I mentionned it because of line 701 in DefaultLifeCycleExecutor
(18:08:02) jdcasey: yeah, but if you look, that just determines how the lifecycle is forked, not whether
(18:08:32) CoffeeBre: you mean it shouldn't be forked at all? (I am trying to follow)
(18:10:42) jdcasey: CoffeeBre: you need a new mojo that integrates with the existing lifecycle, but has to bind on or after the package phase...rather than forking
(18:11:57) CoffeeBre: jdcasey: see also MNG-1310 and MNG-1274. related to my use of the assembly plugin
(18:16:53) CoffeeBre: jdcasey: trying to summarize. If I follow you, the issue is because the assembly:assembly mojo is forking and we don't want that. So I create a simple Mojo wrapper within the assembly plugin with 2 differences. Map to assembly:attached, and do not specify a @execute. Could that be the solution for MNG-1311 as well?
(18:17:45) jdcasey: CoffeeBre: that won't solve MNG-1311, because we need to eliminate the infinite loop (thought I worked on that once already)
(18:18:16) jdcasey: CoffeeBre: you may need to factor some logic out of the existing AssemblyMojo into a common class, or extend it (not sure whether the annotations will show through when extending)
(18:18:41) jdcasey: if you factor into common API, and reference from both the AssemblyMojo and the new AttachedAssemblyMojo (or whatever) it'll definitely work
(18:18:56) jdcasey: but the new mojo should not specify the execute stuff
(18:19:46) jdcasey: CoffeeBre, jeremyw: I've gotta run out for a bit, but I'll be back in like an hour or so
(18:19:58) CoffeeBre: jdcasey: I wondered if the infinite loop was not created by the fact that the plugin was aggregating all the projects
(18:20:35) jdcasey: CoffeeBre: um, possibly...but I think aggregation is appropriate here...not sure, I'd have to investigate further.
(18:20:49) CoffeeBre: jdcasey: ok. Have to run out as well. Will create an issue and add info there.
This fixes it for me. I just moved all the code to an abstract class, and created a new mojo with the exact same code as the AssemblyMojo except for the @execute annotation, which I got rid off.
Note: this patch is not applied on top oif the trunk!!
It is applied on top of trunk + MNG-1274 + MNG-1310.
If we have to reorder these issues, all patches will change.