diff --git a/src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsSerializers.java b/src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsSerializers.java index 505b716a..3feaaac5 100644 --- a/src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsSerializers.java +++ b/src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsSerializers.java @@ -280,7 +280,6 @@ class HalFormsSerializers { .map(it -> it.getAffordanceModel(MediaTypes.HAL_FORMS_JSON)) // .map(HalFormsAffordanceModel.class::cast) // .filter(it -> !it.hasHttpMethod(HttpMethod.GET)) // - .peek(it -> validate(resource, it)) // .forEach(it -> { Class type = it.getInputType().resolve(Object.class); @@ -388,21 +387,4 @@ class HalFormsSerializers { return new String[] { qualifiedCode, localCode, globalCode }; } } - - /** - * Verify that the resource's self link and the affordance's URI have the same relative path. - * - * @param resource - * @param model - */ - private static void validate(RepresentationModel resource, HalFormsAffordanceModel model) { - - String affordanceUri = model.getURI(); - String selfLinkUri = resource.getRequiredLink(IanaLinkRelations.SELF.value()).expand().getHref(); - - if (!affordanceUri.equals(selfLinkUri)) { - throw new IllegalStateException("Affordance's URI " + affordanceUri + " doesn't match self link " + selfLinkUri - + " as expected in HAL-FORMS"); - } - } } diff --git a/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsValidationIntegrationTest.java b/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsValidationIntegrationTest.java deleted file mode 100644 index a48e2e02..00000000 --- a/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsValidationIntegrationTest.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.hateoas.mediatype.hal.forms; - -import static org.assertj.core.api.Assertions.*; -import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.hateoas.CollectionModel; -import org.springframework.hateoas.EntityModel; -import org.springframework.hateoas.IanaLinkRelations; -import org.springframework.hateoas.Link; -import org.springframework.hateoas.MediaTypes; -import org.springframework.hateoas.config.EnableHypermediaSupport; -import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; -import org.springframework.hateoas.support.Employee; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -/** - * Test that when an {@link org.springframework.hateoas.Affordance} is included that does NOT match the self link, an - * exception is thrown. - * - * @author Greg Turnquist - */ -@ExtendWith(SpringExtension.class) -@WebAppConfiguration -@ContextConfiguration -class HalFormsValidationIntegrationTest { - - @Autowired WebApplicationContext context; - - MockMvc mockMvc; - - @BeforeEach - void setUp() { - this.mockMvc = webAppContextSetup(this.context).build(); - } - - @Test - void singleEmployee() throws Exception { - - Exception exception = this.mockMvc.perform(get("/employees/0").accept(MediaTypes.HAL_FORMS_JSON)) - .andExpect(status().is5xxServerError()) // - .andReturn() // - .getResolvedException(); - - assertThat(exception).isNotNull(); - assertThat(exception.getMessage()).contains("Affordance's URI http://localhost/employees"); - assertThat(exception.getMessage()).contains("doesn't match self link http://localhost/employees/0"); - } - - @Test - void collectionOfEmployees() throws Exception { - - Exception exception = this.mockMvc.perform(get("/employees").accept(MediaTypes.HAL_FORMS_JSON)) // - .andExpect(status().is5xxServerError()) // - .andReturn().getResolvedException(); - - assertThat(exception).isNotNull(); - assertThat(exception.getMessage()).contains("Affordance's URI http://localhost/employees/0"); - assertThat(exception.getMessage()).contains("doesn't match self link http://localhost/employees"); - } - - /** - * This controller violates HAL-FORMS spec requirements. We use it to verify the serializers can catch it. - */ - @RestController - static class BadController { - - private final static Map EMPLOYEES = new TreeMap<>(); - - static { - EMPLOYEES.put(0, new Employee("Frodo Baggins", "ring bearer")); - EMPLOYEES.put(1, new Employee("Bilbo Baggins", "burglar")); - } - - @GetMapping("/employees") - public CollectionModel> all() { - - // Create a list of Resource's to return - List> employees = new ArrayList<>(); - - // Fetch each Resource using the controller's findOne method. - for (int i = 0; i < EMPLOYEES.size(); i++) { - employees.add(findOne(i)); - } - - // Generate an "Affordance" based on this method (the "self" link) - Link selfLink = linkTo(methodOn(BadController.class).all()).withSelfRel() - .andAffordance(afford(methodOn(BadController.class).updateEmployee(null, 0))); - - // Return the collection of employee resources along with the composite affordance - return new CollectionModel<>(employees, selfLink); - } - - @GetMapping("/employees/{id}") - public EntityModel findOne(@PathVariable Integer id) { - - // Start the affordance with the "self" link, i.e. this method. - Link findOneLink = linkTo(methodOn(BadController.class).findOne(id)).withSelfRel(); - - // Define final link as means to find entire collection. - Link employeesLink = linkTo(methodOn(BadController.class).all()).withRel("employees") - .andAffordance(afford(methodOn(BadController.class).newEmployee(null))); - - // Return the affordance + a link back to the entire collection resource. - return new EntityModel<>(EMPLOYEES.get(id), findOneLink.andAffordances(employeesLink.getAffordances()), - employeesLink); - } - - @PostMapping("/employees") - public ResponseEntity newEmployee(@RequestBody Employee employee) { - - int newEmployeeId = EMPLOYEES.size(); - - EMPLOYEES.put(newEmployeeId, employee); - - return ResponseEntity.noContent() // - .location(findOne(newEmployeeId) // - .getRequiredLink(IanaLinkRelations.SELF) // - .toUri()) // - .build(); - } - - @PutMapping("/employees/{id}") - public ResponseEntity updateEmployee(@RequestBody Employee employee, @PathVariable Integer id) { - - EMPLOYEES.put(id, employee); - - return ResponseEntity // - .noContent() // - .location(findOne(id) // - .getRequiredLink(IanaLinkRelations.SELF) // - .toUri()) // - .build(); - } - - @PatchMapping("/employees/{id}") - public ResponseEntity partiallyUpdateEmployee(@RequestBody Employee employee, @PathVariable Integer id) { - - Employee newEmployee = EMPLOYEES.get(id); - - if (employee.getName() != null) { - newEmployee = newEmployee.withName(employee.getName()); - } - - if (employee.getRole() != null) { - newEmployee = newEmployee.withRole(employee.getRole()); - } - - EMPLOYEES.put(id, newEmployee); - - return ResponseEntity // - .noContent() // - .location(findOne(id) // - .getRequiredLink(IanaLinkRelations.SELF) // - .toUri()) // - .build(); - } - } - - @Configuration - @EnableWebMvc - @EnableHypermediaSupport(type = { HypermediaType.HAL_FORMS }) - static class TestConfig { - - @Bean - BadController employeeController() { - return new BadController(); - } - } -}