I have the below code when i put some properties statically in SpringApplicationBuilder
#SpringBootApplication(scanBasePackages = { "com" })
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplicationBuilder parentBuilder = new SpringApplicationBuilder(Application.class);
parentBuilder.child(RestConfiguration.class, SwaggerConfig.class)
.properties("server.port:9093")).web(WebApplicationType.SERVLET).run(args);
}
}
I want to move the properties to the file application.properties
application.port.query=9093
I used #value to read from the application file, but i get null. Is there another way to read data in a static method?
try something like this
#Configuration
#ConfigurationProperties("application")
class A {
public static int queryPort;
#Value("${port.query:9093}")
public void setQueryPort(final int portQuery){
A.queryPort = portQuery;
}
}
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplicationBuilder parentBuilder = new SpringApplicationBuilder(Application.class);
parentBuilder.child(RestConfiguration.class, SwaggerConfig.class)
.properties(A.queryPort)).web(WebApplicationType.SERVLET).run(args);
}
}
The preferable way to what you are trying to achieve is to use the spring bean itself which is the parent of your all configurations org.springframework.core.env.Environment
#SpringBootApplication(scanBasePackages = {"com"})
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext =
SpringApplication.run(Application.class, args);
Environment environment = applicationContext.getBean(Environment.class);
String propertyValue = environment.getProperty("any.property.from.configuration")
}
}
In your use-case, just get the bean of Environment and from Environment object get any property value.
Related
Application.java
#SpringBootApplication(scanBasePackages = {"ru.pcask.clients",
"ru.pcask.activities"
})
#EntityScan(value={"ru.pcask.clients",
"ru.pcask.activities"})
#EnableJpaRepositories(value={"ru.pcask.clients",
"ru.pcask.activities"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
"ru.pcask.clients" seems to be a constant. But I don't know how to organize it?
I tried like this:
Constants.java
#Configuration
public class Constants {
private static final String CLIENT = "ru.pcask.clients";
#Bean
public String getClientConst() {
return this.CLIENT;
}
}
But this seems to be a garbage. I don't even know how to use it in #SpringBootApplication.
I have SpringBootApplication that takes args
public class RocksdbBootApp {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(RocksdbBootApp.class);
app.setDefaultProperties(Collections.singletonMap("server.port", args[0]));
app.run(args);
}
}
How can I get access to args in RestController?
#Slf4j
#RestController
#RequestMapping("/api/rocks")
public class RocksApi {
public RocksApi(KeyValueRepository<String, String> rocksDB) {
System.out.println(args[0]);
}
}
To access arguments passed to your application you can make use of ApplicationArguments and inject it into your controller :
#Slf4j
#RestController
#RequestMapping("/api/rocks")
public class RocksApi {
private final ApplicationArguments arguments;
#Autowired //can be ommited in new versions of Spring
public RocksApi(final ApplicationArguments arguments) {
this.arguments = arguments;
}
public RocksApi(KeyValueRepository<String, String> rocksDB) {
String[] args = arguments.getSourceArgs();
System.out.println(args[0]);
}
}
afaik, you're setting an application property, and can acccess that like any other Spring property:
#Slf4j
#RestController
#RequestMapping("/api/rocks")
public class RocksApi {
#Value("${server.port}")
private Integer serverPort;
I already managed to start Spring Shell using Spring Boot:
#SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class);
}
}
All my #ShellComponent classes are detected and I can use the shell as expected.
Now I would like to run the shell without Spring Boot, I expect it to look something like this
Shell shell = context.getBean(Shell.class);
shell.run(...);
What approach should I take to configure all required dependencies myself?
Thanks in advance!
By extracting the necessary parts of ebottard's link (Thank you!) I finally managed to run the shell like I wanted:
#Configuration
#Import({
SpringShellAutoConfiguration.class,
JLineShellAutoConfiguration.class,
JCommanderParameterResolverAutoConfiguration.class,
StandardAPIAutoConfiguration.class,
StandardCommandsAutoConfiguration.class,
})
public class SpringShell {
public static void main(String[] args) throws IOException {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringShell.class);
Shell shell = context.getBean(Shell.class);
shell.run(context.getBean(InputProvider.class));
}
#Bean
#Autowired
public InputProvider inputProvider(LineReader lineReader, PromptProvider promptProvider) {
return new InteractiveShellApplicationRunner.JLineInputProvider(lineReader, promptProvider);
}
}
See this example that shows how to wire up everything without relying on Autoconfiguration.
without Spring Boot I write this:
#Configuration
#ComponentScan(value = {"path.to.commands", "org.springframework.shell.commands", "org.springframework.shell.converters", "org.springframework.shell.plugin.support"})
public class TestShell {
private static String[] args;
#Bean("commandLine")
public CommandLine getCommandLine() throws IOException {
return SimpleShellCommandLineOptions.parseCommandLine(args);
}
#Bean("shell")
public JLineShellComponent getShell() {
return new JLineShellComponent();
}
public static void main(String[] args) {
TestShell.args = args;
System.setProperty("jline.terminal", "none");
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(TestShell.class);
ctx.registerShutdownHook();
JLineShellComponent shell = ctx.getBean(JLineShellComponent.class);
shell.start();
shell.waitForComplete();
ExitShellRequest exitShellRequest = shell.getExitShellRequest();
if (exitShellRequest == null)
exitShellRequest = ExitShellRequest.NORMAL_EXIT;
System.exit(exitShellRequest.getExitCode());
}
}
and command class:
#Component
public class Hello implements CommandMarker {
#CliCommand(value="hi", help = "say hello.")
public String hi() {
return "hello";
}
}
see org.springframework.shell.Bootstrap.
I have spring boot application with profiles. Now I want to switch profile at runtime, refresh spring context and continue application execution. How to switch active profile at runtime (switchEnvironment method)?
#SpringBootApplication
public class Application implements CommandLineRunner {
#Autowired
private Config config;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void run(String ... strings) throws Exception {
System.out.printf("Application is running in %s environment, service parameters below:\n",
getEnvProperty("spring.profiles.active").toUpperCase());
printServiceParameters();
switchEnvironment();
printServiceParameters();
}
private String getEnvProperty(String propertyName) {
return config.getEnv().getProperty(propertyName);
}
private void printServiceParameters() {
System.out.println(getEnvProperty("service.endpoint"));
}
private void switchEnvironment() {
//todo Switch active profile
}
}
Config.class
#Configuration
#ConfigurationProperties
public class Config{
#Autowired
private ConfigurableEnvironment env;
public ConfigurableEnvironment getEnv() {
return env;
}
public void setEnv(ConfigurableEnvironment env) {
this.env = env;
}
}
All what you need, it's add this method into your main class, and create Controller or Service for call this method.
#SpringBootApplication
public class Application {
private static ConfigurableApplicationContext context;
public static void main(String[] args) {
context = SpringApplication.run(Application.class, args);
}
public static void restart() {
Thread thread = new Thread(() -> {
context.close();
context = SpringApplication.run(Application.class, "--spring.profiles.active=your_profile");
});
thread.setDaemon(false);
thread.start();
}
}
Controller:
#RestController
public class RestartController {
#PostMapping("/restart")
public void restart() {
Application.restart();
}
}
To elaborate on some of the other answers, this is what tools like Netflix Archaius (https://github.com/Netflix/archaius/wiki) attempt to solve (Dynamic Context Configurations). As far as I'm aware, the only way to accomplish this would be to refresh the contexts by restarting the application.
I notice that Spring Boot application classes can extend other classes, but that the main(String[] args) methods generally all use SpringApplication.run(Application.class, args). The examples often use different annotations above the Application class definition.
This OP asks for a simple summary of three closely related questions:
1.) What are the possible classes that a Spring Boot Application.java class can extend?
2.) What are the intended uses of each of the extension options?
3.) And does the choice of a given extension also dictate specific annotations that must be added to the class definition?
From my research, I have identified the following three extension options:
1.) Extend nothing at all, as per this example:
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2.) Extend WebMvcConfigurerAdapter, as per this example:
#SpringBootApplication
#Controller
public class UiApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(UiApplication.class, args);
}
}
3.) Extend SpringBootServletInitializer, as per this example:
#Configuration
#EnableAutoConfiguration
#EnableScheduling
#ComponentScan
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String... args) {
System.setProperty("spring.profiles.default", System.getProperty("spring.profiles.default", "dev"));
final ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
}
}
Notice that I kept the annotations and minimal other stuff from the examples. This OP asks simply if specific annotation choices or minimal other stuff are dictated by the choice of extension.
Another one, which is not inheritance but it's composition, is to implement the CommandLineRunner interface so that you can perform some operations when the Spring Boot application starts up, like so:
#SpringBootApplication
public class DevopsbuddyApplication implements CommandLineRunner {
/** The application logger */
private static final Logger LOG = LoggerFactory.getLogger(DevopsbuddyApplication.class);
#Autowired
private UserService userService;
#Value("${webmaster.username}")
private String webmasterUsername;
#Value("${webmaster.password}")
private String webmasterPassword;
#Value("${webmaster.email}")
private String webmasterEmail;
public static void main(String[] args) {
SpringApplication.run(DevopsbuddyApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
User user = UserUtils.createBasicUser(webmasterUsername, webmasterEmail);
user.setPassword(webmasterPassword);
Set<UserRole> userRoles = new HashSet<>();
userRoles.add(new UserRole(user, new Role(RolesEnum.ADMIN)));
LOG.debug("Creating user with username {}", user.getUsername());
userService.createUser(user, PlansEnum.PRO, userRoles);
LOG.info("User {} created", user.getUsername());
}
}
Not sure if this is what you're looking for though.