diff --git a/spring-boot-samples/pom.xml b/spring-boot-samples/pom.xml index 9dd8a0cec1..55851b7721 100644 --- a/spring-boot-samples/pom.xml +++ b/spring-boot-samples/pom.xml @@ -36,6 +36,7 @@ spring-boot-sample-data-rest spring-boot-sample-data-solr spring-boot-sample-flyway + spring-boot-sample-hateoas spring-boot-sample-hornetq spring-boot-sample-integration spring-boot-sample-jersey diff --git a/spring-boot-samples/spring-boot-sample-hateoas/pom.xml b/spring-boot-samples/spring-boot-sample-hateoas/pom.xml new file mode 100644 index 0000000000..5a9a8477bc --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hateoas/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-samples + 1.1.11.BUILD-SNAPSHOT + + spring-boot-sample-hateoas + Spring Boot Hateoas Sample + Spring Boot Hateoas Sample + http://projects.spring.io/spring-boot/ + + Pivotal Software, Inc. + http://www.spring.io + + + ${basedir}/../.. + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.hateoas + spring-hateoas + + + org.springframework.plugin + spring-plugin-core + 1.1.0.RELEASE + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/SampleHateoasApplication.java b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/SampleHateoasApplication.java new file mode 100644 index 0000000000..ff3bad1ab4 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/SampleHateoasApplication.java @@ -0,0 +1,33 @@ +/* + * Copyright 2012-2014 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 + * + * http://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 sample; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableAutoConfiguration +@ComponentScan +public class SampleHateoasApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleHateoasApplication.class, args); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/domain/Customer.java b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/domain/Customer.java new file mode 100644 index 0000000000..d978e03a20 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/domain/Customer.java @@ -0,0 +1,45 @@ +/* + * Copyright 2012-2014 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 + * + * http://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 sample.domain; + +public class Customer { + + private final Long id; + + private final String firstName; + + private final String lastName; + + public Customer(Long id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public Long getId() { + return this.id; + } + + public String getFirstName() { + return this.firstName; + } + + public String getLastName() { + return this.lastName; + } + +} diff --git a/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/domain/CustomerRepository.java b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/domain/CustomerRepository.java new file mode 100644 index 0000000000..d183b173a1 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/domain/CustomerRepository.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2014 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 + * + * http://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 sample.domain; + +import java.util.List; + +public interface CustomerRepository { + + List findAll(); + + Customer findOne(Long id); + +} diff --git a/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/domain/InMemoryCustomerRepository.java b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/domain/InMemoryCustomerRepository.java new file mode 100644 index 0000000000..ee791d2249 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/domain/InMemoryCustomerRepository.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2014 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 + * + * http://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 sample.domain; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Repository; +import org.springframework.util.ObjectUtils; + +@Repository +public class InMemoryCustomerRepository implements CustomerRepository { + + private final List customers = new ArrayList(); + + public InMemoryCustomerRepository() { + this.customers.add(new Customer(1L, "Oliver", "Gierke")); + this.customers.add(new Customer(2L, "Andy", "Wilkinson")); + this.customers.add(new Customer(2L, "Dave", "Syer")); + } + + @Override + public List findAll() { + return this.customers; + } + + @Override + public Customer findOne(Long id) { + for (Customer customer : this.customers) { + if (ObjectUtils.nullSafeEquals(customer.getId(), id)) { + return customer; + } + } + return null; + } + +} diff --git a/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/web/CustomerController.java b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/web/CustomerController.java new file mode 100644 index 0000000000..aeda87376c --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hateoas/src/main/java/sample/web/CustomerController.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2014 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 + * + * http://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 sample.web; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.hateoas.EntityLinks; +import org.springframework.hateoas.ExposesResourceFor; +import org.springframework.hateoas.Resource; +import org.springframework.hateoas.Resources; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import sample.domain.Customer; +import sample.domain.CustomerRepository; + +@Controller +@RequestMapping("/customers") +@ExposesResourceFor(Customer.class) +public class CustomerController { + + private final CustomerRepository repository; + + private final EntityLinks entityLinks; + + @Autowired + public CustomerController(CustomerRepository repository, EntityLinks entityLinks) { + this.repository = repository; + this.entityLinks = entityLinks; + } + + @RequestMapping(method = RequestMethod.GET) + HttpEntity> showCustomers() { + Resources resources = new Resources(this.repository.findAll()); + resources.add(this.entityLinks.linkToCollectionResource(Customer.class)); + return new ResponseEntity>(resources, HttpStatus.OK); + } + + @RequestMapping(value = "/{id}", method = RequestMethod.GET) + HttpEntity> showCustomer(@PathVariable Long id) { + Resource resource = new Resource(this.repository.findOne(id)); + resource.add(this.entityLinks.linkToSingleResource(Customer.class, id)); + return new ResponseEntity>(resource, HttpStatus.OK); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-hateoas/src/test/java/sample/SampleHateoasApplicationTests.java b/spring-boot-samples/spring-boot-sample-hateoas/src/test/java/sample/SampleHateoasApplicationTests.java new file mode 100644 index 0000000000..419209b822 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hateoas/src/test/java/sample/SampleHateoasApplicationTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2014 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 + * + * http://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 sample; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SampleHateoasApplication.class) +@WebAppConfiguration +@IntegrationTest("server.port:0") +@DirtiesContext +public class SampleHateoasApplicationTests { + + @Value("${local.server.port}") + private int port; + + @Test + public void hasHalLinks() throws Exception { + ResponseEntity entity = new TestRestTemplate().getForEntity( + "http://localhost:" + this.port + "/customers/1", String.class); + assertThat(entity.getStatusCode(), equalTo(HttpStatus.OK)); + assertThat(entity.getBody(), startsWith("{\"id\":1,\"firstName\":\"Oliver\"" + + ",\"lastName\":\"Gierke\"")); + assertThat(entity.getBody(), containsString("_links\":{\"self\":{\"href\"")); + } + +}