0

I am trying to create a lightweight web service around a legacy java library to expose it as a web service using Spring Boot. I am new to Spring, while I have a lot of java experiance writing libraries all my web service experiance is in ASP.NET.

I can instantiate an instance of my library object but I can't figure out how to then have that object be injected into my controllers via @Autowired when the application is spun up.

This is my main application:

@SpringBootApplication
public class ResolverWebServiceApplication {
    
    private static ArgumentParser newArgumentParser() {
        ArgumentParser parser = ArgumentParsers.newFor("Resolver").build();
        // configuring the parser
        return parser;
    }

    public static void main(String[] args) throws ArgumentParserException {
        
        ArgumentParser parser = newArgumentParser();
        Namespace ns = parser.parseArgs(args);
        ResolverOptions options = new ResolverOptions.Builder(ns)
                .build();
        ResolverContext context = new ResolverContext(options);
        // ^^^ I need to get this injected into my controllers ^^^
        
        SpringApplication.run(ResolverWebServiceApplication.class, args);
    }

}

And then a simple controller which needs the class injected:

@RestController
public class VersionController {
    
    @Autowired
    private ResolverContext context; // And here the instance needs to be injected.

    @GetMapping(path = "/version", produces = MediaType.APPLICATION_JSON_VALUE)
    public long version() {
                
        return context.getResolver().getVersionAsLong();
    }
}

I could make the context a singleton which the controllers just refer to but I want to be able to test my controllers by mocking the context. There is also obviously a lot of validation and error handeling that needs to be added.

I can't have it be a Bean since I only want to instantiate one for my entire application.

The closest question I have found is this one: Registering an instance as 'singleton' bean at application startup. But I can't put the options in the configuration files. The application might be spun up in a container or on a users machine and requires the ability to accept arguments to initialize the library class. It would be a real usability degradation if someone had to manually edit the application config for these options.

Hangman4358
  • 411
  • 1
  • 4
  • 11

1 Answers1

0

You need to tell spring to consider the required classes from your lib when initializing the application context i.e Configure and let spring know how to create a bean and then let spring handle dependency injection for you.

First of all, add required jar that you have in your build file, say pom.xml for maven, in your current project. Idea is to have it on your classpath when you build the project.

As you said it is legacy lib and I am assuming it is not a spring bean, then

In your configuration class, return it as a bean, using @Bean annotaion.

@Configuration
public class YourConfigurationClass {    

@Bean
SomeBean returnSomeBeanFromLegacyLib() {
    return new SomeClassFromLib();
}

Once you return this bean from your config, it should be available to Spring Context for dependency injection whereever you @Autowire the required dependency.

Mahesh_Loya
  • 2,743
  • 3
  • 16
  • 28
  • I got this far in the Guides and tutorials, but I need to be able to configure the Bean based on startup params. I can't instantiate an instance of my `@Configuration` class and pass that to the application either as far as I can tell so I can't wrap the construction logic in the configuration class. The problem is that I need to be able to configure my class based on the commandline arguments the service is started with and not just call a predefined setup for it. – Hangman4358 Nov 07 '20 at 17:44
  • Just make sure your [cmdline options can be mapped to configuration properties](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-command-line-args) and use `@Value("${my.property}")` to inject the config param into `YourConfigurationClass` (as a field or a parameter to `returnSomeBeanFromLegacyLib`). You should end up with sth like `SomeBean returnSomeBeanFromLegacyLib(@Value("${my.property}") String myProperty)` – crizzis Nov 07 '20 at 20:02