How to protect @ConfigurationProperties classes from changes?

To use annotation @ConfigurationProperties

, you need to create a class with getters and setters:

@ConfigurationProperties(prefix = "some")
public class PropertiesConfig {
    private boolean debug;

    public boolean isDebug() {
        return debug;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }
}

      

But this leads to a situation where someone wants to change this value by calling:

@Autowire
private PropertiesConfig config;        
//....

config.setDebug(true);

      

Is there a way to create @ConfigurationProperties

annotated classes without delimiters and external parser / read classes?

+3


source to share


3 answers


Something like this works great

@Configuration
class MyAppPropertiesConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "some")
    public PropertiesConfig propertiesConfig () {
        return new PropertiesConfigImpl();
    }

    public interface PropertiesConfig {
            public boolean isDebug();
    }

    private static class PropertiesConfigImpl implements PropertiesConfig {
        private boolean debug;

        @Override
        public boolean isDebug() {
            return debug;
        }

        public void setDebug(boolean debug) {
            this.debug = debug;
        }
    }
}

      



and then

@Autowired PropertiesConfig properties;

      

+1


source


Impossible out of the box. @ConfigurationProperties

beans must have standard receivers and setters. You can consider the approach outlined in this answer: Immutable @ConfigurationProperties

Or something like this:



@Component
public class ApplicationProperties {

  private final String property1;
  private final String property2;

  public ApplicationProperties(
    @Value("${some.property1"}) String property1,
    @Value("${some.other.property2}) String property2) {
    this.property1 = property1;
    this.property2 = property1;
  }

  //
  // ... getters only ...
  //

}

      

0


source


One approach with minimal code boilerplate would probably use a getter-only interface

public interface AppProps {
    String getNeededProperty();
}

      

and get rid of boilerplate getters and setters in the implementation with Lombok comments @Getter

and @Setter

:

@ConfigurationProperties(prefix = "props")
@Getter
@Setter
public class AppPropsImpl implements AppProps {
    private String neededProperty;
}

      

Then other beans are available to bean bo only by interface, instead of labeling it as @Component

or using it @EnableConfigurationProperties(AppPropsImpl.class)

in the main application class, consider setting it in a config which will expose it to the interface:

@Configuration
@EnableConfigurationProperties
public class PropsConfiguration  {
    @Bean
    public AppProps appProps(){
        return new AppPropsImpl();
    }
}

      

Now this bean can only be injected using the frontend and this makes the setters inaccessible to other beans:

public class ApplicationLogicBean {
    @Autowired
    AppProps props;

    public void method(){
        log.info("Got " + props.getNeededProperty());
    }
}

      

Tested with Spring Boot 1.5.3 and Lombok 1.16.16.

0


source







All Articles