Assign a value to a parameter in application properties before use - spring-boot

I have a property in my application.properties file in a SpringBoot project -
app.module.service.url=http://localhost:8090/{DOCID}
I have injected it into my Java file as below -
#Value("${app.module.service.url}")
private String url;
Now I need to replace DOCID with some value in my function(i.e-dynamic). How do I get to do this or am I completely missing it?
I am aware that we can do this in case of message properties in Spring. But here I have nothing to do with Locales.
Edit:
There is some value which I need to put in place of {DOCID} when using it within my Java implementation.
...
public class Sample{
#Value("${app.module.service.url}")
private String url;
public void sampleFunc(){
String str = "random Value" //some dynamic value goes in here
...
Now I need to replace {DOCID} with str in url

Two way binding is not possible in Spring Properties.It can only read run time and environmental variables.
Please refer following link for more information.
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding

You can use spring UriTemplate for this purpose.
In your implementation class:
...
public class Sample{
#Value("${app.module.service.url}")
private String url;
public void sampleFunc(){
String dockId = someValue; // customize according to your need
UriTemplate uriTemplate = new UriTemplate(url);
URI uri = uriTemplate.expand(docId);
new RestTemplate().postForEntity(uri, requestObhect, Responseclass.class);
}
...
For more information, you can refer :
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/UriTemplate.html

Try like this ...
app.module.service.url=http://localhost:8090/{{docId}}
And set run configuration as below
-DdocId = 133323 // any number which you want

Related

Camel REST DSL set Example Value for Swagger UI

Is it possible and if yes, how to set the Example Value for Swagger UI using Camel REST DSL in Java?
I'm running Swagger UI from org.webjars dependency in Spring Boot.
rest("/test").description("Some description").consumes("application/json").produces("application/json")
.post("/trigger").id("trigger")
.description("Another description")
.type(Map.class).param().name("body").type(body).description("More description"))
.required(true).example(readJson.getJson("json_example.txt")).endParam()
.route().bean(new Service(), "Trigger");
This readJson get JSON as String.
It looks like .example() is ignored and nothing appears in Swagger UI.
It always shows the "string" value inside Example Value like on the picture below.
As a solution, I've created Java POJO class with next code:
public class User{
public String user_id;
public String user_name;
}
Then I linked that class to the Camel REST DSL inside SpringBootRouter class:
...
rest("/test").description("Some description").consumes("application/json").produces("application/json")
.post("/trigger").id("trigger")
.description("Another description")
.type(User.class).param().name("body").type(body).description("More description"))
.required(true).endParam()
.route().bean(new Service(), "Trigger");
...
And this is the result:
If there is a better solution, please tell.
UPDATE:
To replace default value "string" for String or 0 for int or true for Boolean, I've used ApiModelProperty like this:
import io.swagger.annotations.ApiModelProperty;
public class User{
#ApiModelProperty(example = "1165")
public String user_id;
#ApiModelProperty(example = "Bob")
public String user_name;
}
And this is the final result:
In swagger v3 you use
#Model(description = "The user name", example = "Bob")
public String user_name;

How to make final variable when #Value annotation is used

I have read similar post in the forum but actually could not find an answer. I am reading a property from an application.yaml file but I want to make that variable final. But compiler does not allow me to do it and says the variable might not be initialized. What I want to do is to use final as below. So this variable is defined in a controller class.
#Value("${host.url}")
private final String url;
So how can I do it final ?
The only way to achieve it is using constructor injection.
#Component
public class MyBean {
private final String url;
public MyBean(#Value("${host.url}") String url) {
this.url = url;
}
}

Using #Value annotation with Spring and SPeL

I am trying to find a way to do the following in my spring boot 1.5 application.
I have a variable who's value is dynamic meaning it comes in from an external system.
String name = "abc"; //gets set externally
I want to try and use the name's value to lookup my property file and see if there is a matching property defined. something like..
#Value("#{myClassName.name.concat('something')}")
String propertyValue;
Now my application.property file has the following property set
assume name has the value "abc"
property file contents:
abc.something:abcValue
Now, when i try to access the value of the variable propertyValue it gets set to the value abc.something and not abcValue.
I probably think I cannot use #Value with #{} to get to that, I was wondering if there was a way to to use #{} inside ${} so that I goes and fetches the property value after calculating the name of the property using #{}.
Let me know if you need more details please.
A bean life-cycle requires properties to be resolved at compile time. So, #Value requires constant parameter.
You can use Environment bean to access your properties programmatically.
import org.springframework.core.env.Environment;
#Service
public class Serivce {
#Autowired
private Environment environment;
public String getProperty(final String keyPart) {
String key = "build.your." + keyPart;
return environment.getProperty(key)
}
}
By the way you can use #('${spring.some.property}') in SpEL to access placeholder.
// This is valid access to property
#Value("#('${spring.some.property}')")
private String property;

How can I use a local variable in the annotation #Preauthorize?

i need to do something like this
String myVar = "myString";
...
#Preauthorize("customMethod(myVar)")
public void myMethod() {
...
}
but I'm failing at it. How can I do that? It says it cannot be resolved
EDIT:I'm decoupling few rest services and sometimes I have to share infos between them
#Value("${my-properties}")
String urlIWantToShare;
...
#PreAuthorize("isValid(#myValue,urlIWantToShare)")
#RequestMapping(value = "**/letsCheckSecurityConfig", method = RequestMethod.GET)
public boolean letsCheckSecurityConfig(#RequestHeader(name = "MY-VALUE") String myValue)) {
return true;
}
this "isValid" custom security method will call an external service, that doesn't know anything about the caller and his infos. I need to transmit few infos and I need to take them from different kind of sources
One of the sources is my application.properties
EDIT2: I managed to do this
#PreAuthorize("isValid(#myValue, #myProperty)")
#RequestMapping(value = "**/letsCheckSecurityConfig", method = RequestMethod.GET)
public boolean letsCheckSecurityConfig(#RequestHeader(name = "MY-VALUE") String myValue,
#Value("${my-property-from-app-properties}") String myProperty))
..but I want to use not only actual static properties but runtime one. Any help?
You can create a wrapper method without parameters which will call the desired method with parameters. In the annotation you can use the method without parameters
Apologies if I have misunderstood what you are trying to do, but from my understanding you're trying to set an annotation at runtime based on a variable / app.properties, so that you can then read this variable and then execute your class?
If this is the case, You cannot do this from an annotation alone as annotations cannot read local variables and cannot be set at runtime.
However, one option for you is to have an object which contains the 'values' of interest for you and then read the values from the object.
Something like the below:
PoJo
public class testObject{
#test
private String myVar;
private String myValue;
//Getters and Setters
}
Get Object values
public void getFields (Object obj){
Field fields = obj.getClass().getDeclaredFields();
for (Field f : fields){
test fieldAnnotation = f.getAnnotation(test.Class);
if (fieldAnnotation != null){
f.get(obj);
// Do checks based on this
}
}
}
Main Class
public static void main(String[] args){
//Create object
testObject test = new testObject();
test.setOne("testOne");
test.setTwo("testTwo");
getFields(test);
}
I've pulled this code based on what I had to do to get the fields - but in my case, I did not know the object types I was going to be passed. You are simply using the annotation to 'mark' the fields you want to retrieve and then reading the value from the object.
If you're in a similar situation, then you can see my answer here: initial answer
Let me know if i've misunderstood this and I can try and further clarify my answer.

How to bind a string array of properties in Spring?

I have the following in my application.properties file
some.server.url[0]=http://url
some.server.url[1]=http://otherUrl
How do I refer to the array of properties using the #Value anotation inside a #Bean method?
I am using Java 6 with Tomcat 7 and Spring boot 1.4
I was also having the same problem as you mentioned and it seems using index form on application.properties was not working for me either.
To solve the problem I did something like below
some.server.url = url1, url2
Then to get the those properties I simply use #Value
#Value("${some.server.url}")
private String[] urls ;
Spring automatically splits the String with comma and return you an Array. AFAIK this was introduced in Spring 4+
If you don't want comma (,) as seperator you have to use SpEL like below.
#Value("#{'${some.server.url}'.split(',')}")
private List<String> urls;
where split() accepts the seperator
You can use a collection.
#Value("${some.server.url}")
private List<String> urls;
You can also use a configuration class and inject the bean into your other class:
#Component
#ConfigurationProperties("some.server")
public class SomeConfiguration {
private List<String> url;
public List<String> getUrl() {
return url;
}
public void setUrl(List<String> url) {
this.url = url;
}
}
Follow these steps
1)
#Value("${some.server.url}")
private List urls;
2)
#ConfigurationProperties("some.server")
public class SomeConfiguration {
3)
You should have getter and setter for instance variable 'urls'

Resources