How to use system property variable in log4j2.xml in spring boot using lombok log? - spring-boot

I am having a CommandLineRunner Spring Boot applicatio nwith Sytem property log_prefix.
I am currently using a log24j.xml for setting the log configurations. It is taking the filename etc from the <properites> tag in the log24j.xml. Is there a way to change the log fileName to log_prefix_LogFileName ?
My Application.class
#SpringBootApplication
public class Application implements CommandLineRunner {
static Logger log = Logger.getLogger(Application.class.getName());
public static void main(String[] args) {
System.setProperty("log_prefix",args[0]);// Tried hardcoding a string value
SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.run(args);
}
I tried setting runID in Application.class and using ${log_prefix} in log42j.xml but not working.
Pom.xml log4j2 dependency.
<log4j2.version>2.15.0</log4j2.version>
I am using #Slf4j lombok annotaion over the class
import lombok.extern.slf4j.Slf4j;
#Slf4j

As Piotr P Karwaz pointed out my log config file had ${log_prefix} , to get system properties in spring boot log configuration log4j2.xml file we need to prefix sys: the property name in curly braces. ${sys:log_prefix} fixed the issue.
note this is specific to Spring boot, for normal java application you can refer this answer

Related

SpringBoot does not resolve #Value properties without PropertySource annotation

I have a bunch of #Value annotated fields in a SpringBoot configuration file, with the matching values in the standard application.properties . If I don't annotate the configuration file with #PropertySource("classpath:application.properties") it will just copy the "${prop1}" string into the actual variable.
I tried adding #EnableAutoConfiguration to the #Configuration class (instead of the PropertySource annotation), but all it does is to break when a requested property is not found.
SpringBoot is supposed to resolve the properties automatically from the standard application.properties file, why this behaviour? Using version 2.2.2.RELEASE
Update:
The answers are correct, the reason it was not working was that I was calling these properties in a test. Annotating the test with #SpringBootTest fixes the issue. In fact when the application is running it is #SpringBootApplication that does the magic
As you can read in this article (chapter 5), SpringBoot manage automatically the application.properties file.
I don't know if this is your problem because I've not seen the code, but in Spring Boot the Application class should be annotated with #SpringBootApplication.
#SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Take a look at this starting example.
You can then inject the value for example in a controller class in this way:
#RestController
public class HelloController {
#Value("${test}")
private String test;
#RequestMapping("/test")
String hello() {
return test;
}
}

application.properties not read with #EnableAutoConfiguration and custom spring boot starter

I try to create a simple custom spring boot starter that read property in application.properties :
#EnableConfigurationProperties({ CustomStarterProperties.class })
#Configuration
public class CustomStarterAutoConfiguration {
#Autowired
private CustomStarterProperties properties;
#Bean
public String customStarterMessage() {
return properties.getMessage();
}
}
with its ConfigurationProperties :
#ConfigurationProperties(prefix = "custom.starter")
public class CustomStarterProperties {
private String message;
/* getter and setter */
...
}
There is also the corresponding application.properties and META-INF/spring.factories to enable the autoconfiguration.
I have another project that declares this starter as a dependency and in which I write a test to see if the customStarterMessage Bean is created :
#RunWith(SpringRunner.class)
#EnableAutoConfiguration
public class TotoTest {
#Autowired
String customStarterMessage;
#Test
public void loadContext() {
assertThat(customStarterMessage).isNotNull();
}
}
This test fails (even with the appropriate application.properties file in the project) because the application.properties seems to not be read.
It works well with a #SpringBootTest annotation instead of the #EnableAutoConfiguration but I would like to understand why EnableAutoConfiguration is not using my application.properties file whereas from my understanding all the Spring AutoConfiguration are based on properties.
Thanks
#EnableAutoConfiguration on test classes don't prepare required test context for you.
Whereas #SpringBootTest does default test context setup for you based on default specification like scanning from root package, loading from default resources. To load from custom packages which are not part of root package hierarchy, loading from custom resource directories you have define that even in test context configuration. All your configurations will be automatically done in your actual starter project based on #EnableAutoConfiguration you defined.

Spring boot #ConfigurationProperties not working

I'm using #ConfigurationProperties for auto configuration of properties. My code is working in IDE. But when I run the jar in command line, it is not working.
Configuration class:
#Configuration
#ConfigurationProperties(prefix="location")
public class Location {
private String base;
public String getBase() {
return base;
}
public void setBase(String base) {
this.base = base;
}
}
Main class:
#SpringBootApplication
#EnableConfigurationProperties(Location.class)
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
application.yml:
location:
base: c:\test
If I autowire Location class, I see an instance created. But there is not property set. The code is not entering setBase() method.
The application prints this in the console.
AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject'
annotation found and supported for autowiring
Make sure that application.yml file is in the root of your classpath, usually it's put in the resources folder.
The fact that the setBase() method is not called suggests that your application.yml file is not being found. Spring looks in the root of your classpath for the application.yml file.
The comment from M. Deinum is correct saying that your duplicated annotations will result in 2 spring beans for Location class. However, as you say you managed to autowire the bean without getting an error it suggests that your Location class isn't in a package that is found by spring when it's scanning for beans. If there were 2 beans then you'd get an error when you autowired it. By default spring will scan use the package where the #SpringBootApplication is as the base. It will then look in this package and all sub packages.
If your package structure is like this...
myapp.main
Application.java
myapp.config
Location.java
Then you need to add scanBasePackages="myapp" to the #SpringBootApplication annotation.
Also change your main class and remove the #Enable.. annotations. i.e.:
#SpringBootApplication(scanBasePackages="myapp")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
As nothing worked with yaml, I had to change to property file and use
#PropertySource({"classpath:application.properties"})
for the spring to identify the properties file

Spring does not load data beans (#Repository) from dependency [duplicate]

I have a myapp parent pom type maven project with myapp-core and myapp-web modules. myapp-core module is added as dependency to myapp-web.
All the classes in myapp-core module reside in root package com.myapp.core and all classes in myapp-web module reside in root package com.myapp.web
The main Application.java is also in com.myapp.web package. As my core module root package is different I am including common base package "com.myapp" for ComponentScan as follows:
#Configuration
#ComponentScan(basePackages="com.myapp")
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Now the surprising thing is if I run this app using Run As -> Spring Boot App it is working fine. But if I run it as Run As -> Java Application it is failing with error saying it can't found beans defined in myapp-core module.
If I move my Application.java to com.myapp package it is working fine.
It should work even if i run it as Java Application also, right?
After enabling debug log level for spring and going through extensive logs I found that scanning for various components like JPA Repositories, JPA Entities etc are depending on the Application.java's package name.
If the JPA Repositories or Entities are not in sub packages of Application.java's package then we need to specify them explicitly as follows:
#Configuration
#ComponentScan(basePackages="com.sivalabs.jcart")
#EnableAutoConfiguration
#EnableJpaRepositories(basePackages="com.sivalabs.jcart")
#EntityScan(basePackages="com.sivalabs.jcart")
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
With the above additional #EnableJpaRepositories, #EntityScan I am able to run it using Run As -> Java Application.
But still not sure how it is working fine when Run As -> Spring Boot App!!
Anyway I think it is better to move my Application.java to com.myapp package rather than fighting with SpringBoot!
I have the same problem. Only adding the #EnableJpaRepositories annotation can solve the issue. I tried to define basePackages in #SpringBootApplication, to no avail.
I think the package of the Application class is fed to the scanning process of JpaRepositories, but other packages defined in #SpringBootApplication are ignored.
It looks like a bug/improvement of Spring Boot.
I had a similar issue with Redis repositories that was fixed in a similar way:
#Configuration
#EnableConfigurationProperties({RedisProperties.class})
#RequiredArgsConstructor
#EnableRedisRepositories(basePackages = {"com.example.another"})
public class RedisConfig {
private final RedisConnectionFactory redisConnectionFactory;
#Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
template.setConnectionFactory(redisConnectionFactory);
template.afterPropertiesSet();
return template;
}
}

Logging using spring boot sl4j

In my application properties i have written the below for logging
logging.level.com.intro.dmp=INFO
logging.level.org.springframework.web=ERROR
logging.level.com.intro.dmp=ERROR
logging.file=application.log
and my Application is below , but it is not creating any log file rather displaying in the console . What is that i am missing here , it is reading application properties
#SpringBootApplication(scanBasePackages = "com.intro")
#PropertySource("file:src/main/resources/application.properties")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
logger.debug("--Application Started--");
logger.error("Check the main Articles");
logger.info("Checking files ");
}
}
Two changes will resolve your issue:
In application.properties file, you need to provide quotes to the file name. i.e.:logging.file='application.log'
You can remove #PropertySource annotation. Spring Boot will, by default, look for application.properties file at src/main/resources/.

Resources