Spring Boot | spring EL using with annotation attribute value to set any random value using properties - spring-boot

I am using one existing spring boot annotation and want to set the attribute value dynamically using spring expression and want to have one constant value as a prefix,
sample Code snippet
#KafkaListener(topics="${topic.name}", groupId="#{'consumergroup' + (int)(java.lang.Math).random() }")
public void consumerMethod(){
}
I want to create a new consumer group for each new container using the above kind of implementation.
But I am facing the below exception.
Expression parsing failed; nested exception is
org.springframework.expression.spel.SpelParseException: EL1041E: After
parsing a valid expression, there is still more data in the
expression: 'lparen(()
kindly help me to either use template spring EL or any other way I can use to set dynamic consumer group id with the constant prefix.

groupId="#{'consumergroup' + (100 * T(Math).random()).intValue() }"
There is no cast operator in SpEL. Just because it uses a ConversionService internally to convert from one type to another. I use intValue() any way because the result of random() is Double (not double) - SpEL does coercion into type wrappers for API convenience.
The java.lang is imported into SpEL context automatically. No need to add it for Math type.
100 *. See Math.random() JavaDocs: it returns the value between 0.0 and 1.0. So, casting to int would always bring you only 0. The casting doesn't do rounding.
Also see Spring Boot configuration properties feature where you can use random value for the groupId:
spring.kafka.consumer.group-id=consumergroup${random.int}
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.random-values

Related

Spring Expressions, what does it mean value="{someName}"

I am working with a Spring Boot Application that uses SpEl , it has some Redis annotations and it calls my attention the use of brackets on some expressions, i.e.:
#Cacheable(value = "{mycache}", key = "#param")
I can tell the SpEl expression when using # is to refer to the passed param, but for the first part "{myCache}" I am not sure what is the purpose of the braces.

Spring ConfigurationProperties validation of a Double value

I have a property value that should range between 0 and 1.
I like Spring's ConfigurationProperties to validate the property value.
So in my ConfigProperties class I added the #Validated annotation and wrote this:
#Min(0)
#Max(1)
Double fraction;
The strange thing is that the validation works in a manner that looks like flooring / roofing the value from the property file.
This is the outcome of different values I put in the conf file:
fraction=-2.1 -> Spring reports an error and stops (good!)
fraction=2.1 -> Spring reports an error and stops (good!)
fraction=-1.5 -> Spring doesn't report an error and starts (not good!)
fraction=1.5 -> Spring doesn't report an error and starts (not good!)
I also tried using the #Range annotation, but with the same outcomes
So here is the solution as described here:
#DecimalMax("1.0") #DecimalMin("0.0")
Double fraction;
As (clearly) stated by the documentation of both #Min and #Max. The same applies to #DecimalMin and #DecimalMax
Note that double and float are not supported due to rounding errors (some providers might provide some approximative support)
You can use a BigDecimal or BigInteger instead.

Thymeleaf th:value

Using SpringMVC + Thymeleaf, how does one bind an integer based model attribute, to an input field in a form using th:value or th:field, without having a value of '0' show in the field itself.
The issue is not with Thymeleaf, it is on the EL implementation of Tomcat. It doesn't respect the difference between the nullable Integer and primitive int. It is always coercing null values to 0. You can turn off this behavior using this VM argument :
-Dorg.apache.el.parser.COERCE_TO_ZERO=false
or programatically by
System.setProperty("org.apache.el.parser.COERCE_TO_ZERO", "false");
If you choose the programatic way, make sure that you invoke it during initialization of ServletContext (ServletContextListener#contextInitialized)
Just remove th:field attribute and write id and name attributes with corresponding logical name.

How to disable interpolation of property values in property placeholders

I'm using Spring 3 and Spring's property-placeholders in my application context:
<context:property-placeholder location="my.properties"/>
my.properties contains:
key1=value1
key2=some JSP code ${some-model-attr}
The issue is, the values in my.properties are also evaluated against the placeholders, but in my case the values contain JSP EL, which causes "property not found" errors during Spring initialization:
java.lang.IllegalArgumentException: Could not resolve placeholder 'some-model-attr'
So far I have this workaround, but it's ugly:
key1=value1
key2=some JSP code #{'$'}{some-model-attr}
Hence my question:
Is it possible to tell Spring not to interpolate property placeholder values, or, in other words, not to evaluate placeholders recursively?
It looks like it isn't possible to tell Spring not to recursively evaluate placeholders.
The placeholders are evaluated by org.springframework.util.PropertyPlaceholderHelper which (in Spring 3) contains the following line:
// Recursive invocation, parsing placeholders contained in the placeholder key.
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
So the recursive call is hard-coded into the evaluation.
However I think you could change the default prefix and suffix for placeholders so that you use a different syntax for Spring placeholders. <context:property-placeholder> is just a convenient way of constructing the org.springframework.beans.factory.config.PropertyPlaceholderConfigurer class, and that class has methods setPlaceholderPrefix() and setPlaceholderSuffix(). You could use those methods to change the syntax of the Spring placeholders to something like:
$[property]
instead of
${property}
Then I expect Spring won't parse your JSP properties any more because they're in a different syntax:
key2=some JSP code ${some-model-attr}
As a workaround you can use SpEL expression templating. For example:
key2=some JSP code $#{'{some-model-attr}'}
This works because Spring no longer sees the configured property placeholder prefix of ${. However, the SpEL expression evaluates to the String concatenation of:
'some JSP code $' + '{some-model-attr}'
which is the same as
some JSP code ${some-model-attr}

Injecting Spring Spel Expressions into bean properties

How can I inject a String meant to be a spel expression into an app context bean property without having the context interpret the string property as a spel resolvable value.
<bean id="x" p:spelExpression="${#code}/${#value}"/>
I want the the class's setter property to take a string argument and creates a reusable SpelExpression as a private property of the bean, however, the spring application context appears to be recognizing the #variableName as spel expressions and attempting to interpret the expression at initialization time.
I find Spel interpretation to be very useful, but would like to to use spel internally as well, with expression injection into my own beans.
Is it possible to disable the Spel Interpretation of for a bean, or even for a whole context file (maybe with some namespace shenanigans) without having to disable or modify spel expression resolution for the whole application context.
The #{...} are markers for spel interpreter in xml context.
I don't undestand : ${#code}/${#value}. Good is #{code/value}, as I understand things, if code and value are id.
So, if you want a spel expression without interpret it, put string code/value in xml.

Resources