This is driving me up the wall trying to get spring boot @configurationproperties annotation working. So hoping someone can shed some light on this for me as to what I am doing wrong. I have a spring boot application and it contains a application.properties on the classpath. It has a value in there of
server.contextPath=/test/v1
server.port=8080
spring.profiles.active=dev
vendors=me
I have a application.class which has the spring boot annotation and sits at the top of my package hierarchy
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableConfigurationProperties
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I am trying to map the property vendors into a configurationproperties bean as below
package com.test.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("classpath:application.properties")
@ConfigurationProperties
public class GlobalProperties {
private String vendors;
public String getVendors() {
return vendors;
}
public void setVendors(String vendors) {
this.vendors = vendors;
}
}
and then call this bean from my rest controller. I know it resolves the property as when i rename it the server fails to start. In the code below the props bean is not getting autowired and is null. //code ommitted for brevity
package com.test.controller;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.test.config.GlobalProperties;
@RestController
@Component
public class MController {
//TODO should be wired in from properties file
@Autowired
GlobalProperties props;
private boolean vendorUnknown(String vendor) {
if(props.getAllowedVendor().equalsIgnoreCase(vendor)) {
return true;
}
return false;
}
@RequestMapping(value = "/test/{id}", method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<?> getStatus(
@PathVariable String id) {
//@RequestBody Bookmark input
if(vendorUnknown("me")) {
System.out.println("found");
};
return ResponseEntity.noContent().build();
}
}
Anybody point me to what i have done wrong please?
UPDATE:
changed the code above to be a more simplistic version with a test class to recreate the issue. See below for my pom.xml and test class
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.me.test</groupId>
<artifactId>test-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- tag::actuator[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- end::actuator[] -->
<!-- tag::tests[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- end::tests[] -->
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Test class:
package com.test.controller;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class MControllerTest {
@Autowired
private MockMvc mockMvc;
@InjectMocks
MController testController;
@Before
public void setup() {
// this must be called for the @Mock annotations above to be processed
// and for the mock service to be injected into the controller under
// test.
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(testController).build();
}
@Test
public void testPropertiesMsg() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/test/1").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
}