Retrive value from yaml file to field in external library - java

I have a Spring Boot application
I have a external library (written by me, also using Spring parent) as dependency
In application.yml (in application, not in library) I have property example
In library, I have a class with code like this:
#Value("${example}")
private String example;
The value for this field is null, but when I'm calling for Environmet this value is accessible.
Any hint what should I do to get value by using #Value?

May be you forget add #Component annotation your class

Related

EnvironmentPostProcessor and ConnectionProperties priorities

I use this library to replace links to AWS parameters to they actual values: https://github.com/NitorCreations/spring-property-aws-ssm-resolver/blob/master/src/main/java/com/nitorcreations/spring/aws/SpringPropertySSMParameterResolver.java
This library uses EnvironmentPostProcessor to substitude parameters. Next, I use the following component to get properties:
#Data
#Component
#ConfigurationProperties(prefix = "activemq.connection")
public class ConnectionProperties {}
This library replaces all spring properties except #ConfigurationProperties and I can't understand why. Is there any priority for processing these beans?
UPD: From the library description:
spring-property-aws-ssm-resolver is a small Spring Boot plugin for resolving AWS SSM Parameters during startup simply by using prefixed regular Spring Boot properties.
Set up your Spring Properties with the {ssmParameter} prefix.
Example application.yml:
my.regular.property: 'Foo'
my.secret.property: '{ssmParameter}/myproject/myapp/mysecret'
During startup, the plugin would look for properties with this prefix and replace the value by looking for a property called /myproject/myapp/mysecret on AWS SSM.
I expect this library will replace all values in #ConfigurationProperties on values from AWS SSM, but it actually don't, it leaves them unchanged. I think the reason is in the initialization order of ConfigurationProperties and EnvironmentPostProcessor.

Dynamic JsonProperty using Jackson with Spring Boot

I developped a Spring Boot application. This application can be deployed to a test or prod environment, the application is using REST API for making requests. I use POJOs as wrapper, with the JsonProperty annotations containing the field IDs for the API, that it is being pushed to.
ie
#JsonProperty("field_001)
private String name;
#JsonProperty("field_002)
private String address;
The field labels for these values differ on the test endpoint. So the test endpoint might expect the properties to map as
#JsonProperty("field_005)
private String name;
#JsonProperty("field_006)
private String address;
I would like to be able to utilize the Spring Boot native support for profile based properties files. To read in the JsonProperty annotation values at run time from an external properties file.
So for example,
There might be three files application.properties, application-test.properties and application-prod.properties. Spring Boot could read in the test or prod properties in addition to the vanilla properties file based on the "spring.profiles.active" setting.
...-test.properties would contain the constant values for the test server fields. And ...-prod.properties would contain the constant values for the prod server fields.
Nesting annotations such as Spring's #Value tag, like this:
#JsonProperty(#Value("${property.file.reference.here}))
doesn't seem to work.
Best regards
#JsonProperty(#Value("${property.file.reference.here})) won't work simply because :
#JsonProperty uses a String as value, but #Value is an 'Annotation', so that's not a String value, writing it will give you the following error :
Error:(34, 12) java: annotation not valid for an element of type java.lang.String
Plus, #Value will be loaded "once" when spring context loaded.
Edit
If you wish to use test/dev and prod properties, better create a properties file under your test resources package, they will be loaded automatically. (i'm using it that way).
There is actually another approach, is to modify the annotation value at runtime.

Library (JAR) default value for properties spring

I have an application that need to send emails. I might need later to send emails in a second application so I try to do a library to re-use it.
My application is done with Spring-boot.
My library just include Spring-core, Spring-context and Spring-test.
This is my EmailUtils in my library :
#Named
public class EmailUtils {
#Value("${from}")
private String from;
#Value("${to}")
private String to;
...
}
I would like to have a default file application.properties with that in the library :
from=default-from
to=default-to
now I would like if my application spring boot does something like that :
#Service
public void EmailService {
#Inject
private EmailUtils emailUtils;
...
}
I would like if I don't define a new application.properties in my application to get the default value from the library but would be possible to override them by using an application.properties in my Spring-boot app.
Info : My Spring-boot app have ScanComponent package (just to mention it). But my library has nothing. I don't know if I have to use a beans.xml and define a ContextPlaceHolder ...
I am a little bit loss, maybe there is a better way to do it ?
Thank you.
If I am correctly understanding your question - you want to specify a default value for your #Value annotated properties. You can do this simply by simply using the format #Value("${property_key:default value}") so if you wished the default from value to be me#me.com and to to be you#you.com your code would read:
#Named
public class EmailUtils {
#Value("${from:me#me.com}")
private String from;
#Value("${to:you#you.com}")
private String to;
...
}

Spring: define #RequestMapping value in a properties file

Is it possible to define the value of a #RequestMapping annotation in Spring by defining it in a properties file?
Actually, I do something like:
#Controller
#RequestMapping("/xxx")
public class MyController {
...
}
But I would like to store the path /xxx in a properties file. Why? For instance, it is less likely that I do mystakes in my templates if I rename the path in the controller.
In other framework this is allowed (see Symfony, for instance).
It should be possible to use placeholders in #RequestMapping, like for example #RequestMapping("${foo.bar}"). Take a look at the documentation for more details:
Patterns in #RequestMapping annotations support ${…​} placeholders against local properties and/or system properties and environment variables. This may be useful in cases where the path a controller is mapped to may need to be customized through configuration. For more information on placeholders, see the javadocs of the PropertyPlaceholderConfigurer class.
Thx for the help. It is my contribution...
No dependencies are necessary because maven do everything by itself.
In the property file - use maven interpolation, such as below:
vs= v1
us= users
me= messages
url.user=${vs}/${us}
url.mess=${vs}/${me}
In your destiny file, for example controller/resource (in mycase):
#RestController
//#RequestMapping("v1/users") <<<<<<instead this
#RequestMapping("${url.user}")<<<<<<use this
#Api(value = "API RESTFUL)
public class UserResource {
//
As bohuslav burghardt has mentioned this is totally possible.
So if you have a common domain stored in your application.properties file you can use placeholders to call it in your controller/s and even chain placeholders & text together.
For Example...
In your .properties file
app.domain = mydomain/v1
In the controller
#RestController
#RequestMapping("${app.domain}/my-controller")
public class MyController {

Supply Spring managed objects to non Spring managed Objects?

I have a data structure representing a CSV file containing thousands of config settings. The structure is a Java class file with instance variables to represent the records in the file (ie: a HashMap) and the state of the file (errors, warnings, etc).
These classes are not created by Spring as they have state. I would like the class to access system configuration properties which are currently handled by a Spring managed database DAO class. Usually when classes need this DAO I inject it through Spring using #Autowired. But as my data structure is not managed by Spring, how can the CSV structure class access the DAO?
The only method I can think of is when creating the data structure from the Spring managed bean to just pass in the DAO:
CSVDataStruture c = new CSVDataStruture(dao);
See 6.8.1. Using AspectJ to dependency inject domain objects with Spring about using #Configurable
Another way is to get ahold of the application context (in web applications this is WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)) and get the beans using context.getBean("name"), but it is more of a workaround.
These classes are not created by Spring as they have state.
What makes you think that Spring cannot / should not create objects that have state?
Depending on what you are trying to do (it is hard to figure this out!) I would do one of the following:
Give the CSV class getters and setters for a CVS file parameter and a DAO parameter, and instantiate it using Spring DI. This assumes that the filename is available when Spring wiring occurs.
Create a factory class with a method that instantiates a CSV object from a file parameter. The factory class should have a getter/setter for the DAO object and be instantiated using Spring DI.

Categories