I am currently experimenting with Multi Modules for Springboot and I would to know what are the good or best practices when running tests within different modules that do not contain #SpringBootApplication annotation but have structures or beans like #RestController without errors such as:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.mavenmultimodule.controllers.AdditionController required a bean of type 'com.example.mavenmultimodule.services.SumService' that could not be found.
Action:
Consider defining a bean of type 'com.example.mavenmultimodule.services.SumService' in your configuration.
Failed test:
package com.example.mavenmultimodule.controllers;
imports...
#SpringBootTest(classes = AdditionController.class)
#AutoConfigureMockMvc
class AdditionControllerTest {
#Mock
private SumService sumService;
#Autowired
private MockMvc mockMvc;
#Test
public void shouldReturn5() throws Exception {
SumModel s = new SumModel();
s.setN1(2.0);
s.setN2(3.0);
Gson gson = new Gson();
String json = gson.toJson(s);
when(sumService.sum(s)).thenReturn(5.0);
MvcResult result = this.mockMvc.perform(
post("/sum")
.contentType(MediaType.APPLICATION_JSON)
.content(json)
)
.andExpect(status().isOk())
.andReturn();
assertEquals(5, result.getResponse());
}
}
I have the following structure:
Parent
- pom.xml
- addition
- pom.xml
- src
- main
- test
- subtraction
- pom.xml
- src
- main
- test
- application
- pom.xml
- src
- main
- test
Where application/src/main/MavenMultiModuleApplication contains the following code:
package com.example.mavenmultimodule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = "com.example.mavenmultimodule")
public class MavenMultiModuleApplication {
public static void main(String[] args) {
SpringApplication.run(MavenMultiModuleApplication.class, args);
}
}
The parent pom file contains the following:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<groupId>com.example</groupId>
<artifactId>mavenmultimodule</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mavenmultimodule</name>
<description>mavenmultimodule</description>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<modules>
<module>addition</module>
<module>subtraction</module>
<module>application</module>
</modules>
</project>
The application pom file contains the following:
<?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>
<!-- Parent for the dependencies -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>application</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Custom dependencies -->
<dependency>
<groupId>com.example</groupId>
<artifactId>addition</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>subtraction</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
And both addition and subtraction module contain pom contains:
<?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>
<!-- Parent for the dependencies -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>subtraction</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>
</dependencies>
</project>
Link to the repository in question on Github:
https://github.com/filipe-costa/maven-multi-module
Link to the failing test:
https://github.com/filipe-costa/maven-multi-module/blob/main/addition/src/test/java/com/example/mavenmultimodule/controllers/AdditionControllerTest.java
I ended up figuring it out thanks to Igor.
I not only had to add #MockBean to the service being mocked but also the following annotations to the testing class #WebMvcTest(controllers = AdditionController.class) and #ContextConfiguration(classes = AdditionController.class).
#WebMvcTest(controllers = AdditionController.class)
#ContextConfiguration(classes = AdditionController.class)
class AdditionControllerTest {
ObjectMapper objectMapper = new ObjectMapper();
#MockBean
private SumService sumService;
#Autowired
private MockMvc mockMvc;
#Test
public void shouldReturn5() throws Exception {
Double expectedValue = 5.0;
SumModel s = new SumModel();
s.setN1(2.0);
s.setN2(3.0);
String json = objectMapper.writeValueAsString(s);
given(this.sumService.sum(any())).willReturn(expectedValue);
this.mockMvc.perform(
post("/sum")
.accept(MediaType.APPLICATION_JSON_VALUE)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(json)
)
.andExpect(status().isOk())
.andExpect(content().string(expectedValue.toString()));
}
}
I am still unsure if it is a good practice to not have a SpringBootApplication annotated class in the addition module.
It works for what I needed to understand, I hope this might help others as well.
Related
I've recently started learning Spring and wanted to exercise a bit.
I've created a simple spring boot application, so far it contains only 1 controller with single #GetMapping, but when I try to test it in my browser I only get Whitelabel error. Could someone hint me in the right direction?
Controller:
package com.calculate.calories.web.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
#RestController
public class RecipeController {
#GetMapping("/recipe")
public String getRecipes() {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.aniagotuje.pl/client/posts/search?categories=ciasta-i-torty&diets=&occasions=&tags=&page=0&sort=publish,desc"))
.GET()
.timeout(Duration.of(10, ChronoUnit.SECONDS))
.build();
HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.of(15, ChronoUnit.SECONDS)).build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
return response.body();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
return "e";
}
}
Main:
package com.calculate.calories.start;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class SlimChefApplication {
public static void main(String[] args) {
SpringApplication.run(SlimChefApplication.class, args);
}
}
Main 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>config</module>
<module>persistence</module>
<module>common</module>
<module>application</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.calculate.calories</groupId>
<artifactId>slimchef</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SlimChef</name>
<description>SlimChef</description>
<packaging>pom</packaging>
<properties>
<java.version>17</java.version>
<project.version>0.0.1-SNAPSHOT</project.version>
</properties>
</project>
POM of application module (where controller is):
<?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>slimchef</artifactId>
<groupId>com.calculate.calories</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>application</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
</project>
POM of config module (start point of Spring application):
<?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>slimchef</artifactId>
<groupId>com.calculate.calories</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>config</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.calculate.calories</groupId>
<artifactId>application</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.calculate.calories</groupId>
<artifactId>persistence</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Screenshot
I can see 2 things "wrong" with your setup
You have both spring-boot-starter-web and `spring-boot-starter-webflux in your dependencies. You generally use 1 or the other not both.
To fix remove one of the dependencies and decide what you want, or specify what Spring should start. For this you can use the spring.main.web-application-type in your properties and set it to either SERVLET or REACTIVE.
Your #SpringBootApplication is in the com.calculate.calories.start and it will, by default, scan only in the package it is defined in (and its subpackages). Your controller is in com.calculate.calories.web.controller which doesn't match.
The best practice is to put your #SpringBootApplication in a top level package, in your case com.calculate.calories. If you don't you endup with a class with a lot of additional #ComponentScan/#IMport/#Enable* annotations, which kind of beats the purpose of auto configuration and detection.
So in short move your #SpringBootApplication class to com.calculate.calories instead of a sub-package.
*Ehcache3 not working with spring boot - I tried out with approach given below. Spring boot never caches the value mentioned in the component.It is getting called n - no of times no matter the cache is enable or not. In the logs it shows cache is added to cache manager but thats not the case here
ehcache.xml
<ehcache:config>
<ehcache:cache-template name="myDefaultTemplate">
<ehcache:expiry>
<ehcache:none/>
</ehcache:expiry>
</ehcache:cache-template>
<ehcache:cache alias="customer" uses-template="myDefaultTemplate">
<ehcache:key-type>java.lang.Long</ehcache:key-type>
<ehcache:value-type>com.controller.Customer</ehcache:value-type>
<ehcache:expiry>
<ehcache:tti unit="seconds">30</ehcache:tti>
</ehcache:expiry>
<ehcache:heap unit="entries">200</ehcache:heap>
</ehcache:cache>
</ehcache:config>
In my pom.xml i have the following configurations -
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.6.2</version>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<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>
Application.java which starts spring boot app
#SpringBootApplication
#ComponentScan(basePackages = {"com.service"})
#EnableCaching
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
Component class for caching -
#Component
public class CustomerService {
#Cacheable(cacheNames = "customer",key="#id")
public Customer getCustomer(final Long id){
System.out.println("Returning customer information for customer id
{}
"+id);
Customer customer = new Customer();
customer.setCustomerId(id);
customer.setFirstName("Test");
customer.setEmail("contact-us#test.com");
return customer;
}
}
I tried with couple of approaches by adding component scan in the application
but didn't worked out.
Spring boot starts and it shows cache has been added to cache manager.
I got it working by changing from #Component to #Service. I don't understand why caching is not working under component and works in service layer
If you want to add Caching annotation at the Repository layer then just remove #Repository Annotation, If you want to add Caching at Service Layer then use #Service Annotation instead of #Component Annotation.
I am trying to follow the below tutorial:
https://dzone.com/articles/spring-boot-jpa-hibernate-oracle
My project structure is as follows:
My pom is as below:
<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.nuril.work</groupId>
<artifactId>SpringBootHiberate</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
When I run the Application class as shown:
#SpringBootApplication
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class Application implements CommandLineRunner{
#Autowired
SoccerService soccerService;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void run(String... arg0) throws Exception {
soccerService.addBarcelonaPlayer("Xavi Hernandez", "Midfielder", 6);
List<String> players = soccerService.getAllTeamPlayers(1);
for(String player : players)
{
System.out.println("Introducing Barca player => " + player);
}
}
}
I get the below error:
Description:
Field playerRepository in com.nuril.work.service.SoccerServiceImpl required a bean of type 'com.nuril.work.repository.PlayerRepository' that could not be found.
Action:
Consider defining a bean of type 'com.nuril.work.repository.PlayerRepository' in your configuration.
I looked at other answers and they suggested to add #ComponentScan annotation.
I added the following
#SpringBootApplication
#ComponentScan("com.nuril.work.repository")
#ComponentScan("com.nuril.work.service")
However I am still getting the same error, what could be the reason for this?
Try to add #EnableJpaRepositories(basePackages="com.nuril.work.repository") onto Application class.
See docs: https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/config/EnableJpaRepositories.html
Also, check if your repositories have #Repository annotation.
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.sit</groupId>
<artifactId>multi-module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<modules>
<module>one</module>
<module>app</module>
</modules>
<packaging>pom</packaging>
<name>multi-module</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.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-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<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>
app module POM
spring boot main class resides on this module
<?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>multi-module</artifactId>
<groupId>com.sit</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>app</artifactId>
<dependencies>
</dependencies>
</project>
One module (child module) 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>multi-module</artifactId>
<groupId>com.sit</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>one</artifactId>
<packaging>jar</packaging>
<dependencies>
</dependencies>
</project>
Spring Boot Main Class from app module
package com.sit.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan(basePackages = {"com.sit"})
#EntityScan(basePackages = {"com.sit"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
AppController from app module
package com.sit.app.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class AppController {
#GetMapping(value = "/app")
public String getPage(){
return "app";
}
}
OneController class from one module
package com.sit.one.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class OneController {
#GetMapping(value = "/one")
public String getPage(){
return "one";
}
}
When I run the project AppController.java is working fine by "/app" url.But when I try to access "/one" url of OneController.java ,I got the error page.No #Controller or #RestController is working from child (one) module.To solve this issue I added #ComponentScan(basePackages = {"com.sit"}) in Application.java, but still I am getting the error page.Can any help please.Thanks in advance.
The issue is that com.sit:one is not on the classpath of com.sit:app. Due to this, none of the classes of the one module can be found when you start the application module.
The solution is to make sure that the com.sit:one module is a dependency of com.sit:app by adding the following to pom.xml of the application module:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>one</artifactId>
<version>${project.version}</version>
</dependency>
However, this is not enough, since the spring-boot-maven-plugin will create a fat JAR of both modules, while you only need a fat JAR of your application module (the runnable module).
I suggest that you move the <plugin> to the pom.xml of the application module:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
And then you should remove the plugin from the parent pom.xml.
I'm just started working on Spring Boot and having issues while running the spring boot application. SO scenario is - i have two project
One is called Parent Project SpringBoot and
Other project called web-app is maven module which added in Parent project as module.
In Both Projects(Parent and child) i have Application classes which load the context but somehow when i start the application it gives me some exceptions like on project SpringBoot: Unable to find a suitable main class, please add a mainClass property
On top of that when i run the web-app separately then it works but when i run it through Parent Project SpringBoot it throws me exceptions
Here is my code structure of Spring Boot Project (Parent Project)
Application.java
#Configuration
#ComponentScan
#EnableAutoConfiguration
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Example.java
#RequestMapping("/api/**")
#RestController
public class Example {#RequestMapping(method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
public String index() {
return "Hello World";
}
}
Pom.xml
<?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>SpringBoot</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
</parent>
<!-- Additional lines to be added here... -->
<modules>
<module>web-app</module>
</modules
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Second project which is web-app:
ApplicationWebApp.Java
#Configuration
#ComponentScan
#EnableAutoConfiguration
#SpringBootApplication
ApplicationWebApp
public class ApplicationWebApp {
public static void main(String[] args) {
SpringApplication.run(ApplicationWebApp.class, args);
}
}
Example.java
#RequestMapping("/apis/**")
#RestController
public class Example {#RequestMapping(method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
public String index() {
return "Hello World";
}
}
Pom.xml
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>SpringBoot</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>web-app</artifactId>
</project>
I found couple of solutions on the stackoverflow and different forums by adding
<properties>
The main class to start by executing java -jar
<startclass>com.dashboard.backend.controllers.Application</startclass>
</properties>
By this way, i need to add this properly file in each n every pom.xml to load it. Since this is a web based application so I'm not sure whether its a good solution or not..
If anyone have tried any solution for this problem please share you findings