Spring Boot Use Custom Properties Service - spring

I am working on a legacy project that has its own PropertyService class that manages the reloadable properties and so on.
The thing works pretty much OK, but the problem is now I have this property service, for my project, and an application.yml for the spring boot related properties.
The question is: is there a way to tell spring boot to load properties from something like a properties provider - a custom class or an adapter of sort ?
In this way I could manage my properties only through the existing module
Thank you for your help !

Try #ConfigurationProperties to customize the properties loading (see the example)
The code example
#Configuration
#ConfigurationProperties(locations = "classpath:mail.properties", prefix = "mail")
public class MailConfiguration {
public static class Smtp {
private boolean auth;
private boolean starttlsEnable;
// ... getters and setters
}
#NotBlank
private String host;
private int port;
private String from;
private String username;
private String password;
#NotNull
private Smtp smtp;
// ... getters and setters
#Bean
public JavaMailSender javaMailSender() {
// omitted for readability
}
}
So you define a bean which in fact returns properties

Related

Spring Boot #ConfigurationProperties, skip #Configuration if not valid

In a Spring Boot 1.5.13 project, I have a #Configuration object with some #NotEmpty fields:
#Configuration
#Validated
public class Test {
#NotEmpty
private String name;
private String optionalOne;
private String optionalTwo;
#NotEmpty
private String location;
...
}
And a #ConfigurationProperties class that loads it from application.yml:
#ConfigurationProperties(prefix="test.config")
public class TestConfig {
#Valid
Map<String, Test> testRecords = new HashMap<>();
...
}
There are several "Test" records in the configuration files.
Default behavior from spring is that if validation fails, like if one of the records has a missing location, then an error prevents the app from starting up.
I would instead like the behavior to be that the invalid record is logged and skipped, so that the app continues startup, loading only the valid records, and loading no records that are missing the #NotEmpty fields.
How can I accomplish this?
I would suggest you to implement the validation yourself without any annotations. After the beans are constructed check the constraints programatically (maybe in a #PostConstruct method) to avoid fighting with Spring.

spring boot 2: load application.properties manually

is it possible to access application.properties values while creating datasource in SpringApplication.run?
I have tried to inject value with #Value but when i need the values, the bean with #ConfigurationProperties is not created yet.
if you are referring to data source url,username and password you can use these keys :
spring.datasource.url=your_database_url_and_port_number
spring.datasource.username=your_database_username
spring.datasource.password=your_username_passsword
You need to add #EnableConfigurationProperties annotation mentioning the properties POJO name.
#SpringBootApplication
#EnableConfigurationProperties(ConfigProperties.class)
Then in the ConfigProperties class you need to add the below annotation.Prefix is what you will set in the properties file.
#ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private String from;
// standard getters and setters
}
Values in properties file.
#Simple properties
mail.hostname=host#mail.com
mail.port=9000
mail.from=mailer#mail.com

#CreatedBy becomes null when updating

I have this entity:
#Entity
#EntityListeners( AuditingEntityListener.class )
public class Employee {
#Id
#GeneratedValue
int id;
private String name;
...
#LastModifiedBy
private String modifiedBy;
#CreatedBy
private String createdBy;
}
And i have this config class:
#Configuration
#EnableJpaAuditing
public class DataConfig {
#Bean
public AuditorAware<String> auditorAware() {
return () ->
SecurityContextHolder.getContext().getAuthentication().getName();
}
}
The problem is:
When updating entity, the created_by becomes null.
Any help please.
I'd suggest to you to ensure if your spring boot app is scanning the DataConfig class.
In addition, well in case of having a REST Service (I don't know because that info is not added to the question) but bear in mind a REST Service is Stateless, and you need fetch the Authorization from the request to add it to the spring security context BEFORE executing the request.
But if your spring boot app is just a Spring MVC one with basic Authorization, be sure you have an open session once the data is updated/created

Spring Boot ConfigurationProperties issues

I have been having issues getting my properties to load in a spring boot app. I made a very simple version and it still fails. I have been going over other questions from the site and just have not been able to figure it out.
application.properties is in main/java/resources
rim.dbuser=RIM_API_USER
rim.dbpassword=rimpassword
rim.dbconnection=jdbc:oracle:thin:#kuga.myrim.com:1515:dev179
rim.dbdriver=oracle.jdbc.driver.OracleDriver
A simple class for the properties
#ConfigurationProperties(prefix = "rim")
public class RIMProperties {
private String driver;
private String dbURL;
private String user;
private String password;
<getters and setters>
My object using the RIMproperties
#Component
public class RIMObject {
#Autowired
private RIMProperties rimProperties;
public void print(){
System.out.println("dbuser = "+rimProperties.getUser());
System.out.println("password = "+rimProperties.getPassword());
System.out.println("driver = "+ rimProperties.getDriver());
System.out.println("DBURL = "+rimProperties.getDbURL());
}
}
and my app class
#SpringBootApplication
#EnableConfigurationProperties(RIMProperties.class)
public class App {
public static void main(String[] args)
{
ApplicationContext context = SpringApplication.run(App.class, args);
RIMObject rimObject = context.getBean(RIMObject.class);
rimObject.print();
RIMProperties prop = context.getBean(RIMProperties.class);
System.out.println(prop.getDriver());
System.out.println(prop.getDbURL());
}
}
I get nulls on everything. Not sure why it is not picking up the properties.
I think the problem is with your variable names, change them to match your props file.
private String driver; to private String dbdriver;
you get the idea...
I assume, you have posted correct code.
As mentioned in some other answer looks like your java field names differ to the properties fields.
For more info take a look at https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties
Spring Boot Autoconfiguration
Moreover, as you are using spring-boot, is there a reason you are not using spring-boot's out of the box auto configuration feature?
In you example you are mapping datasource properties in your java class.
You just need to use spring-boot's standard datasource fields in properties and it will automatically create a DataSource and even JdbcTemplate instance which you can simply autowire anywhere in your app.
Please have a look for more https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-connect-to-production-database

How to inject user_provided vcap_services in spring boot

I’m developing an application in spring boot and deploying in PCF (Pivotal Cloud Foundry).
I’ve created 3 “user-provided” services and I would like to inject them in my code using #ConfigurationProperties into a class. I’ve been looking around but the only example I found is injecting a service into a class and I need to inject a list of services.
I’ve tried with #ConfigurationProperties(vcap.services) but it is not working. The class mapped is null. Can you please help me to understand how the CUPS can be injected in spring boot? Thanks in advance
When you create a user provided service in the following way
cf cups ups-example1 -p '{"user":"user1", "password":"password1"}'
and bind that to your application, the information provided in the user provided service gets mapped into your VCAP_SERVICES environment variable.
It should look something like
{
"user-provided": [
{
"credentials": {
"password": "password1",
"user": "user1"
},
"label": "user-provided",
"name": "ups-example1"
}
]
}
With the help of Springs CloudFoundryVcapEnvironmentPostProcessor it gets mapped into an environment property which can be accessed by vcap.services.ups-example1.credentials.
To map these properties into a Java object you can use #ConfigurationProperties
#Configuration
#ConfigurationProperties("vcap.services.ups-example1.credentials")
public class UserProvidedServiceOneProperties {
private String user;
private String password;
// getters & setters
}
If you want to map multiple user provided services into one object you could use inner classes for that use case
#Configuration
public class UserProvidedServicesProperties {
#Autowired
private UserProvidedServiceOneProperties userProvidedService1;
#Autowired
private UserProvidedServiceTwoProperties userProvidedService2;
// getters & setters
#Configuration
#ConfigurationProperties("vcap.services.ups-example1.credentials")
public static class UserProvidedServiceOneProperties {
private String user;
private String password;
// getters & setters
}
#Configuration
#ConfigurationProperties("vcap.services.ups-example2.credentials")
public static class UserProvidedServiceTwoProperties {
private String user;
private String secret;
private String url;
// getters & setters
}
}

Resources