Spring boot - logging to file using #PropertySource not working - java

I have a spring boot library module and I want to enable logging into a file.
What I did was to add logging settings in module-conf.properties, but no file is created.
module-conf.properties
logging.file.name=test.log
I also created a configuration bean:
#Configuration
#ComponentScan("...")
#EnableJpaRepositories("...")
#PropertySource("classpath:module-conf.properties")
public class ModuleConfiguration {
#Autowired
private Environment environment;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl(environment.getProperty("spring.datasource.url"));
dataSource.setUsername(environment.getProperty("spring.datasource.username"));
dataSource.setPassword(environment.getProperty("spring.datasource.password"));
return dataSource;
}
Do I have to configure the logging system the same way I configure the datasource ?
Is there a way avoid manual configuration?

This is interesting!
It appears logging is initialized before the ApplicationContext is created.... and the #PropertySources is read after ApplicationContext is created. As per the documentation, you can override the config by updating one of the config file based on your logging system(Spring's default is logback)
Reference: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-custom-log-configuration
Problem:
Since logging is initialized before the ApplicationContext is created,
it is not possible to control logging from #PropertySources in Spring
#Configuration files. The only way to change the logging system or
disable it entirely is via System properties.
The recommendation:
When possible, we recommend that you use the -spring variants for
your logging configuration (for example, logback-spring.xml rather
than logback.xml). If you use standard configuration locations, Spring
cannot completely control log initialization.

Related

Hibernate/Spring framework: path of the database in a configuration file

I am trying to write a simple Hibernate application and I want the SQLite database location to be changed according to an application configuration file.
What I was trying to do was therefore retrieving the path of the database from a text file in the project and putting it inside dbLocation, then running the following piece of code:
Configuration config = new Configuration();
config.setProperty("hibernate.connection.url", "jdbc:sqlite:" + dbLocation);
Is there a better and more "standard" way to do so? I'm using Spring Boot for my application and I just realized there's afile called application.properties. May I use this one maybe? I'm pretty new to both Hibernate and the Spring framework.
In Spring Boot application properties you can externalize your application properties so they are configured/managed outside your application source code.
Once a property is defined in application.properties you can use SpringBoot built-in feature to access the values
#Configuration
public class ApplicationProperty {
#Value("${prop}")
private String prop;
With Spring Boot another way is to use #ConfigurationProperties.
Example from the documentation can be found here
A comparison between #ConfigurationProperties and #Value annotation from the documentation
Feature #ConfigurationProperties #Value
Relaxed binding Yes No
Meta-data support Yes No
SpEL evaluation No Yes

Making explicit calls to the default Spring Cache Manager provided by SpringBoot

I've enabled caching in a SpringBoot application with the #EnableCaching and #Cacheable annotations. The cache properties are defined in the application.yaml file.
spring
cache
type=simple
Now I want to know if there is a way to access explicitly the cacheManager bean defined by Spring Boot(created to support the #EnableCaching annotation) without defining a new CacheManager Bean in the configuration files.
I'm basically trying to autowire the cacheManager bean defined by Spring Boot so that I can make explicit calls to it.
#Autowired
private CacheManager cacheManager;
...
Cache cache = cacheManage.getCache("toto")
Regards
Notes: My IDE is telling me that It can't autowire the cacheManager bean
Finally, the IDE warning was wrong. I was able to autowire the cache manager bean provided by Spring Boot and I was able to call it explicitly.
Regards

How to disabled spring-security by application.properties?

I'd trying to activate basic authentication with password hash encryption.
#Configuration //gets picked up automatically by spring-boot
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(details).passwordEncoder(new BCryptPasswordEncoder());
}
}
I want the authentication only being active in production. So I'm trying to deactivate it in general at first, use:
security.basic.enabled=false
Result: the application is still secured. I'm presented with the username/password screen.
But how could I then disable the need for authentication?
Solved with ConditionalOnProperty:
#Configuration
#ConditionalOnProperty("security.basic.enabled")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
To do different things in different environments you should use Spring Profiles
Suppose you need security configuration bean only in production environment, then you should mark it to be loaded conditionally when a specific profile is enabled.
#Configuration //gets picked up automatically by spring-boot
#Profile("Production")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(details).passwordEncoder(new BCryptPasswordEncoder());
}
}
Profile specific configuration is done in properties files named application-{profile}.properties and bootstrap-{profile}.properties files.
Now since security configuration bean is marked with profile Production it will be loaded only when Production profile is enabled.
To enable a profile you have to set following property.
#One or more profiles can be active simultaneously
spring.profiles.active=Production,Dev,Local
This property can either be edited in the common properties file application.properties (Always loaded unlike profile specific properties files like application-Production.properties which are conditionally loaded) or it can provided as a environment variable as below.
On Windows
set SPRING_PROFILES_ACTIVE=Production
On Unix
export SPRING_PROFILES_ACTIVE=Production
It can be done using a million other ways that spring supports to load properties. For a list of all the methods go through this link https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Finally to disable default Spring security (Basic) Autoconfiguration, you can use following properties.
security.basic.enabled=false
management.security.enabled=false #For actuator
Above should be in the profile specific properties files where you wish to disable Spring Security auto configuration.
To disable spring-security autoconfiguration entirely use the following property
spring.autoconfigure.exclude[0]=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration

Setting up JNDI connection with Spring Boot

I'm trying to set up a JNDI database connection for my WAR file which will be deployed on WebLogic 12c. This is what I have:
#Bean
public DataSource dataSource() throws DataSourceLookupFailureException {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
return dataSourceLookup.getDataSource("jndiName");
}
In the application.properties file:
spring.datasource.jndi-name=jndiName
This is pieced together from two different sections of the Spring Boot guide:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-configure-a-datasource
I am confused, why is jndiName stated twice? Am I following correctly - is this the correct way to set up?
I am of the impression that Spring Boot will either automatically retrieve the JNDI name from application.properties, so that I do not need to hardcode the JNDI name into getDataSource(), or if I hardcode the JNDI name in then I wouldn't need to include that property in application.properties in the first place.
From my interpretation, the two sections of the guide covering how to set up a JNDI connection appear to contradict each other. What am I getting wrong? What exactly is the correct way to set this up?
Remove your custom bean and use application.properties but in local environment if you want to run embedded container this approach won't work
To use H2 or any other database in embedded container define profile in main method and then configure your data source. This way it works both in local and production

Spring Boot with datasource when testing

I am using Spring Boot application and the auto cofiguration is enabled. The main Application file is marked as #EnableAutoConfiguration. The datasource is lookedup from JNDI is configured using java config and the class which create the datasource is marked as #Configuration.
I have a test class as below.
#RunWith( SpringJUnit4ClassRunner.class )
#WebAppConfiguration
#ContextConfiguration( classes = Application.class )
public class TestSomeBusiness {}
The issue is when I run the test case, the datasource jndi lookup happens, which fails because the test case is not running inside a server environment. As far as I know the classes in classpath marked with #Configuration are executed and that the reason the datasource lookup is being called.
The work around for now I have found is instead of JNDI lookup create the datasource using DriverManagerDataSource, so that even if its not a server environment the datasource lookup won't fail.
My questions are:
1) How do we generally deal with datasource (when looking up from JNDI) in
spring boot application for testing ?
2) Is there a way to exclude the datasource configuration class from being called when executing test case ?
3) Should I create an embedded server so that the JNDI lookup can be done when executing test case ?
2) Is there a way to exclude the datasource configuration class from being called when executing test case ?
You can add a application.properties config file into your src/test/resources and spring boot would pick those configurations in test environments. I suppose, you have application.properties in your src/main/resources like this:
spring.datasource.jndi-name=some_jndi
This JNDI resource will be used in your production environment. For your test environment you can use a, say MySQL database, by adding these configurations into your test application.properties:
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
3) Should I create an embedded server so that the JNDI lookup can be
done when executing test case ?
As i said, you can totally bypass the fact that you're using JNDI for production by adding test specific configurations.
1) How do we generally deal with datasource (when looking up from
JNDI) in spring boot application for testing ?
You can mock JNDI resources using facilities available in org.springframework.mock.jndi package. For example by using SimpleNamingContextBuilder you can:
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind("jndi_name", dataSource);
builder.activate();
The other option is, of course, using Non JNDI resources in test environments.

Categories

Resources