user2185573
user2185573

Reputation:

Autowiring in optional fields in Spring

I apologize beforehand if this question has already been answered before or if its too easy, but I am relatively new to spring as a DI framework and I have the following problem

@Bean
public EnvironmentInfo environmentInfo() {
    return new EnvironmentInfo();
}

@Bean(name = "availabilityZone")
@Autowired
public Optional<String> getAvailabilityZone(EnvironmentInfo envInfo) {
    return envInfo.getAvailabilityZone();  // this returns an Optional<String>
}

And then I autowire it in elsewhere like this

@Autowired
@Named("availabilityZone")
protected Optional<String> availabilityZone;

Now I put a log statement in the getAvailabilityZone and confirmed its called and it evaluates to a Optional with a proper availability zone. However the autowire itself evaluates to Optional.empty

My question is, is there something I am missing from the Autowiring to vend the Optional correctly?

Edit

The problem effectively goes away if I do this

@Bean(name = "availabilityZone")
@Autowired
public String getAvailabilityZone(EnvironmentInfo envInfo) {
    return envInfo.getAvailabilityZone().getOrElse("N/A");
}

@Autowired
@Named("availabilityZone")
protected String availabilityZone;

Upvotes: 2

Views: 1267

Answers (1)

Martin van Wingerden
Martin van Wingerden

Reputation: 981

Autowiring an optional has another meaning, that is why it does not work as you hoped.

I used it in cases where eg. a JavaMailSender was not guaranteed to be available but if it was it was available as an JavaMailSender injecting worked than as:

@Autowired
protected Optional<JavaMailSender> mailSender;

The worst answer is that the following works (at least in the most recent spring-boot):

@Service
public class TestController {
    @Autowired
    TestController(@Named("availabilityZone") Optional<Optional<String>> availabilityZone) {
        System.out.println(availabilityZone);
    }
}

But this makes me cry...

Another option which is a little bit better is:

@Bean(name = "availabilityZone")
@Autowired
public String getAvailabilityZone(EnvironmentInfo envInfo) {
    return envInfo.getAvailabilityZone().orElse(null);
}

Another solution would be wrapping it in some custom object, but I think returning null for your bean would be good enough.

Upvotes: 3

Related Questions