Parameterise a Maven Multimodule Build - java

I'm looking for a possibility to parameterise a multi-module build in a way that I can replace/specify some files (e.g. UML files) that are used during the build in order to produce different output.
The procedure of the build stays the same but I want to be able to produce different output depending on the input UML model.
I have a multi-module project that builds several jars based upon an UML model. The pom structure looks as follows:
+ generation
- mod1
- mod2
- mod3
The root pom (generation) generates java sourcecode (.java) based upon an UML model stored in the directory /uml. Afterwards the modules (mod1...3) compile distinct subsets of this sourcecode and package the output as jar.
I want to reuse this build procedure and apply it to different UML models.
How can I reuse the entire generation, compilation and packaging procedure defined in the multimodule project in other maven projects?
# Generate jars based upon the foo UML model
+ generation-foo
/uml/foo.uml
# Generate jars based upon the bar UML model
+ generation-bar
/uml/bar.uml
Update
I could use profiles in the generation project in order to define the different input uml models and then just activate the relevant one. But I would lose traceability that way.
Perhaps a completely new approach would be a better idea ... any suggestions?

Conceptually, I would say, Maven is designed around the POM file which is a model of the project that is being built. It is not so much a process description that applies a function to an input and results in an output on basis of that.
That being said, there is a lot possible with properties in the POM, which then can be passed along on the command-line: -Dproperty=value. It looks as if you would be able to pass the property to whatever process is generating the source code.
I may express some caution, though. I'm seeing some possible red flags in the overall design that you describe. If modules (regardless of their inheritance relationship) pass along files/folders, that should preferably go through installation.
So, if you were to do that, you end up with a version of the parent project in your local repository of which you don't really know what it is. Which parameters were used? And how will a user of that artifact then deal with that?
I'm not saying this won't work, but it may get hairy and not play entirely well within more traditional Maven implementations.

I'm not entirely sure I understand your use cases but you might want to look at:
POM Inheritance : Defining as much as you can in the parent module (different groups of modules can have the same parent)
Maven profiles : you can activate based on all sort of potential conventions like even the project name.
Maven Archetypes : And finally I think based on what your saying this maybe the only solution of a reusable project template

Related

Is it possible to use wildcard logic '*' to list a specific directory via Apache Maven Goals & Options?

I need to list a specific directory using wildcard logic within my Maven goals and options command.
Currently the root directory is:
mvn test -Dcucumber.options="C:/Users/Joe_Blogs/Desktop/AutoFramework/src/test/resources/features/Bookings/MakeBooking.feature"
I need to use ** to scan the project folders in order to search for a given feature file, as the folder name (Bookings) may change.
mvn test -Dcucumber.options="C:/Users/Joe_Blogs/Desktop/AutoFramework/src/test/resources/features/**/MakeBooking.feature"
In the example above ** will need to reference a variety of different folders, not just Bookings.
Any ideas?
Thanks for your help.
Maven supports the "any" and "any descendant" wildcard denoted by * and **, respectively. It is a subset of the <fileset> Ant convention.
The support comes from the Apache Maven Shared Utils library. The actual logic of walking directory trees, path normalization, pattern matching, etc. is grouped inside the org.apache.maven.shared.utils.io package. Those classes provides uniform file system handling across plugins supported by the the Maven Project.
As the references should demonstrate, wildcard processing is neither trivial logic, nor magically applied outside of Maven proper. Cucumber has to intentionally support the syntax somehow. Sorry, but it doesn't look like Cucumber supports the "any descendant" wildcard. The closest equivalent is /* at the end of a path.
However, one possible workaround is to use tags. Maybe it will seem silly to tag a single file, but doing so dispenses any concern about pathing. Example:
mvn test -Dcucumber.options="--tags #MakeBooking"

"Hide" a maven artifact from the eclipse autocomplete

For reasons I don't even want to begin to get into.. I have a maven hierarchy that looks like the one below. In a nutshell, everything requires commonslang3, except one ancient artifact that requires commonslang2.
We have no issues with compile or runtime, the dependencies work as expected. The challenge we are having is at development time.
We'd like to ensure everyone on the team uses the commonslang3 APIs, but occasionally (because of the ancient artifact and Eclipse auto suggest), someone accidentally uses the commonslang2 APIs.
Normally, we would just force the desired version in our POM, but commonslang is a special snowflake. The package signature changed between comonslang2 and commonslang3, which means we would have compile failures if we excluded the older library. E.g.,
org.apache.commons.lang3.StringUtils
org.apache.commons.lang.StringUtils
My question is this, how can I configure maven/Eclipse, to use commonlang2 as needed during compile... but not populate it in the Eclipse class autosuggest list? My desired end state is that someone types 'stringuti' + ctrl + space, and the only option they see is commonslang3. I am aware that each developer can remove individual classes via (Window->Preferences->Java->Appearance->Type Filters) but that is not a viable solution for two reasons: 1) It's a large team with frequently changing resources... 2) I need an entire artifact removed, as in hundreds of classes.
Example Tree:
MyWar
-- MyModuleJar1
-- ...
-- MyModuleJar2
-- LibA
-- commonslang
-- ...
-- LibB
-- commonslang3
-- ...
-- LibC
-- commonslang3
-- ...
-- ...
In Eclipse:
Window->Preferences->Java->Appearance->Type Filters
Add org.apache.commons.lang.*
Because you want to affect auto-complete which is a function of the IDE, you are forced to change the setting in the IDE. You can export the preferences and share them of the rest of the team.
There is not much you can do about it in Eclipse other than type filters #JustinKSU mentioned.
But with Maven you can use Takari to access rules to prevent accidental inclusion of transitive dependencies. Of course this comes with a plethora of caveats with one ironically being that the Eclipse JDT compiler has to be used instead of plain javac.

JAXB-Gen classes not getting added to class path

I am working on a project whose input is XSD.From the input XSD jaxb classes will be generated in a particular package.
There is reflection class which will create class from the ObjectFactory.java (JAXB generated).
Class<?> aClass = Class.forName("pkg.ObjectFactory");
But its throwing class not found exception.
Refreshing the excipse project by right clicking on it resolving the exception.
How to solve this problem automatically?
Though wait for an eclipse-only answer too, maybe you should consider having a nice build infrastructure like maven. If you reached a size where would like to draw the build system in separate parts and pin it on the wall.
I am in favour of many independantly versioned (sub)projects. An explicit structure is best done with a maven build infrastructure, available for all IDEs. Then a project might generate the JAXB source classes, and the main project might depend on that project.

Java autogenerated getters-setters in project - best practice

Our project has started newly and wanted to know some of the best practices followed in industry. We have generated lot of DTOs(getters and setters) code for webservices using JaxB. we keep all the DTO classes along with regular pojos(logic written), its looks like large project due to this auto-generated code, also for code coverage it considers these classes also.
I am keen to know that these classes should be as a jar file in classpath or it should be as classes in project.
Thanks in Advance,
Madhavi
If your project uses Maven (or something similar) I would advise having the code generation and the generated code in a separate module of a multi module project.
This way the generated stuff is out of the way of the hand crafted code. You can also set up your Maven build process to then build this module first and the rest of the code can rely on the resulting artefact, be it a jar or something else.
You could also regenerate the generated code on each new build this way. Although this can be a lengthy process, depending on the service.
Generated files should not be mixed with your written files.
A common approach is to generate them to the target folder, e.g. target/generated-sources or something similiar. Of course, if they are rarely changed, you could also put them in a jar file that you import into your project.
I think its better to keep them in jar. As its auto generated code and no one is supposed to change. Whenever regenerated include new jar.

Multiple packaging in Maven

I have a project in which there are few components like A, B and C. All the components are exposing rest interfaces that other components are consuming. So, I am using ant to product A.war, A-services.jar, B.war, B-services.jar, C.war, C-services.jar.
A-services.jar contain the interface declarations for B and C.
B-services.jar contain the interface declarations for A and C.
C-services.jar contain the interface declarations for A and B.
I want to migrate it to Maven. But I have read at some places, it is not a good idea to have a single pom produce multiple packages like A-services.jar and A.war. What should be the best way to go for that.
I would assume the reason you have A-services is because of shared data models and such. With that being the case you end up with multiple projects. A POM for the A services. Then another A WAR project that has a dependency on A-services. And your B project also has a dependency on A-services.
With that being said it seems you really just need to separate your projects into data model projects and implementation projects.
You will have six projects. Do not try to make Maven produce a WAR and JAR from the same project.
You may find the maven-assembly-plugin to be helpful for you, but as Andrew stated, you really need to separate out your project into proper modules. This is what Maven is really for.

Categories