Home > Back-end >  SpringBoot pass local variable
SpringBoot pass local variable

Time:05-25

I'm creating a Java application that depending on certain conditions/configurations it instantiates a SpringBoot application to receive some HTTP messages.

My problem is that I have a ReceiverService that needs to use some variables that are created outside of the SpringBoot application. Is there a way to pass local java variables (from inside the application, not outside like the shell or files) to SpringBoot components?

Example:

I have a Manager object that, depending on some conditions, it defines a variable param that I want to use in the SpringBoot Component ReceiverService.

public class Manager {

    public Manager(bool condition) {
         String param = "foo";
         if (condition) {
             param = "bar";
         }
         
         ReceiverApp receiver = new ReceiverApp(); // init SpringBoot app
    }
}

The SpringBoot app:

@SpringBootApplication
public class ReceiverApp {

    public ReceiverApp() {

        SpringApplication.run(ReceiverApp.class);
    }
@Component
public class ReceiverService implements InitializingBean {

    final CustomObject obj1 = new CustomObject(param);

    @Override
    public void aFunction() throws Exception {
        MyConfig config = MyConfig.build(param);
    }
}

CodePudding user response:

There are several ways to create a manager app which configures another app.

Scenario 1

A common way is to put the config in a database which is accessed directly by both apps, although this is less clean (it creates a hard dependency via the database).

Scenario 2

A cleaner solution is if the manager app owns the database, and offers a config service which is consumed (and presumably cached) by the configured app. Typically the config service would be accessed via remoting, e.g. REST, so the two apps can be deployed and run independently.

Scenario 3

If you want to keep it simple, you could reverse the setup and implement the config service in the configured app itself (sort of like the management interface in Tomcat). Then you could either add a web UI in the same app and be done with it, or build a separate standalone client which interacts with that service. In this last two scenarios, think about security because you might not want any client to be able to connect and change the config.

three scenarios

CodePudding user response:

You can have ReceiverService inject a Supplier<String> (or define your own interface if you prefer a less generic naming) and make Manager implement it.

@Component
public class ReceiverService implements InitializingBean {
    @Autowired
    private Supplier<String> paramSupplier;

    final CustomObject obj1 = new CustomObject(param);

    @Override
    public void aFunction() throws Exception {
        MyConfig config = MyConfig.build(paramSupplier.get());
    }
}

public class Manager implements Supplier<String> {
    private final String param;
    public String get() { return param; }

    public Manager(bool condition) {
         param = "foo";
         if (condition) {
             param = "bar";
         }
         
         // why is this in the Manager constructor???
         ReceiverApp receiver = new ReceiverApp(); // init SpringBoot app
    }
}

Or you define your own @Component to supply the parameter and have both manager and receiver inject it.

CodePudding user response:

SpringApplication.run is designed to accept key=value pairs like the ones you give in command line parameters to the main method in Java.

Since you seem to have the other Spring boot application jar in your class-path, and seem to be able to just instanciate the ReceiverApp, you could just pass the parameters as strings (of the format String[]{"key1=value1", "key2=value2"})

These can be passed to SpringApplication.run, and these will automatically become Spring configuration values, which can be injected anywhere in the application.

@SpringBootApplication
public class ReceiverApp {

    public ReceiverApp(String[] notReallyFromCommandLineArgs) {

        SpringApplication.run(ReceiverApp.class, notReallyFromCommandLineArgs);
    }

You can send the parameters like this:

String[] params = new String[]{"my.params.param1=" param1};
ReceiverApp receiver = new ReceiverApp(params);

You can inject them anywhere in that Receiver Spring application as a value.

@Value("my.params.param1")
String theParam1;

Refer: https://stackoverflow.com/a/55890457/1364747

  • Related