0

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
    }
}
  • Can you show us more code about where you autowire the props? Just to make sure this isn't a duplicate of https://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-field-null. – g00glen00b Dec 03 '21 at 23:07
  • @g00glen00b added some code; tried suggestions from the answers in the link you shared, problem still there. HOWEVER, in RestController, it works perfectly. (and in tests) – Samuel Waithaka Dec 04 '21 at 08:22
  • 1
    How do you interact with `MyService`? Can you show that code too (where you call `myService.post()`). – g00glen00b Dec 04 '21 at 11:04
  • @g00glen00b I've showed on RestController example code – Samuel Waithaka Dec 05 '21 at 11:47

2 Answers2

1

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.

g00glen00b
  • 41,995
  • 13
  • 95
  • 133
0

UPDATE:

new MyService() is not a "spring bean", thus can't be auto-wired with anything!;)

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).

xerx593
  • 12,237
  • 5
  • 33
  • 64