How to define #Value as nullable in spring with kotlin? - spring

I don't want autowiring fail when one specific property is missing. In that case i can accept nulls. How can i achieve it?
#Service
class MyClass(
#Value("\${my.nullable.property}") property: String?
)

You can define a default when using #Value and set it to an expression that evaluates to null:
#Value("\${my.nullable.property:#{null}}")
Anything after the : is the default if my.nullable.property cannot be defined. Because putting null there would be treated as a String, we have to use an expression that evaluates to null, which is wrapped by #{}.

Related

Spring ConditionalOnProperty - understanding the "havingValue" property?

The javadoc for org.springframework.boot.autoconfigure.condition.ConditionalOnProperty is like below -
public abstract java.lang.String havingValue
The string representation of the expected value for the properties.
If not specified, the property must not be equal to false.
Returns:
the expected value
Default:
"
What i don't understand in the above is If not specified, the property must not be equal to false.
If the property is not specified at all, then how can it be false (or true or xyz).
From the ConditionalOnProperty api doc - this part is clear.
If the property is not contained in the Environment at all, the matchIfMissing() attribute is consulted. By default missing attributes do not match.

Exclude 0 from JSON response in Jackson Spring boot

I have a POJO like this.
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public class Test {
private int a;
private String b;
}
I want to exclude the property 'a' if it has 0 value. String b is excluded with
#JsonInclude(JsonInclude.Include.NON_NULL)
Only way I could thing of is convert the int data type to Integer Object and set the value to NULL in the setter explicitly if it is 0.
Any other suggestions or correct solution will be appreciated
Option 1:
Do what you said: Change int to Integer and use #JsonInclude(Include.NON_NULL). Because primitive types have default values and their values cannot be compared to null you have to wrap the int to Integer. See Primitive Data Types. imho this is the cleaner way.
Option 2:
Use the way described in this answer and use #JsonInclude(Include.NON_DEFAULT) instead (see Jackson-annotations API), so that default values (and so also null values for objects) will be ignored.
Note:
If you only want to exclude the specific field (in your case the int/Integer - a - field) when it has a null-/default value and the other fields (in your case the String - b - field) should be included when they have null-/default values, put the annotation on field level.

Validate at least 1 of a set of args is present in Kotlin class constructor

Scenario
I need to create a Kotlin class that can receive up to 4 arguments for its constructor, but only requires at least 1 out of a set of 3 (the fourth being entirely optional). To illustrate:
class Pie {
// Completely optional, the constructor should use it if present, otherwise it may be null.
var topping: String?
// Of these three [fillingA, fillingB, fillingC] 1 or more must be present.
var fillingA: String?
var fillingB: String?
var fillingC: String?
}
Thoughts
I've attempted to use Kotlin init{} blocks for validation, or telescoping constructors, but it gets ugly fast and I've yet to solve the issue. I have not found anything in the kotlinlang.org docs on primary/secondary constructors that is more elegant, though. My preference would be to find something similar to the #Size or #NotNull annotations, but I have failed to locate anything close.
It is important to note that I am using this class as a model for an API response.
Question
What is the most concise way to validate that a Kotlin class has at least 1 of a set of arguments passed to its constructor?
Are this fillings interchangeable? You could assume that fillingA is always required and the other ones are optional, something like this:
class Pie constructor(
val fillingA: String,
val fillingB: String? = null,
val fillingC: String? = null,
val topping: String? = null
){...}

Kotlin compiler complains about using a SPeL expression in a property definition. WHY?

When I try to use a SPeL expression to inject a value it works from in Java but NOT in Kotlin. The compiler says
Error:(13, 25) Kotlin: An annotation parameter must be a compile-time constant
Code:
#SpringBootApplication
open class DeDup(#Value("#{new java.io.File('${roots}')}") val roots: Set<File>,
#Value("algo") val hashAlgo: String,
#Value("types")val fileTypes: List<String>) {
}
fun main(args: Array<String>) {
SpringApplication.run(DeDup::class.java, *args)
}
Mmm... news flash Kotlin compiler: It IS a constant! The compiler clearly knows it's a SPeL expression and doesn't like it.
My questions:
Why doesn't Kotlin like SPeL? This is a construction injection (or is it) and doesn't violate immutability.
Is this a compiler bug? The message is irrefutably wrong.
${roots} inside a String in Kotlin is a string template, therefore that String is not a constant.
If you want the String to contain those actual characters and not be interpreted as a template, you'll have to escape the $:
#Value("#{new java.io.File('\${roots}')}")

Using a static variable value in Qualifier annotation

Is it possible to pass a static variable defined in a class as argument to #Qualifier annotation? I tried the below format and a few other variations, but nothing worked.
#Qualifier("T(com.test.Constants).BEAN_NAME")
Spring-el works in #Value annotation. For example, below example is valid:
#Value("#{ systemProperties['user.region'] }")
Try with #Qualifier(com.test.Constants.BEAN_NAME)

Resources