Skip to content

Commit e15d7d2

Browse files
committed
Just respond with the id for successful registration
fixes codecentric#590 (old client - new server)
1 parent cf2a9ee commit e15d7d2

File tree

2 files changed

+148
-138
lines changed

2 files changed

+148
-138
lines changed

spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/registry/web/RegistryController.java

Lines changed: 70 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package de.codecentric.boot.admin.registry.web;
1717

18+
import java.net.URI;
1819
import java.util.Collection;
1920

2021
import org.slf4j.Logger;
@@ -27,11 +28,14 @@
2728
import org.springframework.web.bind.annotation.RequestMethod;
2829
import org.springframework.web.bind.annotation.RequestParam;
2930
import org.springframework.web.bind.annotation.ResponseBody;
31+
import org.springframework.web.util.UriComponentsBuilder;
3032

3133
import de.codecentric.boot.admin.model.Application;
3234
import de.codecentric.boot.admin.registry.ApplicationRegistry;
3335
import de.codecentric.boot.admin.web.AdminController;
3436

37+
import static java.util.Collections.singletonMap;
38+
3539
/**
3640
* REST controller for controlling registration of managed applications.
3741
*/
@@ -40,78 +44,77 @@
4044
@RequestMapping("/api/applications")
4145
public class RegistryController {
4246

43-
private static final Logger LOGGER = LoggerFactory.getLogger(RegistryController.class);
47+
private static final Logger LOGGER = LoggerFactory.getLogger(RegistryController.class);
4448

45-
private final ApplicationRegistry registry;
49+
private final ApplicationRegistry registry;
4650

47-
public RegistryController(ApplicationRegistry registry) {
48-
this.registry = registry;
49-
}
51+
public RegistryController(ApplicationRegistry registry) {
52+
this.registry = registry;
53+
}
5054

51-
/**
52-
* Register an application within this admin application.
53-
*
54-
* @param application The application infos.
55-
* @return The registered application.
56-
*/
57-
@RequestMapping(method = RequestMethod.POST)
58-
public ResponseEntity<Application> register(@RequestBody Application application) {
59-
Application applicationWithSource = Application.copyOf(application).withSource("http-api")
60-
.build();
61-
LOGGER.debug("Register application {}", applicationWithSource.toString());
62-
Application registeredApp = registry.register(applicationWithSource);
63-
return ResponseEntity.status(HttpStatus.CREATED).body(registeredApp);
64-
}
55+
/**
56+
* Register an application within this admin application.
57+
*
58+
* @param application The application infos.
59+
* @return The registered application.
60+
*/
61+
@RequestMapping(method = RequestMethod.POST)
62+
public ResponseEntity<?> register(@RequestBody Application application, UriComponentsBuilder builder) {
63+
Application applicationWithSource = Application.copyOf(application).withSource("http-api").build();
64+
LOGGER.debug("Register application {}", applicationWithSource.toString());
65+
String id = registry.register(applicationWithSource).getId();
66+
URI location = builder.path("/{id}").buildAndExpand(id).toUri();
67+
return ResponseEntity.created(location).body(singletonMap("id", id));
68+
}
6569

66-
/**
67-
* List all registered applications with name
68-
*
69-
* @param name the name to search for
70-
* @return List
71-
*/
72-
@RequestMapping(method = RequestMethod.GET)
73-
public Collection<Application> applications(
74-
@RequestParam(value = "name", required = false) String name) {
75-
LOGGER.debug("Deliver registered applications with name={}", name);
76-
if (name == null || name.isEmpty()) {
77-
return registry.getApplications();
78-
} else {
79-
return registry.getApplicationsByName(name);
80-
}
81-
}
70+
/**
71+
* List all registered applications with name
72+
*
73+
* @param name the name to search for
74+
* @return List
75+
*/
76+
@RequestMapping(method = RequestMethod.GET)
77+
public Collection<Application> applications(@RequestParam(value = "name", required = false) String name) {
78+
LOGGER.debug("Deliver registered applications with name={}", name);
79+
if (name == null || name.isEmpty()) {
80+
return registry.getApplications();
81+
} else {
82+
return registry.getApplicationsByName(name);
83+
}
84+
}
8285

83-
/**
84-
* Get a single application out of the registry.
85-
*
86-
* @param id The application identifier.
87-
* @return The registered application.
88-
*/
89-
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
90-
public ResponseEntity<?> get(@PathVariable String id) {
91-
LOGGER.debug("Deliver registered application with ID '{}'", id);
92-
Application application = registry.getApplication(id);
93-
if (application != null) {
94-
return ResponseEntity.ok(application);
95-
} else {
96-
return ResponseEntity.notFound().build();
97-
}
98-
}
86+
/**
87+
* Get a single application out of the registry.
88+
*
89+
* @param id The application identifier.
90+
* @return The registered application.
91+
*/
92+
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
93+
public ResponseEntity<?> get(@PathVariable String id) {
94+
LOGGER.debug("Deliver registered application with ID '{}'", id);
95+
Application application = registry.getApplication(id);
96+
if (application != null) {
97+
return ResponseEntity.ok(application);
98+
} else {
99+
return ResponseEntity.notFound().build();
100+
}
101+
}
99102

100-
/**
101-
* Unregister an application within this admin application.
102-
*
103-
* @param id The application id.
104-
* @return the unregistered application.
105-
*/
106-
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
107-
public ResponseEntity<?> unregister(@PathVariable String id) {
108-
LOGGER.debug("Unregister application with ID '{}'", id);
109-
Application application = registry.deregister(id);
110-
if (application != null) {
111-
return ResponseEntity.ok(application);
112-
} else {
113-
return ResponseEntity.notFound().build();
114-
}
115-
}
103+
/**
104+
* Unregister an application within this admin application.
105+
*
106+
* @param id The application id.
107+
* @return the unregistered application.
108+
*/
109+
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
110+
public ResponseEntity<?> unregister(@PathVariable String id) {
111+
LOGGER.debug("Unregister application with ID '{}'", id);
112+
Application application = registry.deregister(id);
113+
if (application != null) {
114+
return ResponseEntity.ok(application);
115+
} else {
116+
return ResponseEntity.notFound().build();
117+
}
118+
}
116119

117120
}

spring-boot-admin-server/src/test/java/de/codecentric/boot/admin/registry/web/RegistryControllerTest.java

Lines changed: 78 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,25 @@
1515
*/
1616
package de.codecentric.boot.admin.registry.web;
1717

18+
import static org.mockito.Matchers.matches;
1819
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
1920
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
2021
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
22+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
2123
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
2224
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
2325

2426
import java.io.UnsupportedEncodingException;
2527

28+
import org.hamcrest.CoreMatchers;
2629
import org.json.JSONException;
2730
import org.json.JSONObject;
2831
import org.junit.Before;
2932
import org.junit.Test;
3033
import org.mockito.Mockito;
34+
import org.mockito.internal.matchers.Matches;
3135
import org.springframework.context.ApplicationEventPublisher;
36+
import org.springframework.http.HttpHeaders;
3237
import org.springframework.http.MediaType;
3338
import org.springframework.test.web.servlet.MockMvc;
3439
import org.springframework.test.web.servlet.MvcResult;
@@ -42,76 +47,78 @@
4247

4348
public class RegistryControllerTest {
4449

45-
private static final String APPLICATION_TEST_JSON;
46-
private static final String APPLICATION_TWICE_JSON;
47-
48-
static {
49-
try {
50-
APPLICATION_TEST_JSON = new JSONObject().put("name", "test")
51-
.put("healthUrl", "http://localhost/mgmt/health").toString();
52-
APPLICATION_TWICE_JSON = new JSONObject().put("name", "twice")
53-
.put("healthUrl", "http://localhost/mgmt/health").toString();
54-
} catch (JSONException ex) {
55-
throw new ExceptionInInitializerError(ex);
56-
}
57-
}
58-
59-
private MockMvc mvc;
60-
61-
@Before
62-
public void setup() {
63-
ApplicationRegistry registry = new ApplicationRegistry(new SimpleApplicationStore(),
64-
new HashingApplicationUrlIdGenerator());
65-
registry.setApplicationEventPublisher(Mockito.mock(ApplicationEventPublisher.class));
66-
mvc = MockMvcBuilders.standaloneSetup(new RegistryController(registry)).build();
67-
}
68-
69-
@Test
70-
public void test_register_twice_get_and_remove() throws Exception {
71-
MvcResult result = mvc
72-
.perform(post("/api/applications").contentType(MediaType.APPLICATION_JSON)
73-
.content(APPLICATION_TEST_JSON))
74-
.andExpect(status().isCreated()).andExpect(jsonPath("$.name").value("test"))
75-
.andExpect(jsonPath("$.healthUrl").value("http://localhost/mgmt/health"))
76-
.andExpect(jsonPath("$.id").isNotEmpty()).andReturn();
77-
78-
String id = extractId(result);
79-
80-
mvc.perform(post("/api/applications").contentType(MediaType.APPLICATION_JSON)
81-
.content(APPLICATION_TWICE_JSON)).andExpect(status().isCreated())
82-
.andExpect(jsonPath("$.name").value("twice"))
83-
.andExpect(jsonPath("$.healthUrl").value("http://localhost/mgmt/health"))
84-
.andExpect(jsonPath("$.id").value(id));
85-
86-
mvc.perform(get("/api/applications")).andExpect(status().isOk())
87-
.andExpect(jsonPath("$[0].id").value(id));
88-
89-
mvc.perform(get("/api/applications?name=twice")).andExpect(status().isOk())
90-
.andExpect(jsonPath("$[0].id").value(id));
91-
92-
mvc.perform(get("/api/applications/{id}", id)).andExpect(status().isOk())
93-
.andExpect(jsonPath("$.id").value(id));
94-
95-
mvc.perform(delete("/api/applications/{id}", id)).andExpect(status().isOk())
96-
.andExpect(jsonPath("$.id").value(id));
97-
98-
mvc.perform(get("/api/applications/{id}", id)).andExpect(status().isNotFound());
99-
}
100-
101-
private String extractId(MvcResult result) throws UnsupportedEncodingException {
102-
return JsonPath.compile("$.id").read(result.getResponse().getContentAsString());
103-
}
104-
105-
@Test
106-
public void test_get_notFound() throws Exception {
107-
mvc.perform(get("/api/applications/unknown")).andExpect(status().isNotFound());
108-
mvc.perform(get("/api/applications?name=unknown")).andExpect(status().isOk())
109-
.andExpect(jsonPath("$").isEmpty());
110-
}
111-
112-
@Test
113-
public void test_delete_notFound() throws Exception {
114-
mvc.perform(delete("/api/applications/unknown")).andExpect(status().isNotFound());
115-
}
50+
private static final String APPLICATION_TEST_JSON;
51+
private static final String APPLICATION_TWICE_JSON;
52+
53+
static {
54+
try {
55+
APPLICATION_TEST_JSON = new JSONObject().put("name", "test")
56+
.put("healthUrl", "http://localhost/mgmt/health")
57+
.toString();
58+
APPLICATION_TWICE_JSON = new JSONObject().put("name", "twice")
59+
.put("healthUrl", "http://localhost/mgmt/health")
60+
.toString();
61+
} catch (JSONException ex) {
62+
throw new ExceptionInInitializerError(ex);
63+
}
64+
}
65+
66+
private MockMvc mvc;
67+
68+
@Before
69+
public void setup() {
70+
ApplicationRegistry registry = new ApplicationRegistry(new SimpleApplicationStore(),
71+
new HashingApplicationUrlIdGenerator());
72+
registry.setApplicationEventPublisher(Mockito.mock(ApplicationEventPublisher.class));
73+
mvc = MockMvcBuilders.standaloneSetup(new RegistryController(registry)).build();
74+
}
75+
76+
@Test
77+
public void test_register_twice_get_and_remove() throws Exception {
78+
MvcResult result = mvc.perform(
79+
post("/api/applications").contentType(MediaType.APPLICATION_JSON).content(APPLICATION_TEST_JSON))
80+
.andExpect(status().isCreated())
81+
.andExpect(header().string(HttpHeaders.LOCATION, new Matches("http://localhost/[0-9a-f]+")))
82+
.andExpect(jsonPath("$.id").isNotEmpty())
83+
.andReturn();
84+
85+
String id = extractId(result);
86+
87+
mvc.perform(post("/api/applications").contentType(MediaType.APPLICATION_JSON).content(APPLICATION_TWICE_JSON))
88+
.andExpect(status().isCreated())
89+
.andExpect(header().string(HttpHeaders.LOCATION, new Matches("http://localhost/[0-9a-f]+")))
90+
.andExpect(jsonPath("$.id").value(id));
91+
92+
mvc.perform(get("/api/applications")).andExpect(status().isOk()).andExpect(jsonPath("$[0].id").value(id));
93+
94+
mvc.perform(get("/api/applications?name=twice"))
95+
.andExpect(status().isOk())
96+
.andExpect(jsonPath("$[0].id").value(id));
97+
98+
mvc.perform(get("/api/applications/{id}", id)).andExpect(status().isOk()).andExpect(jsonPath("$.id").value(id));
99+
100+
mvc.perform(delete("/api/applications/{id}", id))
101+
.andExpect(status().isOk())
102+
.andExpect(jsonPath("$.id").value(id));
103+
104+
mvc.perform(get("/api/applications/{id}", id)).andExpect(status().isNotFound());
105+
}
106+
107+
private String extractId(MvcResult result) throws UnsupportedEncodingException {
108+
return JsonPath.compile("$.id").read(result.getResponse().getContentAsString());
109+
}
110+
111+
@Test
112+
public void test_get_notFound() throws Exception {
113+
mvc.perform(get("/api/applications/unknown")).andExpect(status().isNotFound());
114+
mvc.perform(get("/api/applications?name=unknown"))
115+
.andExpect(status().isOk())
116+
.andExpect(jsonPath("$").isEmpty());
117+
}
118+
119+
@Test
120+
public void test_delete_notFound() throws Exception {
121+
mvc.perform(delete("/api/applications/unknown")).andExpect(status().isNotFound());
122+
}
116123

117124
}

0 commit comments

Comments
 (0)