Spring conditionally require bean only if profile is active

Viewed 37

I have a class which is disabled based on @Profile. I want to use it inside another class that is not conditional on the same profile:

@Component
@Profile("!local")
public class NotAlwaysExistingClass {

    public void doThing() {
    ...
    }
}

public class AlwaysExistingClass {
    
    @Autowired(required=true)
    NotAlwaysExistingClass notAlwaysExisting;

    // Impossible for this to happen if profile is "local"
    public void notAlwaysDoneThing() {
        notAlwaysExisting.doThing();
    }
    ...
}

I don't want to set the @Autowired(required=false) in all cases. Is it possible to disable the requirement only if a certain profile is active? I want to do this to make it more convenient to occasionally run the code locally, but without compromising the application or making major changes to the class structure.

2 Answers

"Smart" (tricky) (?) approach:

NO-OP Bean/Profile ;)

  1. Introduce an other "bean" (or "class"), which:
  • extends NotAlwaysExistingClass
  • takes @Profile("local") (so the logical complement of the "non-local" profile)
  • overrides doThing(), but with no-op/cheap/only logging code.
  1. Done.
  • you don't need (further) refactorings
  • you can leave the required attribute (one of the profiles will always strike)
  • in "non-local" profile, you get the right bean
  • in "local" profile: nice logging/no-op :)

I agree with @xerx593's #1 but you could also change that a little. You could extract an interface and make the class depending on it use it via an interface. Then you would have 2 beans that implement that interface and only available at a given time via @Profile selection. Remember @Autowired is by type by default.

Really this issue is similar (or the same) to having a couple of profiles for various needs of a datasource for example. In my projects, the local profile points to a local DB, the regular one points to some cloud db via env variables or whatever, and then I have a "cicd" profile for integration tests and those use a spun up H2 DB.

Related