Maven: How to deal with modules that contain modules? - java

Previously I have worked with multi-module Maven projects that consisted out of two hierarchies. The parent POM followed by modules in their own directories and POMs.
But now I have taken over a project that contains a parent, followed by modules which again contain modules.
Is this all according to Maven guidelines or am I dealing with something customized?
And how to I interpret these sub-modules? Know a guide you can point me to?
I can run all Maven lifecycles successfully. Though I'm unsure whether and how to refactor the application and start inserting my own code.
Here is a tree of my project structure with only a few modules left:
top-parent
| pom.xml (modules: applications, checks, core, test)
|
+---applications
| | pom.xml (parent: top-parent) (modules: batch, surefire, web)
| <parent>
| <artifactId>applications</artifactId>
| <groupId>com.a.b.codechecker</groupId>
| <version>1.0</version>
| </parent>
| <artifactId>batch</artifactId>
|
| |
| \---web
| | pom.xml
| <parent>
| <groupId>com.a.b.codechecker</groupId>
| <artifactId>applications</artifactId>
| <version>1.0</version>
| </parent>
| <artifactId>web</artifactId>
|
+---checks
| | pom.xml (parent: top parent) (modules: aggregator, blacklist-check)
| <parent>
| <groupId>com.a.b.codechecker</groupId>
| <artifactId>parent</artifactId>
| <version>1.0</version>
| </parent>
| <groupId>com.a.b.codechecker.checks</groupId>
| <artifactId>checks</artifactId>
| |
| +---aggregator
| | pom.xml
<parent>
<artifactId>checks</artifactId>
<groupId>com.a.b.codechecker.checks</groupId>
<version>1.0</version>
</parent>
<artifactId>aggregator</artifactId>

I provide below few outlines.
As per the question,
Is this all according to Maven guidelines or am I dealing with something customized?
Yes, you can have Parent, Child, Grand child type module structure.Parent and Child type maven multi module hierarchy is simple, but in some cases, developers design to have several sub modules inside a module. If you have large project having n number of modules and m number of submodules, it becomes complex for different levels of developers.
As per this question,
And how to I interpret these sub-modules? Know a guide you can point me to?
It is upto the development team about how to manage for simplicity. I would recommend, if you have many sub modules, you can create/maintain another independent project and you can add the dependency to the main project wherever it is required. It will provide you the granularity and a separate team work on this project without considering the main project.
In case of large project, it is always recommended to maintain independent projects and you can add the dependency in other projects. For this you can use Nexus or Artifactory for artifact management.

Related

Integrate spring projects and EJB projects within a gradle(or maven) multiple projects

I have a gradle multiple projects. The structure is like below:
|--MyProject
| |--ejb-project
| | --build.gradle
| |--spring-project
| --com.mine.demo
| --Test.java
| | --build.gradle
| |--build.gradle
| |--settings.gradle
in the settings.gradle
include: ':ejb-project'
include: ':spring-project'
I defined a Test.java in the spring-project.
Now, if I wanna use Test.java in the EJB projects, How can I use it? Are there configurations to be configured?
Questions can be simplfy as this: Can I use a class from spring project in a ejb project within a gradle(or maven) multiple projects? If can, How can I use it?
I've never done this before, so barely know how to integrate spring in ejb. HELP!

Enforce class only once in jar/ear/rar with maven build

In light of a recent problem I had, I would like to make sure it does not happen again. Kind of like a regression test for my build system.
I need a way to scan an ear (or other jar style package) to make sure a class is only once in it.
Example:
- test.ear
| - lib (folder)
| | - api.jar (zipped file)
| | - packageName
| | - ClassName.class
| - connector.rar (zipped file)
| - api.jar (zipped file)
| - packageName
| - ClassName.class
| - ejbs.jar
The pom.xml of ejbs.jar has a dependency on the api that brings the api.jar to the lib folder. The pom.xml of the connector.rar also has a dependency on the api that brings the api.jar to the connector.rar file, so while the reference to the same dependency, it still causes the above result.
As I have a maven build I'm looking for a way that integrates well there (if possible).
There's this enforcer rule you can use. Have a look at http://www.mojohaus.org/extra-enforcer-rules/banDuplicateClasses.html

Spring Boot application with part of JSP files from other Maven module

Let's assume that we have Spring Boot based web application using JSP templates. It can be even as simple as in the following example (from official Spring Projects repository)
Project structure:
|-src/main/java/
| |-sample.tomcat.jsp
| |-SampleTomcatJspApplication.java
| |-WelcomeController.java
|-src/main/resources/
| |-application.properties
|-src/test/java/
| |-...
|-src/main/webapp/
| |-WEB-INF
| |-jsp
| |-welcome.jsp
|-pom.xml
Properties file contains view prefix /WEB-INF/jsp/ and suffix .jsp and when requesting / we see properly rendered content of welcome.jsp.
WelcomeController.java
application.properties
Changes
Now let's make the following changes
Duplicate WelcomeController.java as WelcomeController2.java and change a bit request mapping, model attributes and returned view name, e.g.:
#RequestMapping("/2")
public String welcome2(Map<String, Object> model) {
model.put("message", "Hi from Welcome2");
return "welcome2";
}
Duplicate welcome.jsp as welcome2.jsp so that src/main/webapp will be like this:
|-src/main/java/
| |-sample.tomcat.jsp
| |-SampleTomcatJspApplication.java
| |-WelcomeController.java
| |-WelcomeController2.java
...
|-src/main/webapp/
| |-WEB-INF
| |-jsp
| |-welcome.jsp
| |-welcome2.jsp
Then when requesting /2 we can see properly rendered content of welcome2.jsp.
The question
What is the way of splitting such project into two maven projects, so that both WelcomeController2.java and welcome2.jsp could be moved to other project (maven dependency) and still be successfully resolved when /2 URL is requested?
Note that with Spring Boot web-fragment.xml (that could be placed in META-INF directory of dependency) is ignored.
Unfortunately, I don't know of an easy way to do this but one approach I've used is to create a Maven artifact just like normal for the main project, in your case probably a WAR artifact. This project will need to have a dependency upon your second project. Then your second project would consist of two components:
A standard Maven JAR artifact containing the compiled class files.
A Maven assembly ZIP consisting of the JSP files that need to be included in the WAR archive as well. This will be generated from the second project during the package phase, but will need to be included as a separate dependency on the main project using a zip classifier.
When the first project is built, you'll need to unpack the assembly dependency as part of the packaging process for the WAR archive. If you want this to work in an IDE, you'll probably need to unpack it in a fairly early phase, such as process-resources or generate-sources.

Import package into other module of the same maven project

I've got a maven parent project that has two child modules (spring ws archetypes) each one is intend to be deployed in its own application server. One of the modules exposes a ws endpoint that is used by a ws client in the other module.
My problem is that i will have the java objects generated by jaxb and xsd in both modules, unless i find the way to share this set of classes without replicating it.
Is there any way to import an specific package from one module to the other? Is there other more appropriate way to deal with this problem?
Cheers!
create a ws-api maven module that only contains the api classes interfaces.
create a ws-impl that depends on the ws-api, because it implements it.
create the client module with the ws-api module as it's dependency, because it uses it.
Then you have the following structure, you can reuse the api clases and you have a clear api:
parent-pom
+- ws-api
+- ws-impl
+- client
The module dependencies will be
+------------+ uses +------------+
| client | --------> | ws-api |
+------------+ +------------+
^
| implements
|
+------------+
| ws-impl |
+------------+
In this setup the jaxb objects have to be generated in the ws-api module.
For a detailed explanation of why to separate the api and implementation take a look at my blog
http://www.link-intersystems.com/blog/2012/02/26/separation-of-api-and-implementation/

Can maven projects have multiple parents?

We have Java and Flex projects. We currently have 1 base pom that contains the configurations we want to use for both projects. Problem with this is: Flex projects inherit configuration, for example, for javadoc and pmd plugins, which is not desirable.
I want to clean it up and have a real base pom, and then a java-base-pom and a flex-base-pom. But how does this work in a multi-module that has both a Flex part and a Java part?
We have plugins to our own application where we use the following structure:
my-plugin
my-plugin-client (flex)
my-plugin-server (java)
my-plugin just contains a pom.xml with <modules/> section. I would use my-plugin pom.xml as a parent for both, but then I cannot also use the java base-pom or the flex base-pom as parent. What would be the best approach for this?
Even though maven projects have single parent, they can import any number of other pom's like this:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>my-shared-dependencies</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
This has two important differences compared to a parent:
Plugins defined in the imported pom won't be imported
Dependencies defined in the imported pom won't be added to the current pom, it will only import dependencies into the dependency management section
However, if your parent pom has a <dependencies> section and you want to include those into your dependencies, then you can add the parent to your <dependencies> section just like a regular dependency:
<dependency>
<groupId>org.example</groupId>
<artifactId>my-shared-dependencies</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
Even though the same dependency is already imported, the version tag has to be specified again. To reduce duplication, it can be stored in a property
A project can have only one parent (unlike multiple inheritance in C++) but this parent can be part of a bigger parent hierarchy. As pointed out by others, you could thus have something like this:
base-pom/
|-- flex-base-pom
| |-- my-plugin-client
| | `-- pom.xml
| `-- pom.xml
|-- java-base-pom
| |-- my-plugin-server
| | `-- pom.xml
| `-- pom.xml
`-- pom.xml
That said, I noticed you wrote that your actual problem is that:
flex projects inherit configuration for javadoc and pmd for example, which they do not want.
You should use the pluginManagement element to avoid this situation:
pluginManagement is an element that is seen along side plugins. Plugin Management contains plugin elements in much the same way, except that rather than configuring plugin information for this particular project build, it is intended to configure project builds that inherit from this one. However, this only configures plugins that are actually referenced within the plugins element in the children. The children have every right to override pluginManagement definitions.
So, in the parent pom, configure your plugins in pluginManagement (javadoc and pmd for example), and reference them within the plugins element in the desired children (only in my-plugin-server here). This would solve your current issue.
The only way is to have base-pom as parent of java-base-pom and flex-base-pom.
I have similar structure for my spring projects:
base-pom (basic configuration - eclipse, reports, repositories, etc)
|
+ spring-base-pom (spring definitions)
|
+ spring-jar-base-pom (jar specific definitions)
|
+ spring-war-base-pom (spring web and servlet dependencies)
|
+ spring-webapp-base_pom (spring web mvc dependencies)
I've cross this exact proble also, and the best solution I found was to use Inheritance and Aggregation as suggest in this question : does maven support multiple parents (multiple inheritance) ?
You can have an aggregator pom that is not the parent of the projects it
aggregates.
and explain in the Maven Documentation
Inheritance and aggregation create a nice dynamic to control builds through a single, high-level POM (...) Conversely, a POM project may aggregate projects that do not inherit from it.
From this I had my POMs inheritance (pom-master contains communes configurations, and each children the specifics ones) :
pom-master
|-- pom-java
|-- pom-flex
and so my project can get the specifics for each modules configurations as wished :
project (aggregate project-flex & project-java)
|-- project-java
| `-- pom.xml => parent = pom-java
|-- project-flex
| `-- pom.xml ==> parent = pom-flex
`-- pom.xml => parent = pom-master
Hope it will help others as well :)
Just image that pom.xml are in fact Java classes: you can have only one parent (or extends a class), but this parent can also have another parent, and so on.
As I explained here, you must distinguish the parent and aggregation principles in Maven, which means that my-plugin would be considered as an aggregation project, not necessarily a parent project for both my-plugin-client and my-plugin-parent.
So to summarize:
my-plugin will define the base pom for all your projects. Then, you create two new pom projects: java-base-pom and flex-base-pom. They have both my-plugin as parent. Now, my-plugin-client will have java-base-pom as parent, while my-plugin-server will use flex-base-pom for his parent.
This way, my-plugin-client will inherit all properties defined in the my-plugin pom.xml, and also from java-base-pom project.
You can achieve multiple inheritance with profiles:
You create (multiple) profiles in the root pom, and auto activate any variation of these profiles achieves multiple inheritance of maven configuration.

Categories