get name of the file loaded by #PropertySource - java

Is there anyway I can know in my program, the full path of file loaded through #PropertySource annotation of Spring.
I need it to show in logs so that one can know which property file is being used in the application

This information is logged already by StandardServletEnvironment. You can set log level to DEBUG for org.springframework.web.context.support.StandardServletEnvironment class to show details in your logs.
If you use spring-boot you can simply add following line into your application.properties file.
logging.level.org.springframework.web.context.support.StandardServletEnvironment = DEBUG

Below seems to be working, though I am not sure if the instance is always of type ConfigurableEnvironment
#Component
public class MyListener implements ApplicationListener<ContextRefreshedEvent>{
#Autowired
private Environment env;
private static final Logger log = LoggerFactory.getLogger(MyListener.class);
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if(env instanceof ConfigurableEnvironment){
MutablePropertySources propertySources = ((ConfigurableEnvironment)env).getPropertySources();
for(PropertySource ps : propertySources){
log.info(ps.getName()); //if only file based needed then check if instanceof ResourcePropertySource
}
}
}
}
Edit: don't really need all this. As already answered by Selim, enabling the proper logs does the trick
log4j.logger.org.springframework.core.env.MutablePropertySources=DEBUG

in current ('21) versions of Spring Boot, neither of the two above suggestions for the logging level seem to work. moreover - if the file is actually NOT loaded, because it is NOT found or for whatever other reason, nothing is printed anyway.
at the moment when i have my ROOT logger set to DEBUG (logging.level.root=DEBUG in application.properties), the only thing I see in the log file, when the file is loaded correctly and the #Value annotated property is resolved successfully is:
2021-07-23 11:06:10.299 DEBUG 16776 --- [ restartedMain]
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of
singleton bean 'bahblahService'
2021-07-23 11:06:10.302 DEBUG 16776 --- [ restartedMain]
o.s.c.e.PropertySourcesPropertyResolver : Found key
'blahblah.username' in PropertySource 'class path
resource [custom-local.properties]' with value of type String

Related

Micronaut context configuration for test

I'm trying to write a basic controller test in a micronaut (3.2.7) application. When I run it, it fails to start as it wants to create DB related beans too. micronaut-hibernate-jpa, flyway, etc. are in the pom.xml.
Can I configure the context somehow so it doesn't pick up hikaripool,flyway, and jpa realted beans?
11:46:23.820 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [test]
11:46:24.112 [main] WARN i.m.c.h.j.JpaConfiguration$EntityScanConfiguration - Runtime classpath scanning is no longer supported. Use #Introspected to declare the packages you want to index at build time. Example #Introspected(packages="foo.bar", includedAnnotations=Entity.class)
11:46:24.133 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
11:46:25.197 [main] ERROR com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Exception during pool initialization.
org.postgresql.util.PSQLException: FATAL: password authentication failed for user "postgres"
The code:
class HelloTest {
private static EmbeddedServer server;
private static HttpClient client;
#BeforeAll
public static void setupServer() {
server = ApplicationContext.run(EmbeddedServer.class);
client = server
.getApplicationContext()
.createBean(HttpClient.class, server.getURL());
}
#AfterAll
public static void stopServer() {
if (server != null) {
server.stop();
}
if (client != null) {
client.stop();
}
}
#Test
void testHelloWorldResponse() {
...
}
}
I tried to exclude configurations like this, but with no luck:
server = ApplicationContext.builder("test")
.exclude("io.micronaut.configuration.hibernate.jpa","io.micronaut.configuration.jdbc.hikari")
.run(EmbeddedServer.class);
Note: If I remove everything from application.yml then the test works. It looks like that in tests the default properties are resolved which turns on jpa,metrics, etc. So I guess the test needs to ignore the default settings too somehow.
You can override all of your (default) application.yml with (test-)environment specific property files: https://docs.micronaut.io/latest/guide/index.html#_included_propertysource_loaders
So you can just provide a dedicated application-mycustomtest.yml as part of your test resources, in which you override all default settings.
Then you can specify as part of the test, which environments shall be active:
#MicronautTest(environments={"mycustomtest"})
Asked the micronaut team on gitter and currenlty the only option is not having a default configuration and having multiple configuration files for controller, repo and e2e testing.

Serving static files with spaces in file names with Spring Boot

I've found a very strange behavior in Spring Boot when trying to serve static files with spaces (or any other special chars, like accents) in file names.
I'm using Spring Boot 2.6.1 with Spring Web MVC and the following customization:
#Configuration
public class MyConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/repo/**")
.addResourceLocations("file:///srv/intranet/repo/");
}
}
I have two files under /srv/intranet/repo, named foo.txt and foo bar.txt (note the space in the second file name).
When I start my application, I can access the first file at http://localhost:8080/repo/foo.txt. But I cannot access the second file (the one with the space in the file name) at http://localhost:8080/repo/foo%20bar.txt (I get a 404 error).
BUT if I put the file foo bar.txt under src/main/resources/static, then I can acces the file at http://localhost:8080/foo%20bar.txt.
I'm aware that Spring Boot configures several directories by default to serve static content (one of them being classpath:/static/), so I'm wondering: what is the difference between the preconfigured directories and the one I'm adding in my #Configuration class via addResourceHandler().addResourceLocations()? Am I missing some details when adding the new resourceHandler?
WORKAROUND
You can set the following property in your application.properties (or equivalent .yml) to get the old behavior in Spring Boot (pre-v2.6.0):
spring.mvc.pathmatch.matching-strategy=ant-path-matcher
UPDATE
I believe this is probably a bug in PathPattern, which replaces AntPathMatcher, and was introduced in Spring Framework 5.3 and adopted in Spring Boot 2.6.0. I submitted a bug report.
UPDATE (2022-06-04)
The bug has been fixed. The fix will be included in Spring Framework 5.3.21.
I have found a workaround for this issue.
Just add the following in your Spring Boot configuration file application.properties:
spring.mvc.pathmatch.matching-strategy=ant-path-matcher
The documentation for this property states that ant-path-matcher is the default value, but it is not. The source code shows that the default value is path-pattern-parser. I submitted an issue.
I have following configuration with Spring Boot 2.6.1 and it successfully loads file with a space in name.
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.example.sw" })
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/files/**").addResourceLocations("file:D:/img/");
}
}
I have an image with name "SO 1.png" (note the space). When hitting the application I get the image
You can probably troubleshoot by putting Spring web on TRACE level where it emits below information while serving the file.
logging.level.org.springframework.web.servlet=TRACE
Below are the logs
2021-12-07 14:24:24.544 TRACE 17200 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/files/SO%201.png", parameters={}, headers={masked} in DispatcherServlet 'dispatcherServlet'
2021-12-07 14:24:24.568 TRACE 17200 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to HandlerExecutionChain with [ResourceHttpRequestHandler [URL [file:D:/img/]]] and 3 interceptors
2021-12-07 14:24:24.580 TRACE 17200 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : Applying default cacheSeconds=-1
2021-12-07 14:24:24.626 TRACE 17200 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : No view rendering, null ModelAndView returned.
2021-12-07 14:24:24.626 DEBUG 17200 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 200 OK, headers={masked}
in Spring 5 a new PathPatternParser was introduced
try replacing
registry.addResourceHandler("/files/**")
with:
registry.addResourceHandler("/files/{*path}")

Spring Boot getting invalid property value with #Value for userName

Why Spring Boot giving me wrong property value when i use this code
#Component
public class MyComponent implements ApplicationListener<ContextRefreshedEvent> {
#Value("${userName}")
private String user;
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("===================: "+user);
}
}
application.properties
userName=admin
It is not printing 'admin', it is printing my windows user name.
From Spring boot documentation :
Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Properties are considered in the following order:
1- Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).
[...]
10- OS environment variables.
[...]
14- Application properties outside of your packaged jar (application.properties and YAML variants).
As you can see, your OS env variable take precedence over variables defined in application.properties which is very useful when you want to override them.
You should consider renaming your variable so that it does not conflicts with windows' environment variable names.

Spring boot with profiles: javax.sql.DataSource' that could not be found

I have application.properties in resource dir
server.port = 8888
Pool bean
#Bean
#Profile("local")
protected DataSource dataSource(#Value("${db.driver}") String driver,...) {
HikariConfig configuration = new HikariConfig();//........
return new HikariDataSource(configuration);
}
Config
#EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class,
DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
Skipped other my configs, because all works without profile annotation.
App runs with
-Dspring.profiles.active=local
How to fix this?
based on information provided, you its not able to create the DataSource bean for which 'db.driver' value is required. This property needs to be mentioned in application properties. Try adding this property in propertySource.
or you provide some default value for this property, something like this:
#Value("${db.driver:'defaultValue'}"
if error still exists, pls add stack trace and code-snippet for info to determine whats going on.

Spring Boot - #Value("${my.property}") gets resolved to String ${my.property} if missing instead of initialization exception

I have a Spring Boot project which loads it's custom properties from src/main/application.yml. There it has a property:
my:
property: some-value
In my Java code I bind it like that:
#Configuration
public class SomeConfiguration {
private static final Logger logger = ...
#Value("${my.property}")
private String myProperty;
#Bean
public MyBean someBeanThatUsesMyProperty() {
logger.debug("Initializing MyBean with myProperty: {}", myProperty);
// Actual initialization logic
}
}
And everything works fine until the property is present. But if the property is not present I would expect the application start up to fail with some kind of initialization exception, but that's not what actually happens. What actually happens is that if the property is missing then my instance variable private String myProperty gets resolved to a String literal ${my.property}.
Can anyone explain why this happens and how can I make the property be required and application start up fail, if it is missing?
P.S Interesting is that lot's of people in the internet seem to be having problem making the #Value annotated fields not mandatory and they can get their desired behaviour with #ProperySource(ignoreResourceNotFound = true) but for me it's the other way around. I tried playing with ignoreResourceNotFound also, but it acts the same no matter if it's false or true.

Categories

Resources