Home > other >  How to override constructor values
How to override constructor values

Time:09-20

I have a configuration class with this constructor:

  public CxfConfigurerImpl(@Value("${cxfclient.timeout.connection}") long connectionTimeout,
                           @Value("${cxfclient.timeout.connection-request}") long connectionRequestTimeout,
                           @Value("${cxfclient.timeout.receive}") long receiveTimeout) {
    this.receiveTimeout = receiveTimeout;
    this.connectionTimeout = connectionTimeout;
    this.connectionRequestTimeout = connectionRequestTimeout;
  }

But I have different values to set according with my endpoints requests. Ex:

  @Value("${cxfclient.timeout-three.connection}")
  private long connectionTimeout3;

  @Value("${cxfclient.timeout-three.connection-request}")
  private long connectionRequestTimeout3;

  @Value("${cxfclient.timeout-three.receive}")
  private long receiveTimeout3;

  @Autowired
  private CxfConfigurerImpl cxfConfigurer3Seg = new CxfConfigurerImpl(connectionTimeout3, connectionRequestTimeout3, receiveTimeout3);

My environment variables are:

CXFCLIENT_TIMEOUT_CONNECTION=1000
CXFCLIENT_TIMEOUT_CONNECTIONREQUEST=1000
CXFCLIENT_TIMEOUT_RECEIVE=1000

CXFCLIENT_TIMEOUTTHREE_CONNECTION=3000
CXFCLIENT_TIMEOUTTHREE_CONNECTIONREQUEST=3000
CXFCLIENT_TIMEOUTTHREE_RECEIVE=3000

The problem is that for the object "cxfConfigurer3Seg" I'm getting the default constructor values (1000). Is there any way to override the values?

OBS: I can't change the "CxfConfigurerImpl" constructor implementation.

CodePudding user response:

Please notes that @Value : by definition is an Annotation used at the field or method/constructor parameter levelthat indicates a default value expression for the annotated element.
And Note that actual processing of the @Value annotation is performedby a BeanPostProcessor So values are setted after bean built, otherwise you will already find the value 1000 in your variables

So you should change your implementation here :

You should init configuration in the application level and use @Qualifier for two different bean instead the @Value constructor injection:

@Component
@Getter
@Setter
@ToString
public class B {

    private long receiveTimeout;
    private long connectionTimeout;
    private long connectionRequestTimeout;

    public B () {
    
    }
    public B ( long connectionTimeout,
               long connectionRequestTimeout,
               long receiveTimeout) {
        this.receiveTimeout = receiveTimeout;
        this.connectionTimeout = connectionTimeout;
        this.connectionRequestTimeout = 
        connectionRequestTimeout;
    }
}

In the spring boot application startup class : build two beans with two configurations : (b1, b2)

  @Value("${cxfclient.timeout-three.connection}")
  private long connectionTimeout3;

  @Value("${cxfclient.timeout-three.connection-request}")
  private long connectionRequestTimeout3;

  @Value("${cxfclient.timeout-three.receive}")
  private long receiveTimeout3;
  
  @Value("${cxfclient.timeout.connection}")
  private long receiveTimeout;
  @Value("${cxfclient.timeout.connection-request}") 
  private long connectionTimeout;
  @Value("${cxfclient.timeout.receive}")
  private long connectionRequestTimeout;


  @Bean ("b1")
  public B createAsB1() { 
      return new B (connectionTimeout3, connectionRequestTimeout3, receiveTimeout3);
  }
  
  @Bean ("b2")
  public B createAsB2() { 
      return new B(connectionTimeout, connectionRequestTimeout, receiveTimeout);
  }

use them by :

@Component
@Getter
@Setter
@ToString
public class UseB {
  @Autowired
  @Qualifier ("b1") 
  private B b1; 

  @Autowired
  @Qualifier ("b2") 
  private B b2; 
}

    String d = ab.getB1().toString();
    System.out.println(d);
    d = ab.getB2().toString();
    System.out.println(d);

result of run :

B(receiveTimeout=3000, connectionTimeout=3000, 
connectionRequestTimeout=3000)
B(receiveTimeout=1000, connectionTimeout=1000, 
connectionRequestTimeout=1000)

CodePudding user response:

There are two options - 
1- if you want both the beans available in your application context then you can create two separate beans with two different values. 
2- If you want to have both values in your application but only one active bean at a time then you can use @ConditionalOnBean, attaching [here][1] a document for your help. Below is sample rough conditionalonbean code snippet and can enable only one of bean from your configurations file.

    @ConditionalOnBean(
    "prefix" = "..",
    "havingValue" = "true",
    "name" = "abc")
    public A methodA() {}
    
    @ConditionalOnBean(
    "prefix" = "..",
    "havingValue" = "false",
    "name" = "abc")
    public A methodB() {}
  • Related