Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two Spring Boot projects both with @SpringBootApplication

I have a data project and UI project. Both projects are Spring Boot applications. Both projects have the same root package (com.myorg) with a main class annotated with @SpringBootApplication.

Data project's main class is:

package com.myorg;
@SpringBootApplication
public class DataApplication {

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

}

The UI project's main class is:

package com.myorg;
@SpringBootApplication
public class UiApplication {

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

}

The UI project depends on the data project via the following Gradle dependency:

dependencies {
    compile('com.myorg:data:1.0')
}

If I run the UI application, it runs without issue. However, if I run an integration test within the UI application such as follows:

package com.myorg
@RunWith(SpringRunner.class)
@SpringBootTest
public class UiIntTest {

    @Test
    public void contextLoads() {
    }

}

The following initialization error occurs:

java.lang.IllegalStateException: Found multiple @SpringBootConfiguration annotated classes

In the data project's main class, if I replace @SpringBootApplication with

@Configuration
@EnableAutoConfiguration
@ComponentScan({ "com.myorg" })

I get the following initialization error when trying to run its integration tests:

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

For example, if I try to run:

package com.myorg
@RunWith(SpringRunner.class)
@SpringBootTest
public class DataIntTest {

    @Test
    public void contextLoads() {
    }

}

How can I properly configure the data and UI projects?

like image 513
James Avatar asked Jan 18 '17 21:01

James


People also ask

Can two spring boot applications run on same port?

No you can have only one application listening on a specific port at a time.

Is @SpringBootApplication mandatory?

@SpringBootApplication Annotation Features not Mandatory.

Can we run spring boot application without @SpringBootApplication?

It's not mandatory to put @SpringBootApplication to create a Spring Boot application, you can still use @Configuration and @EnableAutoConfiguration individually as shown in the example given in the next point.


2 Answers

You need to specify which Spring Boot Main class to use along with @SpringBootTest:

@SpringBootTest(classes = YourUiSpringBootApp.class)
like image 118
alexbt Avatar answered Oct 16 '22 10:10

alexbt


You shouldn't have two SpringApplication annotations in the same package.

Package one.

twoapps.one;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackageClasses = {One.class})
@EnableAutoConfiguration
public class One extends SpringApplication {
}

Package two.

twoapps.two;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackageClasses = {Two.class})
@EnableAutoConfiguration
public class Two extends SpringApplication {

}

Root package and launcher

package twoapps;

import org.springframework.boot.SpringApplication;
import twoapps.one.One;
import twoapps.two.Two;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Application {

    public static void main(String[] args) throws Exception {
        new Thread(() -> SpringApplication.run(One.class, args(args, "--spring.profiles.active=one"))).start();
        new Thread(() -> SpringApplication.run(Two.class, args(args, "--spring.profiles.active=two"))).start();
    }

    private static String[] args(String[] args, String s) {
        List<String> collect = Arrays.stream(args).collect(Collectors.toList());
        collect.add(s);
        String[] strings = collect.toArray(new String[]{});
        return strings;
    }
}

This is a terrible idea. please don't do it. It is much better to have two different projects and a common project.

like image 6
Olayinka Avatar answered Oct 16 '22 10:10

Olayinka