21

I've spent quite some time but I can't get past this (configuration) issue.

Technology stack : Java (1.8), Springboot (starter-parent, starter-web), Maven, IntelliJ IDEA

Description: Trying to create a multi module Java application composed (at first) of 2 modules :

  1. core module : main module (main business logic, every other module should see and interact through this one). This module contains the main application class.
  2. webgateway module : Simple Rest Controller that will map a request and make calls to the core module

Issue: Springboot doesn't load/scan the RestController from the webgateway module => 404 error when sending the http request

Github repo : https://github.com/Sorin-J/Greeter

Project configuration :

Greeter 
   |
   + pom.xml (parent pom)
   |
   + -- core                                            
   |     |
   |     + ...
   |     |
   |     + pom.xml
   |
   + -- webgateway 
         |
         + ...
         |
         + pom.xml (depends on core pom.xml)

Parent 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.bet.jbs</groupId>
    <artifactId>Greeter</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <modules>
        <module>core</module>
        <module>webgateway</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

core module 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">

    <parent>
        <artifactId>Greeter</artifactId>
        <groupId>com.bet.jbs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <artifactId>core</artifactId>

</project>

webgateway module 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">

    <parent>
        <artifactId>Greeter</artifactId>
        <groupId>com.bet.jbs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <artifactId>webgateway</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.bet.jbs</groupId>
            <artifactId>core</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

MainApplication class from core module :

package com.bet.jbs.core;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"com.bet.jbs.core", "com.bet.jbs.webgateway"})
@EnableAutoConfiguration
public class MainApplication {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(MainApplication.class, args);
    }
}

GreetingController class from webgateway module :

package com.bet.jbs.webgateway.controller;

import com.bet.jbs.core.util.GreetingGenerator;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    @RequestMapping(value = "/webgreeting", method = RequestMethod.GET)
    public String getGreeting() {
        return "WEBGATEWAY module says " + GreetingGenerator.getRandomGreeting();
    }
}

Just to test that an identical REST controller would work fine if it is located in the core module, I've created a similar GreetingController class also in core module (and this one works fine) :

package com.bet.jbs.core.controller;

import com.bet.jbs.core.util.GreetingGenerator;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/*
 * This REST controller should not be in the CORE component.
 * It is just for proving that this controller is recognized and the other one from WEBGATEWAY component is not.
 *
 */
@RestController
public class GreetingController {

    @RequestMapping(value = "/coregreeting", method = RequestMethod.GET)
    public String getGreeting() {
        return "CORE module says " + GreetingGenerator.getRandomGreeting();
    }
}
Sorin J
  • 542
  • 1
  • 4
  • 14

4 Answers4

16

The Spring Boot main application is in the core module, which does not have a dependency on the webgateway module. Therefore the class with the controller will not be present at runtime and can not be discovered by spring.

Fix: Add dependency to the webgateway to the core or move the launcher/main class to the webgateway module.

You can also use a third module that does the launching and has the dependencies to core and webgateway.

Lii
  • 11,553
  • 8
  • 64
  • 88
Thomas
  • 11,272
  • 2
  • 24
  • 40
  • 1
    Already have a dependency from webgateway -> core. Adding a reversed one will throw (Annotation processing is not suppoted for module cycles). Furthermore, the core should not depend on a specific gateway. We could deploy the project using another gateway (LAN TCP/IP for e.g). I will try the option with a third module. – Sorin J May 10 '16 at 08:45
  • Indeed you should avoid a cycle. I had that in mind when suggesting a third module to get clean dependencies, but did not explain that correctly. – Thomas May 10 '16 at 08:53
  • Works ok with a third model (dependent on both core & webgateway). It is a bit strage to have an entire module just to start up the application (seems a bit overkill), but if there is no other elegant way of solving this, I'm ok with it. Thanks for the feedback. – Sorin J May 10 '16 at 09:05
  • Glad to hear it works out. Regarding the strange feeling: I tend to start with a single module project, especially when using Spring Boot. If it grows too large, I try to separate it into multiple separate applications. If there is common functionality you can extract a core module. – Thomas May 10 '16 at 09:51
  • What if i do have the third module with the needed dependency and spring still doesn´t find that Controller? – Juan Monsalve Apr 02 '20 at 15:02
  • 1
    @JuanMonsalve I had that issue as well. Got it fixed with 2 steps: 1.) maven: clean + install on the parent project. 2.) IntelliJ => File => Invalidate Caches/Restart. – Tigerware Feb 15 '21 at 21:33
  • thanks for answering @BluE, a little late xd but still useful for coming people. It seems like those two steps fixes a lot issues from Intellij – Juan Monsalve Feb 17 '21 at 04:24
5

I was stuck in this problems since last one day... The solution below will save you a lot of time for sure!

Here is how I solved it:

  1. Create a separate module for main Application class.

    x-service

    • pom.xml (parent)
    • child1-module
      • pom.xml
    • child2-module
      • pom.xml
    • app-module
      • pom.xml (contains dependency for both child1 and child2)
      • src/main/java/Application.java
  2. Add all the modules as dependencies in the pom of the module having application class.

     <?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>x-service</artifactId>
         <groupId>com.a.b.c</groupId>
         <version>0.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
    
     <artifactId>app-module</artifactId>
    
     <dependencies>
         <dependency>
             <groupId>com.a.b.cs</groupId>
             <artifactId>child1-module</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>com.a.b.cs</groupId>
             <artifactId>child1-module</artifactId>
             <version>0.0.1-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
     </dependencies>
    
     <build>
         <resources>
             <resource>
                 <directory>src/main/resources</directory>
                 <filtering>true</filtering>
             </resource>
         </resources>
         <plugins>
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
                 <configuration>
                     <executable>true</executable>
                 </configuration>
             </plugin>
         </plugins>
     </build>
    
  3. Keep the main pom as 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>
     <packaging>pom</packaging>
     <modules>
         <module>child1-module</module>
         <module>child2-module</module>
         <module>app-module</module>
     </modules>
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
         <version>2.1.2.RELEASE</version>
         <relativePath/>
     </parent>
    
     <groupId>com.a.b.c</groupId>
     <artifactId>x-service</artifactId>
     <version>0.0.1-SNAPSHOT</version>
    
     <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-web</artifactId>
         </dependency>
    
    
     </dependencies>
    
     <build>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-checkstyle-plugin</artifactId>
                 <version>3.0.0</version>
             </plugin>
         </plugins>
     </build>
    
  4. Add the parent pom artifect as parent in all child poms.

     <?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>dxg-service</artifactId>
         <groupId>com.a.b.c</groupId>
         <version>0.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
    
     <groupId>com.a.b.c</groupId>
     <artifactId>child1-module</artifactId>
     <version>0.0.1-SNAPSHOT</version>
    
     <dependencies>
         <dependency>
             <groupId>com.a.b.c</groupId>
             <artifactId>child2-modulde</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
     </dependencies>
    

More details here: https://medium.com/macoclock/how-create-multi-module-project-in-intellij-on-macos-50f07e52b7f9

KayV
  • 12,987
  • 11
  • 98
  • 148
0

I had added the correct dependency and Spring Boot still did not find my new Controller. Seems like IntelliJ IDEA (2020.3.2) or Maven (3.3.6) don't update properly when a module gets added. This solved it for me:

  1. Maven: clean + install on the parent project

  2. In IntelliJ from the file menu Invalidate Caches / Restart..

Tigerware
  • 3,196
  • 2
  • 23
  • 39
0

as mentioned you should have parent pom with setup spring web starter in that and other modules must get that parent pom as their parent. be carful to add your root pom project to maven. to do this open maven in IDE and add pom.

Master mj
  • 73
  • 3