├── .gitignore
├── pom.xml
└── src
├── main
├── java
│ └── org
│ │ └── springframework
│ │ └── hateoas
│ │ └── sample
│ │ ├── ApplicationConfig.java
│ │ ├── SampleWebApplicationInitializer.java
│ │ ├── core
│ │ ├── Customer.java
│ │ ├── Customers.java
│ │ ├── Order.java
│ │ ├── Orders.java
│ │ └── package-info.java
│ │ ├── hateoas
│ │ ├── CustomerController.java
│ │ ├── HypermediaConfiguration.java
│ │ ├── OrderController.java
│ │ └── package-info.java
│ │ ├── package-info.java
│ │ └── web
│ │ ├── CustomerController.java
│ │ ├── OrderController.java
│ │ ├── Snippets.java
│ │ └── package-info.java
└── resources
│ └── logback.xml
└── test
└── java
└── org
└── springframework
└── hateoas
└── sample
├── AbstractWebIntegrationTest.java
├── hateoas
└── ApplicationIntegrationTest.java
└── web
└── ApplicationIntegrationTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .settings/
3 | .project
4 | .classpath
5 | .springBeans
6 | .sonar4clipse
7 | *.sonar4clipseExternals
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | org.springframework.hateoas
6 | spring-hateoas-sample
7 | 1.0.0.BUILD-SNAPSHOT
8 | war
9 |
10 | Spring HATEOAS - Sample
11 |
12 |
13 | 3.2.2.RELEASE
14 |
15 |
16 |
17 |
18 |
19 | org.springframework.hateoas
20 | spring-hateoas
21 | 0.7.0.RELEASE
22 |
23 |
24 |
25 | org.springframework
26 | spring-webmvc
27 | ${spring}
28 |
29 |
30 |
31 | org.springframework
32 | spring-web
33 | ${spring}
34 |
35 |
36 |
37 | org.springframework
38 | spring-core
39 | ${spring}
40 |
41 |
42 |
43 | org.springframework.plugin
44 | spring-plugin-core
45 | 0.8.0.RELEASE
46 |
47 |
48 |
49 | com.fasterxml.jackson.core
50 | jackson-databind
51 | 2.1.4
52 |
53 |
54 |
55 | javax.servlet
56 | javax.servlet-api
57 | 3.0.1
58 | provided
59 |
60 |
61 |
62 | org.projectlombok
63 | lombok
64 | 0.11.8
65 | provided
66 |
67 |
68 |
69 |
70 | org.slf4j
71 | jcl-over-slf4j
72 | 1.7.2
73 | runtime
74 |
75 |
76 |
77 | ch.qos.logback
78 | logback-classic
79 | 1.0.9
80 | runtime
81 |
82 |
83 |
84 |
85 | org.springframework
86 | spring-test
87 | ${spring}
88 | test
89 |
90 |
91 |
92 | junit
93 | junit
94 | 4.11
95 | test
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | org.apache.maven.plugins
105 | maven-compiler-plugin
106 | 3.0
107 |
108 | 1.7
109 | 1.7
110 |
111 |
112 |
113 |
114 | org.apache.maven.plugins
115 | maven-war-plugin
116 | 2.3
117 |
118 | false
119 |
120 |
121 |
122 |
123 | org.eclipse.jetty
124 | jetty-maven-plugin
125 | 9.0.0.v20130308
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/ApplicationConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample;
17 |
18 | import org.springframework.context.annotation.ComponentScan;
19 | import org.springframework.context.annotation.Configuration;
20 | import org.springframework.http.MediaType;
21 | import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
22 | import org.springframework.web.servlet.config.annotation.EnableWebMvc;
23 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
24 |
25 | /**
26 | * Spring JavaConfig configuration class. Enabling component scanning and basic Spring MVC configuration.
27 | *
28 | * @author Oliver Gierke
29 | */
30 | @Configuration
31 | @ComponentScan
32 | @EnableWebMvc
33 | class ApplicationConfig extends WebMvcConfigurerAdapter {
34 |
35 | /*
36 | * (non-Javadoc)
37 | * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#configureContentNegotiation(org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer)
38 | */
39 | @Override
40 | public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
41 | configurer.defaultContentType(MediaType.APPLICATION_JSON);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/SampleWebApplicationInitializer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample;
17 |
18 | import org.springframework.web.WebApplicationInitializer;
19 | import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
20 |
21 | /**
22 | * {@link WebApplicationInitializer} to bootstrap the app as Servlet 3 application.
23 | *
24 | * @author Oliver Gierke
25 | */
26 | public class SampleWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
27 |
28 | /*
29 | * (non-Javadoc)
30 | * @see org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#getRootConfigClasses()
31 | */
32 | @Override
33 | protected Class>[] getRootConfigClasses() {
34 | return null;
35 | }
36 |
37 | /* (non-Javadoc)
38 | * @see org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#getServletConfigClasses()
39 | */
40 | @Override
41 | protected Class>[] getServletConfigClasses() {
42 | return new Class>[] { ApplicationConfig.class };
43 | }
44 |
45 | /*
46 | * (non-Javadoc)
47 | * @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#getServletMappings()
48 | */
49 | @Override
50 | protected String[] getServletMappings() {
51 | return new String[] { "/" };
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/core/Customer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.core;
17 |
18 | import lombok.EqualsAndHashCode;
19 | import lombok.Getter;
20 | import lombok.RequiredArgsConstructor;
21 |
22 | /**
23 | * Customer domain class.
24 | *
25 | * @author Oliver Gierke
26 | */
27 | @Getter
28 | @RequiredArgsConstructor
29 | @EqualsAndHashCode(of = "id")
30 | public class Customer {
31 |
32 | private final Long id;
33 | private final String firstname, lastname;
34 |
35 | /**
36 | * Returns whether the {@link Customer} has the given id.
37 | *
38 | * @param id
39 | * @return
40 | */
41 | public boolean hasId(Long id) {
42 |
43 | return this.id.equals(id);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/core/Customers.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.core;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import org.springframework.stereotype.Repository;
22 |
23 | /**
24 | * Simple repository abstraction for {@link Customer}s.
25 | *
26 | * @author Oliver Gierke
27 | */
28 | public interface Customers {
29 |
30 | /**
31 | * Returns all {@link Customer}s.
32 | *
33 | * @return
34 | */
35 | List findAll();
36 |
37 | /**
38 | * Finds a particular {@link Customer} with the given id or {@literal null} in case no Customer is available with the
39 | * given id.
40 | *
41 | * @param id
42 | * @return
43 | */
44 | Customer findOne(Long id);
45 |
46 | /**
47 | * Basic in-memory implementation of {@link Customers}.
48 | *
49 | * @author Oliver Gierke
50 | */
51 | @Repository
52 | static class InMemoryCustomers implements Customers {
53 |
54 | private final List customers = new ArrayList();
55 |
56 | public InMemoryCustomers() {
57 | customers.add(new Customer(1L, "Dave", "Matthews"));
58 | customers.add(new Customer(2L, "Carter", "Beauford"));
59 | }
60 |
61 | /*
62 | * (non-Javadoc)
63 | * @see org.springframework.hateoas.sample.Customers#findAll()
64 | */
65 | public List findAll() {
66 | return customers;
67 | }
68 |
69 | /*
70 | * (non-Javadoc)
71 | * @see org.springframework.hateoas.sample.Customers#findOne(java.lang.Long)
72 | */
73 | public Customer findOne(Long id) {
74 |
75 | for (Customer customer : customers) {
76 | if (customer.hasId(id)) {
77 | return customer;
78 | }
79 | }
80 |
81 | return null;
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/core/Order.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.core;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import lombok.EqualsAndHashCode;
22 | import lombok.Getter;
23 | import lombok.RequiredArgsConstructor;
24 |
25 | /**
26 | * Simple order entity.
27 | *
28 | * @author Oliver Gierke
29 | */
30 | @Getter
31 | @RequiredArgsConstructor
32 | @EqualsAndHashCode(of = "id")
33 | public class Order {
34 |
35 | private final Long id;
36 | private final Customer customer;
37 | private final List lineItems = new ArrayList();
38 |
39 | /**
40 | * Returns whether the Order has the given id.
41 | *
42 | * @param id
43 | * @return
44 | */
45 | public boolean hasId(Long id) {
46 | return this.id.equals(id);
47 | }
48 |
49 | /**
50 | * Returns whether the {@link Order} belongs to the given {@link Customer}.
51 | *
52 | * @param customer
53 | * @return
54 | */
55 | public boolean belongsTo(Customer customer) {
56 | return this.customer.equals(customer);
57 | }
58 |
59 | /**
60 | * Adds the given {@link LineItem} to the {@link Order}.
61 | *
62 | * @param item
63 | * @return
64 | */
65 | public Order add(LineItem item) {
66 | this.lineItems.add(item);
67 | return this;
68 | }
69 |
70 | @Getter
71 | @RequiredArgsConstructor
72 | public static class LineItem {
73 |
74 | private final String name;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/core/Orders.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.core;
17 |
18 | import java.util.ArrayList;
19 | import java.util.Collections;
20 | import java.util.List;
21 |
22 | import org.springframework.beans.factory.annotation.Autowired;
23 | import org.springframework.hateoas.sample.core.Order.LineItem;
24 | import org.springframework.stereotype.Repository;
25 | import org.springframework.util.Assert;
26 |
27 | /**
28 | * Simple repository to access {@link Order}s.
29 | *
30 | * @author Oliver Gierke
31 | */
32 | public interface Orders {
33 |
34 | /**
35 | * Returns all {@link Order}s.
36 | *
37 | * @return
38 | */
39 | List findAll();
40 |
41 | /**
42 | * Returns all {@link Order}s placed by the given {@link Customer}.
43 | *
44 | * @param customer
45 | * @return
46 | */
47 | List findAll(Customer customer);
48 |
49 | /**
50 | * Returns the {@link Order} with the given id.
51 | *
52 | * @param id
53 | * @return
54 | */
55 | Order findOne(Long id);
56 |
57 | /**
58 | * In-memory implementation of {@link Orders}.
59 | *
60 | * @author Oliver Gierke
61 | */
62 | @Repository
63 | static class InMemoryOrders implements Orders {
64 |
65 | private final List orders = new ArrayList();
66 |
67 | @Autowired
68 | public InMemoryOrders(Customers customers) {
69 |
70 | Assert.notNull(customers, "Customers must not be null!");
71 | Customer customer = customers.findOne(1L);
72 |
73 | LineItem iPad = new Order.LineItem("iPad");
74 | LineItem iPhone = new Order.LineItem("iPhone");
75 |
76 | Order order = new Order(1L, customer);
77 | order.add(iPhone).add(iPad);
78 |
79 | this.orders.add(order);
80 | }
81 |
82 | /*
83 | * (non-Javadoc)
84 | * @see org.springframework.hateoas.sample.Orders#findAll()
85 | */
86 | public List findAll() {
87 | return Collections.unmodifiableList(orders);
88 | }
89 |
90 | /*
91 | * (non-Javadoc)
92 | * @see org.springframework.hateoas.sample.Orders#findAll(org.springframework.hateoas.sample.Customer)
93 | */
94 | public List findAll(Customer customer) {
95 |
96 | List result = new ArrayList();
97 |
98 | for (Order order : orders) {
99 | if (order.belongsTo(customer)) {
100 | result.add(order);
101 | }
102 | }
103 |
104 | return Collections.unmodifiableList(result);
105 | }
106 |
107 | /*
108 | * (non-Javadoc)
109 | * @see org.springframework.hateoas.sample.Orders#findOne(java.lang.Long)
110 | */
111 | public Order findOne(Long id) {
112 |
113 | for (Order order : orders) {
114 | if (order.hasId(id)) {
115 | return order;
116 | }
117 | }
118 | return null;
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/core/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Core domain abstractions.
3 | */
4 | package org.springframework.hateoas.sample.core;
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/hateoas/CustomerController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.hateoas;
17 |
18 | import lombok.NonNull;
19 | import lombok.RequiredArgsConstructor;
20 |
21 | import org.springframework.beans.factory.annotation.Autowired;
22 | import org.springframework.context.annotation.Profile;
23 | import org.springframework.hateoas.EntityLinks;
24 | import org.springframework.hateoas.ExposesResourceFor;
25 | import org.springframework.hateoas.Resource;
26 | import org.springframework.hateoas.Resources;
27 | import org.springframework.hateoas.sample.core.Customer;
28 | import org.springframework.hateoas.sample.core.Customers;
29 | import org.springframework.http.HttpEntity;
30 | import org.springframework.http.HttpStatus;
31 | import org.springframework.http.ResponseEntity;
32 | import org.springframework.stereotype.Controller;
33 | import org.springframework.web.bind.annotation.PathVariable;
34 | import org.springframework.web.bind.annotation.RequestMapping;
35 | import org.springframework.web.bind.annotation.RequestMethod;
36 |
37 | /**
38 | * @author Oliver Gierke
39 | */
40 | @Controller
41 | @Profile("hateoas")
42 | @RequestMapping("/customers")
43 | @ExposesResourceFor(Customer.class)
44 | @RequiredArgsConstructor(onConstructor = @_(@Autowired))
45 | public class CustomerController {
46 |
47 | private final @NonNull Customers customers;
48 | private final @NonNull EntityLinks entityLinks;
49 |
50 | @RequestMapping(method = RequestMethod.GET)
51 | HttpEntity> showCustomers() {
52 |
53 | Resources resources = new Resources<>(customers.findAll());
54 | resources.add(entityLinks.linkToCollectionResource(Customer.class));
55 |
56 | return new ResponseEntity<>(resources, HttpStatus.OK);
57 | }
58 |
59 | @RequestMapping(value = "/{id}", method = RequestMethod.GET)
60 | HttpEntity> showCustomer(@PathVariable Long id) {
61 |
62 | Resource resource = new Resource<>(customers.findOne(id));
63 | resource.add(entityLinks.linkToSingleResource(Customer.class, id));
64 |
65 | return new ResponseEntity<>(resource, HttpStatus.OK);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/hateoas/HypermediaConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.hateoas;
17 |
18 | import org.springframework.context.annotation.Configuration;
19 | import org.springframework.context.annotation.Profile;
20 | import org.springframework.hateoas.config.EnableHypermediaSupport;
21 | import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
22 |
23 | /**
24 | * Separate configuration class to enable Spring Hateoas functionality if the {@code hateoas} profile is activated.
25 | *
26 | * @author Oliver Gierke
27 | */
28 | @Configuration
29 | @Profile("hateoas")
30 | @EnableHypermediaSupport(type = HypermediaType.HAL)
31 | class HypermediaConfiguration {
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/hateoas/OrderController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.hateoas;
17 |
18 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
19 |
20 | import java.util.ArrayList;
21 | import java.util.List;
22 |
23 | import lombok.Getter;
24 | import lombok.NonNull;
25 | import lombok.RequiredArgsConstructor;
26 |
27 | import org.springframework.beans.factory.annotation.Autowired;
28 | import org.springframework.context.annotation.Profile;
29 | import org.springframework.hateoas.Resource;
30 | import org.springframework.hateoas.ResourceSupport;
31 | import org.springframework.hateoas.Resources;
32 | import org.springframework.hateoas.sample.core.Customer;
33 | import org.springframework.hateoas.sample.core.Customers;
34 | import org.springframework.hateoas.sample.core.Order;
35 | import org.springframework.hateoas.sample.core.Order.LineItem;
36 | import org.springframework.hateoas.sample.core.Orders;
37 | import org.springframework.http.HttpEntity;
38 | import org.springframework.http.HttpHeaders;
39 | import org.springframework.http.HttpStatus;
40 | import org.springframework.http.ResponseEntity;
41 | import org.springframework.stereotype.Controller;
42 | import org.springframework.web.bind.annotation.PathVariable;
43 | import org.springframework.web.bind.annotation.RequestMapping;
44 |
45 | /**
46 | * @author Oliver Gierke
47 | */
48 | @Controller
49 | @Profile("hateoas")
50 | @RequiredArgsConstructor(onConstructor = @_(@Autowired))
51 | public class OrderController {
52 |
53 | private final @NonNull Orders orders;
54 | private final @NonNull Customers customers;
55 |
56 | /**
57 | * Exposes a collection resource for {@link Order}s.
58 | *
59 | * @return
60 | */
61 | @RequestMapping("/orders")
62 | HttpEntity> showOrders() {
63 |
64 | Resources orders = new Resources<>(this.orders.findAll());
65 | orders.add(linkTo(methodOn(OrderController.class).showOrders()).withSelfRel());
66 |
67 | return new ResponseEntity<>(orders, HttpStatus.OK);
68 | }
69 |
70 | /**
71 | * Exposes a single {@link Order} resource.
72 | *
73 | * @param id
74 | * @return
75 | */
76 | @RequestMapping("/orders/{id}")
77 | HttpEntity> showOrder(@PathVariable Long id) {
78 |
79 | Resource order = new Resource(orders.findOne(id));
80 | order.add(linkTo(methodOn(OrderController.class).showOrder(id)).withSelfRel());
81 |
82 | return new ResponseEntity>(order, HttpStatus.OK);
83 | }
84 |
85 | /**
86 | * Exposes all {@link Order}s for {@link Customer}s.
87 | *
88 | * @param id
89 | * @return
90 | */
91 | @RequestMapping("/customers/{id}/orders")
92 | HttpEntity> showCustomerOrders(@PathVariable Long id) {
93 |
94 | Customer customer = customers.findOne(id);
95 |
96 | if (customer == null) {
97 | return new ResponseEntity<>(HttpStatus.OK);
98 | }
99 |
100 | List orderResources = new ArrayList<>();
101 |
102 | for (Order order : orders.findAll(customer)) {
103 |
104 | OrderResource resource = new OrderResource(order.getLineItems());
105 | resource.add(linkTo(methodOn(OrderController.class).showOrder(order.getId())).withSelfRel());
106 | resource.add(linkTo(methodOn(CustomerController.class).showCustomer(id)).withRel("customer"));
107 |
108 | orderResources.add(resource);
109 | }
110 |
111 | Resources resources = new Resources<>(orderResources);
112 | resources.add(linkTo(methodOn(OrderController.class).showCustomerOrders(id)).withSelfRel());
113 |
114 | HttpHeaders headers = new HttpHeaders();
115 | headers.add("Link", linkTo(methodOn(OrderController.class).showCustomerOrders(id)).withSelfRel().toString());
116 |
117 | return new ResponseEntity<>(resources, headers, HttpStatus.OK);
118 | }
119 |
120 | /**
121 | * DTO for {@link Order}s.
122 | *
123 | * @author Oliver Gierke
124 | */
125 | @RequiredArgsConstructor
126 | @Getter
127 | private static class OrderResource extends ResourceSupport {
128 |
129 | private final List lineItems;
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/hateoas/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Controller classes using Spring HATEOAS.
3 | */
4 | package org.springframework.hateoas.sample.hateoas;
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Spring and web application configuration files.
3 | */
4 | package org.springframework.hateoas.sample;
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/web/CustomerController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.web;
17 |
18 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
19 |
20 | import java.util.List;
21 |
22 | import lombok.NonNull;
23 | import lombok.RequiredArgsConstructor;
24 |
25 | import org.springframework.beans.factory.annotation.Autowired;
26 | import org.springframework.context.annotation.Profile;
27 | import org.springframework.hateoas.Resource;
28 | import org.springframework.hateoas.sample.core.Customer;
29 | import org.springframework.hateoas.sample.core.Customers;
30 | import org.springframework.http.HttpEntity;
31 | import org.springframework.http.HttpStatus;
32 | import org.springframework.http.ResponseEntity;
33 | import org.springframework.stereotype.Controller;
34 | import org.springframework.web.bind.annotation.PathVariable;
35 | import org.springframework.web.bind.annotation.RequestMapping;
36 | import org.springframework.web.bind.annotation.RequestMethod;
37 |
38 | /**
39 | * Plain Spring MVC controller implementation to expose {@link Customer}s.
40 | *
41 | * @author Oliver Gierke
42 | */
43 | @Controller
44 | @Profile("web")
45 | @RequestMapping("/customers")
46 | @RequiredArgsConstructor(onConstructor = @_(@Autowired))
47 | public class CustomerController {
48 |
49 | private final @NonNull Customers customers;
50 |
51 | /**
52 | * Exposes a single {@link Customer}.
53 | *
54 | * @param id
55 | * @return
56 | */
57 | @RequestMapping(value = "/{id}", method = RequestMethod.GET)
58 | HttpEntity> showCustomer(@PathVariable Long id) {
59 |
60 | Resource resource = new Resource<>(customers.findOne(id));
61 | resource.add(linkTo(methodOn(CustomerController.class).showCustomer(id)).withSelfRel());
62 |
63 | return new ResponseEntity<>(resource, HttpStatus.OK);
64 | }
65 |
66 | /**
67 | * Exposes all {@link Customers}.
68 | *
69 | * @return
70 | */
71 | @RequestMapping(method = RequestMethod.GET)
72 | HttpEntity> showCustomers() {
73 |
74 | List result = customers.findAll();
75 | return new ResponseEntity>(result, HttpStatus.OK);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/web/OrderController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.web;
17 |
18 | import java.util.List;
19 |
20 | import lombok.NonNull;
21 | import lombok.RequiredArgsConstructor;
22 |
23 | import org.springframework.beans.factory.annotation.Autowired;
24 | import org.springframework.context.annotation.Profile;
25 | import org.springframework.hateoas.sample.core.Customer;
26 | import org.springframework.hateoas.sample.core.Customers;
27 | import org.springframework.hateoas.sample.core.Order;
28 | import org.springframework.hateoas.sample.core.Orders;
29 | import org.springframework.http.HttpEntity;
30 | import org.springframework.http.HttpStatus;
31 | import org.springframework.http.ResponseEntity;
32 | import org.springframework.stereotype.Controller;
33 | import org.springframework.web.bind.annotation.PathVariable;
34 | import org.springframework.web.bind.annotation.RequestMapping;
35 | import org.springframework.web.bind.annotation.RequestMethod;
36 |
37 | /**
38 | * Spring MVC controller exposing {@link Order} instances directly to the web. Quite a couple of problems to note here:
39 | *
40 | *
Basically exporting the the domain model to the web 1:1. No means to control what is exposed in which way except
41 | * rendering-specific annotations on the domain classes themselves (which you wnat to avoid).
42 | *
No hypermedia elements at all. Relations to other resources exposed should rather become links in the
43 | * representation, not embedded. Every resource is "on it's own". There are no general links between the entities.
44 | *
45 | *
46 | * @author Oliver Gierke
47 | */
48 | @Controller
49 | @Profile("web")
50 | @RequiredArgsConstructor(onConstructor = @_(@Autowired))
51 | public class OrderController {
52 |
53 | private final @NonNull Orders orders;
54 | private final @NonNull Customers customers;
55 |
56 | /**
57 | * Exposes all {@link Order}s.
58 | *
59 | * @return
60 | */
61 | @RequestMapping(value = "/orders", method = RequestMethod.GET)
62 | HttpEntity> showOrders() {
63 |
64 | List result = orders.findAll();
65 | return new ResponseEntity>(result, HttpStatus.OK);
66 | }
67 |
68 | /**
69 | * Exposes an individual {@link Order}.
70 | *
71 | * @param id
72 | * @return
73 | */
74 | @RequestMapping(value = "/orders/{id}")
75 | HttpEntity showOrder(@PathVariable Long id) {
76 |
77 | Order order = orders.findOne(id);
78 | return new ResponseEntity(order, HttpStatus.OK);
79 | }
80 |
81 | /**
82 | * Exposes all {@link Order}s placed by a particular customer.
83 | *
84 | * @param id
85 | * @return
86 | */
87 | @RequestMapping("/customers/{id}/orders")
88 | HttpEntity> showCustomerOrders(@PathVariable Long id) {
89 |
90 | Customer customer = customers.findOne(id);
91 |
92 | if (customer == null) {
93 | return new ResponseEntity>(HttpStatus.NOT_FOUND);
94 | }
95 |
96 | return new ResponseEntity>(orders.findAll(customer), HttpStatus.OK);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/web/Snippets.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.web;
17 |
18 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
19 |
20 | import org.springframework.hateoas.EntityLinks;
21 | import org.springframework.hateoas.Resource;
22 | import org.springframework.hateoas.Resources;
23 | import org.springframework.hateoas.sample.core.Customer;
24 | import org.springframework.hateoas.sample.core.Customers;
25 | import org.springframework.hateoas.sample.core.Order;
26 | import org.springframework.hateoas.sample.core.Orders;
27 | import org.springframework.http.HttpEntity;
28 | import org.springframework.http.HttpStatus;
29 | import org.springframework.http.ResponseEntity;
30 | import org.springframework.web.bind.annotation.PathVariable;
31 | import org.springframework.web.bind.annotation.RequestMapping;
32 |
33 | /**
34 | * Code snippets to hypermediize the sample controllers.
35 | *
36 | * @author Oliver Gierke
37 | */
38 | public class Snippets {
39 |
40 | Customers customers;
41 | Orders orders;
42 |
43 | Resource resource;
44 | Resources resources;
45 |
46 | EntityLinks links;
47 |
48 | /**
49 | * Step 1 - Resources
50 | */
51 | HttpEntity> showCustomer(@PathVariable Long id) {
52 |
53 | Resource resource = new Resource<>(customers.findOne(id));
54 | return new ResponseEntity<>(resource, HttpStatus.OK);
55 | }
56 |
57 | /**
58 | * Step 2 - LinkBuilder
59 | */
60 | void linkBuilder(Long id) {
61 |
62 | // import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
63 | resource.add(linkTo(CustomerController.class).slash(id).withSelfRel());
64 | resource.add(linkTo(methodOn(CustomerController.class).showCustomer(id)).withSelfRel());
65 | }
66 |
67 | /**
68 | * Step 3 - EntityLinks
69 | */
70 | @RequestMapping("/customers/{id}/orders")
71 | HttpEntity> showCustomerOrders(@PathVariable Long id) {
72 |
73 | // @ExposesResourceFor(Customer.class)
74 |
75 | // @Autowired
76 | // EntityLinks links;
77 |
78 | // @EnableHypermediaSupport
79 |
80 | Customer customer = customers.findOne(id);
81 |
82 | if (customer == null) {
83 | return new ResponseEntity<>(HttpStatus.NOT_FOUND);
84 | }
85 |
86 | Resources resources = new Resources<>(orders.findAll(customer));
87 | resources.add(linkTo(methodOn(CustomerController.class).showCustomer(id)).withRel("customer"));
88 | // resources.add(links.linkForSingleResource(Customer.class, id).withRel("customer"));
89 |
90 | return new ResponseEntity<>(resources, HttpStatus.OK);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/org/springframework/hateoas/sample/web/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Controller classes using plain Spring MVC.
3 | */
4 | package org.springframework.hateoas.sample.web;
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 | %d %5p %40.40c:%4L - %m%n
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/test/java/org/springframework/hateoas/sample/AbstractWebIntegrationTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample;
17 |
18 | import static org.hamcrest.CoreMatchers.*;
19 | import static org.junit.Assert.*;
20 |
21 | import org.junit.Before;
22 | import org.junit.Test;
23 | import org.junit.runner.RunWith;
24 | import org.springframework.beans.factory.annotation.Autowired;
25 | import org.springframework.test.context.ContextConfiguration;
26 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
27 | import org.springframework.test.context.web.WebAppConfiguration;
28 | import org.springframework.test.web.servlet.MockMvc;
29 | import org.springframework.test.web.servlet.setup.MockMvcBuilders;
30 | import org.springframework.web.context.WebApplicationContext;
31 |
32 | /**
33 | * Base class setting up Spring MVC integration testing bootstrapping the core application configuration.
34 | *
35 | * @author Oliver Gierke
36 | */
37 | @RunWith(SpringJUnit4ClassRunner.class)
38 | @WebAppConfiguration
39 | @ContextConfiguration(classes = ApplicationConfig.class)
40 | public abstract class AbstractWebIntegrationTest {
41 |
42 | @Autowired
43 | WebApplicationContext context;
44 |
45 | protected MockMvc mvc;
46 |
47 | @Before
48 | public void setUp() {
49 | this.mvc = MockMvcBuilders.webAppContextSetup(context).build();
50 | }
51 |
52 | @Test
53 | public void bootstrapsWebApp() {
54 | assertThat(mvc, is(notNullValue()));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/java/org/springframework/hateoas/sample/hateoas/ApplicationIntegrationTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.hateoas;
17 |
18 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
19 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
20 |
21 | import org.junit.Test;
22 | import org.springframework.hateoas.sample.AbstractWebIntegrationTest;
23 | import org.springframework.test.context.ActiveProfiles;
24 |
25 | /**
26 | * Web integration test using the {@code hateoas} profile.
27 | *
28 | * @author Oliver Gierke
29 | */
30 | @ActiveProfiles("hateoas")
31 | public class ApplicationIntegrationTest extends AbstractWebIntegrationTest {
32 |
33 | @Test
34 | public void foo() throws Exception {
35 | mvc.perform(get("/customers/1")).andExpect(status().isOk());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/org/springframework/hateoas/sample/web/ApplicationIntegrationTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.hateoas.sample.web;
17 |
18 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
19 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
20 |
21 | import org.junit.Test;
22 | import org.springframework.hateoas.sample.AbstractWebIntegrationTest;
23 | import org.springframework.test.context.ActiveProfiles;
24 |
25 | /**
26 | * Web integration test using the {@code web} profile.
27 | *
28 | * @author Oliver Gierke
29 | */
30 | @ActiveProfiles("web")
31 | public class ApplicationIntegrationTest extends AbstractWebIntegrationTest {
32 |
33 | @Test
34 | public void foo() throws Exception {
35 | mvc.perform(get("/customers/1")).andExpect(status().isOk());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------