Creating multi module project using Intellij & Maven - java

I have a project structure which has a core tool and a REST API to interact and configure that tool.
I have a package structure like this:
com.example.api -> contains API definitions
com.example.commons -> contains module common to both core and api
com.exmaple.core -> contains the core module
This is primarily a Spring Boot application and both will run in different containers. So the API and the Core jar will be different.
How do I create a multi-module project with this structure so that I can also use the commons module in both the sub packages(core & api).
Suggestions on how to configure Maven and IntelliJ in such an environment?
Is my pattern right? Are there other well known patterns for this kind of project structure?

You can have a multi Maven module project as you wish. Here's an example on how you should configure your modules:
Create a parent pom.xml as follows (note that I am not adding spring-boot-starter-parent as a parent to the project, I am bringing in the Spring Boot dependencies with spring-boot-dependencies):
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>example-commons</module>
<module>example-core</module>
<module>example-api</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>1.5.3.RELEASE</version>
</dependency>
</dependencies>
</project>
And a non executable module's pom.xml would be like:
<?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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>com.example</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>example-commons</artifactId>
</project>
whereas an executable module's pom.xml would be like (note the spring-boot-maven-plugin is present only here for this dependency):
<?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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>com.example</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>example-core</artifactId>
<build>
<plugins>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-maven-plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.3.RELEASE</version>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>example-commons</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

Related

Occurred an error while packaging spring-boot application by maven

The IDEA app told me that Invalid packaging for parent POM org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE, must be "pom" but is "jar" while I packaged my easy-start spring-boot application, how to solve this problem?
My platform is macOS 10.15.7 with 3 JDKs(1.8, 11, 14), and I am using maven-3.6.3, my maven settings are also changed the JDK to 1.8 and 11
The pom.xml file is as followed:
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringBoot-01-HelloWorld</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<parent>
<artifactId>spring-boot-starter-web</artifactId>
<groupId>org.springframework.boot</groupId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The parent POM should be the Spring Boot parent project
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>

How to remove transitive dependency from pom

Problem with Child module is that it inherent the dependency from parent pom. However parent pom marked that dependency with option tag.
This is the parent pom:
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.parent</groupId>
<artifactId>Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Parent</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<modules>
<module>Child</module>
</modules>
</project>
This is Child pom:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.parent</groupId>
<artifactId>Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>org.child</groupId>
<artifactId>Child</artifactId>
</project>
Problem is when I starts child module, I can see tomcat initialization. I dont want to load tomcat for child module. How do I restrict tomcat dependency in child module? Do I need to define additional configuration to exclude it ?
I already tried with exclusion tag but it didn't work.
As you already mentioned you'll have to exclude those transitive Tomcat dependencies. Here's an example for doing so - not in a child module though but it should be similar:
How to exclude embeded Tomcat in Spring Boot application
This is not actually solution to this concern. However I got something that can do this trick to stop initializing tomcat for child modules. All that need is to disable it through
spring.main.web-application-type=none
More details can be found on this thread
Spring boot enable/disable embedded tomcat with profile

How to package a maven multi-module properly?

I'm building a multi-module rest service with Maven and Spring Boot that will be published on a WebLogic Server, and I'm a bit confuse about how to configure the packaging of the application modules.
My current structure is:
/application
/main (main mehtod for spring-boot)
/api
/service
/dao
The parent project (application folder) is set up as pom packaging, but child projects I'm not sure how to configure it. I believe the correct way would be packaging like .jar file, but i saw some examples on the internet of Java projects with Maven multi-modules defined as war.
can someone tell me what's the correct way to define the child modules packaging in this case?
My parent pom:
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.radarveicular</groupId>
<artifactId>radarveicular-application</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<javax.inject.version>1</javax.inject.version>
</properties>
<modules>
<module>radarveicular-api</module>
<module>radarveicular-service</module>
<module>radarveicular-main</module>
<module>radarveicular-dao</module>
</modules>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<wtpversion>2.0</wtpversion>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
main pom:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.radarveicular</groupId>
<artifactId>radarveicular-application</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>radarveicular-main</artifactId>
<dependencies>
<dependency>
<groupId>com.radarveicular</groupId>
<artifactId>radarveicular-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Spring Framework -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
api pom:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.radarveicular</groupId>
<artifactId>radarveicular-application</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>radarveicular-api</artifactId>
<dependencies>
<dependency>
<groupId>com.radarveicular</groupId>
<artifactId>radarveicular-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
service pom:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.radarveicular</groupId>
<artifactId>radarveicular-application</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>radarveicular-service</artifactId>
<dependencies>
<dependency>
<groupId>com.radarveicular</groupId>
<artifactId>radarveicular-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
</dependencies>
</project>
dao pom:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.radarveicular</groupId>
<artifactId>radarveicular-application</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>radarveicular-dao</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
I think your problem is that your parent pom.xml shouldn't handle your spring boot project. Meaning, you should have this in it :
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
I recommend that your pom.xml parent only handles your modules and dependencies as pom packaging :
Packaging
<packaging>pom</packaging>
Modules
<modules>
<module>radarveicular-api</module>
<module>radarveicular-service</module>
<module>radarveicular-main</module>
<module>radarveicular-dao</module>
</modules>
Then, you will have your module radarveicular-main with the spring boot parent :
Parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
Packaging
<packaging>war</packaging>
I hope this will help you. =)
I feel your question is more towards designing part of multi module.
Multi module management of application can depend on various things.
One thing could be if you want to deploy each sub module as separate module/service based, which can be turned off/on based on need. In that case it would help you if you build each of module as separate war and deploy them separately.
If you have to deploy it as a single war than most straight forward would to create all dependent modules as jar and include them in parent project. In this way a single war will be deployed.
You can have a hybrid approach of above two.
Hopefully i have understood your question correctly. :)
Happy coding!!

Managing Spring Boot parent POM version in multiple projects

I've created a few Spring Boot projects, each one's POM including a spring-boot-starter-parent as a parent. Whenever a new version comes out, I currently need to manually update it in every POM.
Adding a POM dependency which already has the spring-boot-starter-parent does not help, and the Spring Boot documentation states that using an 'import' scope will only work for dependencies, and not the Spring Boot version itself.
Is there a way to define a "super-pom" which all my projects can inherit from, where I can set the Spring Boot version once, and not go through each project?
Here is an approach you can try.
Your parent POM:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Do you really need to have this parent? -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.7.RELEASE</version>
</parent>
<groupId>org.example</groupId>
<artifactId>my-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Parent POM</name>
<properties>
<!-- Change this property to switch Spring Boot version-->
<spring.boot.version>1.2.7.RELEASE</spring.boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Declare the Spring Boot dependencies you need here
Please note that you don't need to declare the version tags.
That's the whole point of the import above.
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<!-- About 50 in total if you need them all -->
...
</dependencies>
</project>
A child POM:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>my-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>my-child</artifactId>
<name>Child POM</name>
</project>
If you do a mvn dependency:tree on the child POM, you'll see that they are all in there.

Spring boot JSP configuration not working

I followed the sample Git setup here: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-web-jsp.
When I load the home page it displays resource could not be found. Even when I've cross-checked my configuration and the only difference between the two projects is that one is multi-module, while the other is single module.
And it worked, but for my multi-module maven project the same configuration seems to not be working... is there any explanation to this? I'm also kind of new to maven so I'm assuming it has something to do with the way I have my maven setup configured. The link to my GitHub repo is: https://github.com/diljotr/storm.net.
Relevant links to look at are:
https://github.com/diljotr/storm.net/blob/master/storm.net.app/src/main/java/storm/net/Application.java
https://github.com/diljotr/storm.net/blob/master/storm.net.web/src/main/java/storm/net/controller/HomeController.java
https://github.com/diljotr/storm.net/blob/master/storm.net.web/src/main/java/storm/net/WebApplication.java
Setup outlined below
Parent POM:
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>storm.net</groupId>
<artifactId>storm.net</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.1.RELEASE</version>
</parent>
<modules>
<module>storm.net.api</module>
<module>storm.net.core</module>
<module>storm.net.web</module>
<module>storm.net.app</module>
</modules>
<properties>
<spring.version>4.0.3.RELEASE</spring.version>
<tomcat.version>7.0.53</tomcat.version>
<!-- Spring Boot build configuration -->
<java.version>1.7</java.version>
<start-class>storm.net.Application</start-class>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</plugin>
</plugins>
</build>
</project>
Web Child POM:
<?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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>storm.net</artifactId>
<groupId>storm.net</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>storm.net.web</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/webapp</directory>
</resource>
</resources>
</build>
</project>
App POM that wraps the entire library together
<?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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>storm.net</artifactId>
<groupId>storm.net</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>storm.net.app</artifactId>
<dependencies>
<dependency>
<groupId>storm.net</groupId>
<artifactId>storm.net.core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>storm.net</groupId>
<artifactId>storm.net.web</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Follow below Configuration :
In Intellij:
Go to Run Menu -> Edit Configuration -> Working directory: $MODULE_WORKING_DIR$
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp

Categories

Resources