How to inject user_provided vcap_services in spring boot - spring

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
}
}

Related

Why setters are mandatory for fields in a class which reads properties from application.yml file in springboot?

Following is my code:
Why setter is mandatory. Without it, the class does not
read the property from the
application.yml file
correctly.
Thank you.
#Getter
#Setter
#NoArgsConstructor
#Configuration
#ConfigurationProperties(prefix = "test")
#EnableConfigurationProperties
public class KafkaTopicConfig {
private String bootstrapAddress;
#Value(value = "${test.bootstrapAddress}")
private String bootstrapAddressFromVariable;
should only use #Value in encapsulated components/services (we can call them configuration services).
This way, we will have all our configurations in one place, and that component will only have the responsibility of loading and providing them to other components.
https://stackabuse.com/the-value-annotation-in-spring
From baeldung.com... The Spring framework uses standard Java bean setters, so we must declare setters for each of the properties.
So it looks like you're using Lombok so I would make my class look more like this:
#ConfigurationProperties(prefix = "test")
#Data
public class KafkaTopicConfig {
private String bootstrapAddress;
}
Then in the main spring boot application class or a #Configuration class I would do:
#Configuration
#EnableConfigurationProperties({KafkaTopicConfig.class})
public MyApplicationConfig{
}
Then to use my configuration properties I would autowire it into the #Component where I wished to use it.
e.g.
#Component
public MyComponent{
private final KafkaTopicConfig config;
public MyComponent(KafkaTopicConfig config) {
this.config = config;
}
public void doStuff() {
if ("some address".equals(config.getBootstrapAddress())) {
blah();
}
}
}
Using the #Value inside the configuration properties feels confusing to me, and defeats the point of using configuration properties in the first place.

#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 Use Custom Properties Service

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

Fetching global values from database on application startup in Spring boot

I'm writing a Spring Boot / JPA application. I have some values which needs to be visible to the entire application and these values are located in a database. Where should I fetch these values? Should I fetch them in the class containing #SpringBootApplication?
And how do I make it visible to the application? I read that with Spring, we can use a #Bean class to hold global variables. Then do I have to map my #Entity class with a Bean class and autowire the Bean class where ever I want? I'm new to Spring / JPA, so I apologize if the question is basic.
Thanks.
Make a bean that is instantiated with your applicationContext, and use the init-method to run some code after it's instantiated.
A very off the top of my head solution:
In applicationContext.xml:
<bean class="com.example.DbConfigLoader" init-method="init">
A class to load a config entity at startup:
public class DbConfigLoader {
#Autowired
private DbConfigRepository repository;
private DbConfig dbConfig;
public void init(){
dbConfig = repository.findOne(1L);
}
public DbConfig getDbConfig() {
return dbConfig;
}
}
A class representing your config:
#Entity
public class DbConfig {
#Id
private Long id;
private String someSetting;
public String getSomeSetting() {
return someSetting;
}
}
A Spring Data repository for easy database access:
public interface DbConfigRepository extends JpaRepository<DbConfig, Long> {
}

Correct scope for spring beans on Rest Service

I'm creating a REST service using RestEasy and Spring 4.
The service is basically an endpoint for a complex batch process. So clients call the service passing a bunch of parameters and then the processing is triggered.
As there are many parameters that are initially passed to the service, and those parameters are used pretty much everywhere in the system, I've chosen to create a 'helper' bean that will hold the parameters, then every other bean can autowire the 'parameter bean' and use it.
example:
the url called by the client would be: http://localhost/rest/service/execute?processType=A&initialDate=20141220&finalDate=20141231......
The REST Service endpoint would be something like:
#Path("/service")
public class RESTService {
#Autowired
private RequestParams params;
#Autowired
private ProcessOrchestrator orchestrator;
#POST
#Path("/execute")
#Produces(MediaType.TEXT_PLAIN)
public Response executa(
#NotNull #QueryParam("processType") String processType,
#NotNull #QueryParam("initialDate") String initialDate,
#NotNull #QueryParam("finalDate") String finalDate,
...
) {
params.setProcessType(processType);
params.setInitialDate(initialDate);
params.setFinalDate(finalDate);
orchestrator.triggerBatchProcess();
}
}
The RequestParams bean will only hold the parameters values:
#Component
public class RESTService {
private String processType;
private String initialDate;
private String finalDate;
...
// getters and setters
}
And the other beans would #Autowire the params bean and use its parameters:
#Component
public class DataProcessor {
#Autowire
private RequestParams params;
//...
}
#Component
public class DataConverter {
#Autowire
private RequestParams params;
//...
}
#Component
public class FileWritter {
#Autowire
private RequestParams params;
//...
}
The design looks correct, right? Now, my concern is: how do I make sure that a new RequestParams instance is created every time the service is called? Do I need to declare a scope ("request" for instance) for all my beans?

Resources