Home > Software design >  @ConfigurationProperties, @Value not Working YET Passing the Tests
@ConfigurationProperties, @Value not Working YET Passing the Tests

Time:12-06

I have a strange problem reading configuration, none of solutions I've seen seem to work. Here is my code:

@SpringBootApplication
@EnableConfigurationProperties
public class Application {
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Here is my properties class

@Component
@ConfigurationProperties(prefix = "my")
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class MyProperties {
    private String host;
    private int port;
}

I then use MyProperties class in my class using @Autowired:

@Autowired
private MyProperties props;

However, I'm getting null for my props object.

Strangely, this is passing the tests just perfectly:

@SpringBootTest
class ApplicationTests {
    
    @Autowired
    private MyProperties props;
    
    @Test
    void test_configuration() {
        Assertions.assertEquals(props.getHost(), "xx.xx.xx.xx");//pass!
        Assertions.assertEquals(props.getPort(), xxxxxx);//pass!
    }
}

It has totally refused to work, and so has @Value injection. What could I be missing?

EDIT

Here's complete code of how I'm using @Autowired on MyProperties (I've included @Value which is also not working)

@Slf4j
@Component //also tried @Configurable, @Service
public class MyService {
    
    @Autowired
    private MyProperties props;
    
    @Value("localhost")
    public String host;
    
    public void post() {
        log.info(host   props);// =null and null
    }
}

EDIT2

However, I've noticed that on the controller, it works perfectly okay:

@Slf4j
@RestController
@Service
public class Main {
    
    @Autowired
    private MyProperties props;
    
    @Value("localhost")
    private String host;
    
    @GetMapping("/post")
    public void post() {
        log.info(host   props);//=it's perfect!
        new MyService().post();// calling MyService - where @Autowired or @Value is failing
    }
}

CodePudding user response:

The reason this isn't working is because the MyService you're using isn't a Spring bean, but an instance you created by yourself (using new MyService()).

To make this work, you should autowire MyService, in stead of creating your own instance:

@Slf4j
@RestController
public class Main {
    @Autowired // Autowire MyService
    private MyService myService;

    @GetMapping("/post")
    public void post() {
        myService.post(); // Use the myService field
    }
}

For more information, look at this Q&A: Why is my Spring @Autowired field null.

CodePudding user response:

1. Lombok

Some people use Project Lombok to add getters and setters automatically. Make sure that Lombok does not generate any particular constructor for such a type, as it is used automatically by the container to instantiate the object.

With "such a type" ConfigurationProperties is referred in Externalized Configuration (one of my favorite chapters;) More Exact: 2.8.1. JavaBean properties binding, at the bottom of second "Note!" ;)

So this could be a reason (for strange behavior).

  • Related