Feasibility of obtaining a Maven aggregator for embedding properties in poms modules (without using inheritance)

A little feasibility question for you regarding Maven. In particular, about whether we can define properties in aggregate memory and then enter them into reference modules, thereby allowing this module to locally overwrite the default properties defined in the inheritance hierarchy.

If you are interested in specifics, I will describe my setup. Before I do this, let me just say that we have discussed in detail our project structure, and it fits our needs very well. At the moment, we are not looking for proposals on other structures, but exclusively study whether maven can satisfy our needs.

So, our setup; I will cook it until necessary. We have two source projects: A and B. Each of them is actually a child of the other, ParentA and ParentB, respectively. ParentA and ParentB technically have several child modules, but in this example I will simply refer explicitly to each for simplicity. So far, so good. ParentA refers to A as a submodule and A refers to ParentA as a parent. The same relationship applies between B and ParentB.

Now the fun comes. We would like the super parent pom for ParentA and ParentB to inherit common properties and configuration, such as dependencyManagement and plugins, etc. But we DO NOT want this super parent pom to be responsible for assemblies. Instead, we would like to identify a number of construction projects that selectively create various modules. In this example, I will talk about BuildAB and BuildB. The former build A, and then B, while the latter builds only B. In reality, we have quite a few such groups of modules and interleaving module dependencies. Finally, to finish the picture, we have a dependency from B to A.

Let me try to do this using some kind of ascii art;)

Inheritance

A --> ParentA --> parent B --> ParentB --> parent 

Relations between modules

 BuildAB ==> { (ParentA ==> A) (ParentB ==> B) } BuildB ==> (ParentB ==> B) 

Dependencies

 B > A 

Now, as this means, it is not possible to use the properties from the BuildAB and BuildB files to define dependencies; these assembly files are not part of any inheritance tree, so nothing will be found. But we want to manage dependency versions differently when starting BuildAB and BuildB; just installing dependencies in the superuser is not going to cut it for our requirements.

If you're wondering why this might be due to the fact that one team can develop modules B and possibly make minor changes to A. Other developers can work on the last and largest for project A, which has consequences for B due to dependency. We have excellent mechanisms for handling this in source code thanks to Mercurial. But we are really trying to make this work with Maven.

Ideally, each assembly file in the first case will rely on submodules inheriting from the parent. But when we need to override this inheritance, we would like to be able to specify the injective properties in the Build file, which will act exactly as if they were specified in the module initially. Of course, all without the actual modification of the pump controlled by the source.

We would like to evaluate whether it is possible to change maven for this, through a plugin or patch.

We have never written plugins (and, frankly, textbooks and other materials on the Internet are relatively scarce and not very friendly to developers) if someone does not have a good tutorial that I missed :)), but we would be willing to give try it if it seems doable.

So basically

  • Have you dealt with these requirements yourself and worked with existing plugins?
  • Is there a simple trick we are missing?
  • Have you written a similar plugin and can you recommend a place to run?
  • Do you know of any practical reason why such a plugin does not work?
  • You are working on the maven source code and know if we can add any resulting code ... and where we should look if we want.

Last comment. We are developing in Eclipse, so we need a build to work without inserting properties. I expect this to be through a regular inheritance tree.

Thanks a lot, I know this is a bit of a tricky question.

+4
source share
1 answer

For all kinds of special magic: use the maven build extension.

This is not well known (and, as usual, for maven, sigh) an insufficiently documented mechanism, but, as far as I see, this is a truly officially approved way to influence the assembly process as a whole.

 import org.apache.maven.AbstractMavenLifecycleParticipant; import org.apache.maven.execution.MavenSession; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.Logger; @Component(role = AbstractMavenLifecycleParticipant.class, hint = "mySpecialService") public class MySpecialExtension extends AbstractMavenLifecycleParticipant { @Requirement private Logger logger; @Override public void afterProjectsRead( MavenSession session ) { // ...do you magic here // for example, to set some POM properties Properties sysProps = session.getSystemProperties(); .... Properties projProps = session.getCurrentProject().getProperties(); projProps.setProperty("..",val); 

This function is called immediately after parsing the pom.xml files and building the base POM in memory, but before any further build operation begins. In a project with several modules, the extension is called from the root project, even if it is defined only in a certain submodule. At this point, you could theoretically do something with your build process, for example, just enter some properties in pom, load other projects from the artefact manager and add them to the build reactor, look for some specific plugins, change POM some module, or even build things that are not announced anywhere (!)

To create such an extension, you put your code in a separate maven project

 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <prerequisites> <maven>3.0</maven> </prerequisites> <name>my-special-service</name> <groupId>my.group</groupId> <artifactId>my-special-service</artifactId> <packaging>jar</packaging> <parent> .... </parent> <properties> <mavenApiVer>3.0.5</mavenApiVer> <mavenModelVer>2.2.1</mavenModelVer> </properties> <build> <plugins> <!-- Maven Build Extension --> <plugin> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-component-metadata</artifactId> <version>1.5.5</version> <executions> <execution> <goals> <goal>generate-metadata</goal> <!-- goal>generate-test-metadata</goal --> </goals> </execution> </executions> </plugin> <!-- Maven Build Extension --> </plugins> </build> <dependencies> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-project</artifactId> <version>${mavenModelVer}</version> </dependency> <!-- Maven Build Extension --> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-compat</artifactId> <version>${mavenApiVer}</version> </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-core</artifactId> <version>${mavenApiVer}</version> </dependency> <!-- Maven Build Extension --> .... </dependencies> </project> 

To use the extension in any other project, simply add the following

 <build> <extensions> <extension><!-- Maven Build Extension: my Special Service --> <groupId>my.group</groupId> <artifactId>my-special-service</artifactId> <version>.....</version> </extension> </extensions> <pluginManagement> .... 

In our specific use case, we had some common services (for example, database URLs) used from specific plug-ins during the build process), which we should receive from the configuration management system transparently. Rolling out property files to each developer and each build server would be inappropriate, since the environment is a heterogeneous path.

+2
source

Source: https://habr.com/ru/post/1345913/


All Articles