Spring boot - #ConditionalOnProperty or #ConditionalOnExpression - spring-boot

I'm using Spring-Boot-1.1.7.
My intention is to add a bean to my context according to a value of a property of type string.
I mean, I can see a lot of examples of boolean values such as this:
#ConditionalOnExpression("${xxx.enabled:true}")
But I want an expression based on a value of a property, for example:
#ConditionalOnExpression("${server.host==localhost} or ${server.port==8080} ")
or something like that.
Can someone show me an example how to do it?

Eventually , this one worked for me:
#ConditionalOnExpression("'${server.host}'=='localhost'")

For property value conditional I used:
#ConditionalOnProperty(name="server.host", havingValue="localhost")

If the value you want to compare with is a literal, you need to quote it, and the placeholder would go round the property name (not the whole expression), e.g. ${server.host}=='localhost'

If you are using e.g. a string value and want to check if a value is set, you can use a simple "check":
#Component
#ConditionalOnProperty(value = "foo.value")
public class Foo {
private String value;
// getter/ setter and other stuff ...
}
If you add: foo.value: bar to your application.yml file the component will be found and added to the application context, but if you do not set a value the component will not be added.
If you want to check if the component is found, you can use: debug: true in your application.yml.
Foo matched:
- #ConditionalOnProperty (foo.value) matched (OnPropertyCondition)
vs
Foo: Did not match:
- #ConditionalOnProperty (foo.value) did not find property 'foo.value' (OnPropertyCondition)

Related

Quarkus ConfigMapping: how to map properties with keys with and without next level at the same time, like "fields" and "fields.excludes"

Converting my app to use Quarkus #ConfigMapping is not easy, especially when the properties names may be used by other apps and you are not free to change them.
I have two keys like fields(set of string) and fields.excludes(another set of string). I want to know what I can do to map both of them. I tried:
Set<String> fields();
#WithName("fields")
FieldsExcludes fieldsToExclude();
interface FieldsExcludes {
Set<String> excludes();
}
...
No compilation error, but runtime error:
Caused by: java.util.NoSuchElementException: SRCFG00014: The config property app.operator.0000001.endpoint.0.fields.exclude is required but it could not be found in any config source
at io.smallrye.config.SmallRyeConfig.getIndexedValues(SmallRyeConfig.java:114)
at io.smallrye.config.SmallRyeConfig.getValues(SmallRyeConfig.java:106)
...
Of course, I think Quarkus cannot tell if "fields" is a field of set, or a field of type FieldsExcludes. But this kind of configs are valid in YAML.
fields: [a,b,c,d]
fields.exclude: [e]
(if I break line at 2nd line after fields it's not valid; but if I put it like this it's valid, at least for Intellij IDEA)
See here: https://quarkus.io/guides/config-yaml#configuration-key-conflicts, in the doc it's stated that it's valid; I can use a ~ as a null key. So fields as a list and fields.exclude as another object should be supported.
OK at last it seems already supported; the error is due to it's not defined as "Optional<>" so Quarkus can find it in one place but cannot in another. (YAML contains 2 ConfigDetail, one of them does not have excludes, and it has no default value)
The final code is like this:
interface ConfigDetail {
Set<String> fields();
#WithName("fields")
Optional<FieldsToExclude> fieldsToExclude();
}
...
interface FieldsToExclude {
Set<String> exclude();
}
fields:
~: [a,b,c,d]
exclude: [e]
...
fields:
~: [a,b,c,d,e]
...

Freemarker template value missing while first or second letter is capitalized

I am trying to learn how to integrate Spring Boot(2.6.3) with FreeMarker(2.3.31). Everything works fine until I met an FreeMarker error while trying to get the value like ${myObject.pAram!} while the first or second letter of the param is capitalized.
So I did so test work and get the following conclusion:
While param name of an object is first letter or second letter capitalized, FreeMarker couldn`t get the param value. Some code here in case of my poor English:
#Data
public class TestBean {
String param; //no-capitalized param
String aParam; //second letter capitalized param
String Bparam; //first letter capitalized param
String cpRam; //third letter capitalized param
}
Here what I do some setter in controller:
#RequestMapping("/test")
public String insure(#PathVariable String module,HttpServletRequest request) {
TestBean testBean = new TestBean();
testBean.setParam("param-no capitalize");
testBean.setAParam("aParam-capitalize the second letter");
testBean.setBparam("Bparam-capitalize the first letter");
testBean.setCpAram("cpAram-capitalize the third letter");
request.setAttribute("testBean",testBean);
return "test";
}
And what the test.ftl looks like:
<body>
<body>
<div>${testBean.param!"missing param"}</div>
------------------------------
<div>${testBean.aParam!"missing aParam"}</div>
------------------------------
<div>${testBean.Bparam!"missing Bparam"}</div>
------------------------------
<div>${testBean.cpAram!"missing cpAram"}</div>
However, the final html result is:
param-no capitalize
------------------------------
missing aParam
------------------------------
missing Bparam
------------------------------
cpAram-capitalize the third letter
Since I`m new to FreeMarker and Spring Boot, I failed to figure out why.
Could someone tell me the exact reason? Am I missing some point?
Thanks a lot!
The Java Bean property names are deduced from the getter method names, not from the field names.
For Bparam, Lombok will generate getBparam(), which is the same that you will get for a filed named bparam. So the two cases are indistinguishable, and both will give the property name bparam.
For aParam, Lombok will generate getAParam(), which is the same that you will get for a filed named AParam. So the two cases are indistinguishable, and both will give the property name AParam. Now this last is not intuitive (I would rather expect aParam), but these are the rules of Java Beans (not of FreeMarker). Which, in turn is a consequence of the broken camel case conventions of Java (i.e., that you must keep letters that were originally upper case as upper case, instead of only using upper case for the first letter of words, so Java camel case is not reversible in general).

Is there a way to configure 2 property system in same #Value ins spring boot?

I trying to use 2 different property files with the same parameters which every parameter is describing the same property for example:
NewsPaperConsumer.properties, MarketConsumer.properties when every file have the same parameters.
My aim is to use the separated way to make the configuration files more readable but at the progromatic side union them to one hash map for example:
NewPaperConsumer and MarketConsumer have the parameter serverAddress so I'll get it by:
#Value("${serverAddress}")
private HashMap<String,String> serverAdresses;
how I change the way the system property save the parameter (instead of assign the value to string that It will assign it to hash map - {"key" : "value }

FreeMarker Java 8 Optional value support

Does FreeMarker support Optional value in Java 8?
e.g. I have String id, and its getter method is like:
public Optional<String> getId() {
return Optional.ofNullable(Id);
}
How am I going to reference it in the .ftl file. It seems that {data.id} can not find the correct Optional value. But gives me Optional[1334586]
Well, Freemarker is not supposed to be aware of Optional or it is better to say that its dynamically typed so it works for any object.
Since you calling ${data.id} it's just calls toString on Optional which is totally expected behavior.
If you want to handle null values in your template and for that you want to use Optional, you may choose to set a default value if null, so Optional usage won't be needed:
Synopsis: unsafe_expr!default_expr or unsafe_expr! or (unsafe_expr)!default_expr or (unsafe_expr)!
Example: ${data.id!"No id."}
Or check if it's exists:
<#if data?? && data.id??>
Id found
<#else>
Id not found
</#if>
For more info check out the Freemarker docs. Specifically parts: Handling missing values and Missing value test operator.
If you just want to get the value from Optional in your template:
${data.id.orElse('')}
or
${data.id.get()!''}

Ember.js: bindAttr only expects a boolean

Here is a simple jsfiddle. I'm trying to add the class-names a and b, but what I get is an empty class. For example, if I change it to
{{ bindAttr class="str:a:b}}
I get a
Furthermore, is it possible to add some other (default) classnames too ?
{{ bindAttr class"str className1 className2"}}
Of course! Your syntax is just a bit wrong. The syntax for adding a default class is only :className. Here is a simple jsfiddle to show you.
What your first line of code actually states is that if str is true, then assign class 'a' to the element, otherwise class 'b' (which is why you only get 'a' as the assigned class). An example of conditional classes is in an updated version of your jsfiddle here.

Resources