Spring Boot Programmatically setting profiles - spring-boot

How to set active profile in spring boot Application. This application will be deployed in stand alone Tomcat.
I have 2 property files application-{profile}.properties.
My Application class
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "dev");
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
if I run the app with embedded tomcat the dev profile is set as active and it works fine. But when I deploy in stand alone tomcat. It does not work.
I tried to set active profile in configure method. but i get null pointer exception, when i get the environment from the context.
Any help on how to set the active profile.

You can set additional profiles on start up:
SpringApplication springApp = new SpringApplication(Main.class);
springApp.setAdditionalProfiles("profile1", "profile2");
springApp.run(args);

I also had the same problem and after struggling for half a day I ended up with this:
#SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "dev");
SpringApplication.run(MyApplication.class, args);
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "dev");
super.onStartup(servletContext);
}
}

Another way of doing it in Spring Boot 2 is by using SpringApplicationBuilder:
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
#SpringBootApplication
public class MySpringProgram {
public static void main(String[] args) {
new SpringApplicationBuilder(MySpringProgram.class)
.profiles("profile1", "profile2")
.run(args);
}
}

Instead of activating the profile dynamically, you can put the profiles as vm-arguments in the catalina.sh
CATALINA_OPTS="-Dspring.profiles.active=dev"

System.setProperty("spring.profiles.active", "dev");

SpringApplication app =new SpringApplication(Application.class);
Properties props = new Properties();
props.put("AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAM", "dev");
app.setDefaultProperties(props);
app.run(args);
I think this code is better solution, because it doesn't set system property

Related

How do I get Environment variables in the main method of a spring boot application? [duplicate]

I am trying to get the value of a property
hello.world=Hello World
in MainApp class
#SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
This didn't work as its the main method.
#Value("${hello.world}")
public static String helloWorld;
Maybe its possible to load by
Properties prop = new Properties();
// load a properties file
prop.load(new FileInputStream(filePath));
Is there any other better way to get the properties using Spring in the main method of SpringBoot before SpringApplication.run
ConfigurableApplicationContext ctx =
SpringApplication.run(MainApp.class, args);
String str = ctx.getEnvironment().getProperty("some.prop");
System.out.println("=>>>> " + str);
You have declared the variable helloWorld as static. Hence you need to use Setter Injection and not Field Injection.
Injecting a static non-final field is a bad practice. Hence Spring doesn't allow it. But you can do a workaround like this.
public static String helloWorld;
#Value("${hello.world}")
public void setHelloWorld(String someStr) {
helloWorld = someStr
}
You can access this variable helloWorld at any point in the class, if its any other class. But if you want to do it in the main class. You can access the variable only after this line
SpringApplication.run(MainApp.class, args);)
i.e only after the application has started.
Don't do this. Its better to use CommandLineRunner.
Thanks to this you can have a non static method that Spring Boot will run for you automatically:
#SpringBootApplication
public class SimulatorApplication implements CommandLineRunner {
#Value("${my-value}")
private myValue;
public static void main(String[] args) {
SpringApplication.run(SimulatorApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
// here you can access my-value
}
}
#SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(MainApp.class);
springApplication.addListeners(new VersionLogger());
springApplication.run(args);
}
// The VersionLogger Class
public class VersionLogger implements ApplicationListener<ApplicationEnvironmentPreparedEvent>{
#Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEvent) {
String helloWorld = applicationEvent.getEnvironment().getProperty("hello.world");
}
}
ApplicationEnvironmentPreparedEvent
Event published when a SpringApplication is starting up and the Environment is first available for inspection and modification.
ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
String applicationPropertyVersion=applicationContext.getEnvironment().getProperty("application.property.version");
LOGGER.info("RELEASE CODE VERSION {} and applicationProperty Version {} ", LcoBuildVersion.version,
applicationPropertyVersion);
We can't read values into static fields . Here is the explanation gives a better insight How to assign a value from application.properties to a static variable?

Before spring boot start read properties file

I have spring boot application, before running the application run method I have to validate the properties file, then only run the application example
Interface ValidateProperties {
public boolean isValid();
}
#SpringBootApplication
public class MyApp {
public static void main(String[] args) throws Exception {
**// what is the best way to call Interface here**
if (i.isValid) {
SpringApplication.run(MyApp.class, args);
}
}
}

In Spring-based web application, where is my console/log output going to?

I'm writing a simple Spring-based web application and deploying it to Websphere Liberty 8.5.5.9; I've gotten past my deployment problems and the application seems to start (according to the Liberty console.log). However, I'm not seeing any console or log output. My application main class, which contains print statements in the main method, is:
#Configuration
public class UserSettingApplication extends SpringBootServletInitializer implements WebApplicationInitializer {
ServletContext servletContext;
private static final LoggerUtils logger = new LoggerUtils( UserSettingApplication.class );
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
builder.sources(UserSettingApplication.class);
return builder;
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.addListener(RequestContextListener.class);
this.servletContext=servletContext;
super.onStartup(servletContext);
}
public static void main(String[] args) throws Exception {
System.out.println( "Entering UserSettingApplication.main" );
SpringApplicationBuilder applicationBuilder = new UserSettingApplication().configure(new SpringApplicationBuilder());
applicationBuilder.run(args);
System.out.println( "Entering UserSettingApplication.main" );
}
#Override
protected WebApplicationContext run(SpringApplication application) {
WebApplicationContext webApplicationContext = super.run(application);
Environment env = webApplicationContext.getEnvironment();
String sessionName = env.getProperty("server.session.cookie.name", "xplore-session-id");
servletContext.getSessionCookieConfig().setName(sessionName);
return webApplicationContext;
}
#Bean
protected RequestContextListener requestContextListener() {
return new RequestContextListener();
}
#Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
logger.info("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
logger.info(beanName);
}
};
}
}
Shouldn't I be seeing the print statements in the main method in the WASLiberty console.log?
Shouldn't I be seeing the print statements in the main method in the WASLiberty console.log?
You will not see any printouts from the main method as it is not executed in the Liberty. The main method is used for standalone apps started from the command line not run from the app server. Put your messages in the configure method like below and you will see it.
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
System.out.println("########################################Starting app");
System.out.println() will NOT write into files such as console.log.
Instead it will write into console such as commandline window or eclipse console.
You need to use loggers such as log4j or Java.util.logging for writing into files.
You can find more info here what-is-the-difference-between-java-logger-and-system-out-println

Spring Boot application to read a value from properties file in main method

I am trying to get the value of a property
hello.world=Hello World
in MainApp class
#SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
This didn't work as its the main method.
#Value("${hello.world}")
public static String helloWorld;
Maybe its possible to load by
Properties prop = new Properties();
// load a properties file
prop.load(new FileInputStream(filePath));
Is there any other better way to get the properties using Spring in the main method of SpringBoot before SpringApplication.run
ConfigurableApplicationContext ctx =
SpringApplication.run(MainApp.class, args);
String str = ctx.getEnvironment().getProperty("some.prop");
System.out.println("=>>>> " + str);
You have declared the variable helloWorld as static. Hence you need to use Setter Injection and not Field Injection.
Injecting a static non-final field is a bad practice. Hence Spring doesn't allow it. But you can do a workaround like this.
public static String helloWorld;
#Value("${hello.world}")
public void setHelloWorld(String someStr) {
helloWorld = someStr
}
You can access this variable helloWorld at any point in the class, if its any other class. But if you want to do it in the main class. You can access the variable only after this line
SpringApplication.run(MainApp.class, args);)
i.e only after the application has started.
Don't do this. Its better to use CommandLineRunner.
Thanks to this you can have a non static method that Spring Boot will run for you automatically:
#SpringBootApplication
public class SimulatorApplication implements CommandLineRunner {
#Value("${my-value}")
private myValue;
public static void main(String[] args) {
SpringApplication.run(SimulatorApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
// here you can access my-value
}
}
#SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(MainApp.class);
springApplication.addListeners(new VersionLogger());
springApplication.run(args);
}
// The VersionLogger Class
public class VersionLogger implements ApplicationListener<ApplicationEnvironmentPreparedEvent>{
#Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEvent) {
String helloWorld = applicationEvent.getEnvironment().getProperty("hello.world");
}
}
ApplicationEnvironmentPreparedEvent
Event published when a SpringApplication is starting up and the Environment is first available for inspection and modification.
ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
String applicationPropertyVersion=applicationContext.getEnvironment().getProperty("application.property.version");
LOGGER.info("RELEASE CODE VERSION {} and applicationProperty Version {} ", LcoBuildVersion.version,
applicationPropertyVersion);
We can't read values into static fields . Here is the explanation gives a better insight How to assign a value from application.properties to a static variable?

Setting Spring #Profile from JNDI for SpringBoot

I'm deploying my SpringBoot Application to a Tomcat 8.5 container.
Similar as described here: http://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html I modified my SpringBootApplication, so it's deployable as war.
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
Similiar to this question Activating Spring #Profile Using JNDI I wan't the application to select the active Profile using an JNDI entry.
I added an EnvironmentApplicationContextInitializer identical to the one shown in the accepted answer.
However: I do not use any web.xml. So the profile is not being picked up and used.
How do I make the SpringBootApplication using the EnvironmentApplicationContextInitializer?
Thanks to M Deinum's comment I found a solution:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
// this would be used if run via java -jar service.war
// SpringApplication app = new SpringApplication(Application.class);
// CustomApplicationContextInitializer initializer = new CustomApplicationContextInitializer();
// app.addInitializers(initializer);
// app.run(args);
SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
// this will be used within an app container
CustomApplicationContextInitializer initializer = new CustomApplicationContextInitializer();
return builder.initializers(initializer).sources(Application.class);
}
}
Note the builder.initializers(initializer) part.

Resources