ChikChak
ChikChak

Reputation: 1024

SpEL @Value with nested condition

I'm using the @Value annotation, and I want it to be a bit more complex now. I have two config values - val1, and val2. I want to inject it as follows: If val1 exists in the configuration, use it. Else, if val2 is true, inject default1. If it's false, inject default2.

I tried something like:

@Value("#{val1 ? val1 : (val2 ? 'default1' : 'default2')}")

But I keep getting:

`EL1008E`: property or filed 'val1' cannot be found on object of type 'org.springframeowrk.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?

When I try other expressions, such as ${val1} or '${val1}' it still does not seem to work.

What's the correct way to do nested conditions in the @Value annotation, or is it too complex?

Upvotes: 1

Views: 3730

Answers (1)

Michiel
Michiel

Reputation: 3410

I have adjusted the expression and written a small test to illustrate the change. In short, use ${some.prop:defaultVal} to define a default value and use ${some.prop:} to define an empty String as a default value. Also, use single quotes ' in a SPEL expression to indicate the String value instead of a reference.

Play around with the TestPropertySource to verify the outcome. I have added a second test to show that when a default value is not present, Spring might (not always) decide to return the textual representation of the placeholder.


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@TestPropertySource(properties = {"val1=v1", "val2=v2"})
public class SomeTest {

    @Value("#{ '${val1:}' != '' ? '${val1}' : ('${val2:}' != '' ? 'default1' : 'default2')}")
    private String testVal;

    @Value("${nonExistingValue}")
    private String nonExistingValue;

    @Test
    public void test() {
        assertThat(testVal).isEqualTo("v1");
    }

    @Test
    public void testNonExistingValue() {
        assertThat(nonExistingValue).isEqualTo("${nonExistingValue}");
    }
}

Although the above expression works, I would highly recommend to use ConfigurationProperties, or a T expression type operator referring to a static method. The current set up might become even less readable when the expressions becomes more complex.

Upvotes: 2

Related Questions