|
|
|
|
|
|
1
|
-Getting Started: Creating a REST Endpoint
|
|
|
|
2
|
-=========================================
|
|
|
|
|
|
1
|
+Getting Started: Creating a REST Service
|
|
|
|
2
|
+========================================
|
|
3
|
|
3
|
|
|
4
|
-This Getting Started guide will walk you through the process of creating a simple REST endpoint using Spring.
|
|
|
|
|
|
4
|
+This Getting Started guide will walk you through the process of creating a simple REST service using Spring.
|
|
5
|
|
5
|
|
|
6
|
To help you get started, we've provided an initial project structure for you in GitHub:
|
6
|
To help you get started, we've provided an initial project structure for you in GitHub:
|
|
7
|
|
7
|
|
|
|
|
|
|
|
15
|
$ git clone -b completed https://github.com/springframework-meta/gs-rest-service.git
|
15
|
$ git clone -b completed https://github.com/springframework-meta/gs-rest-service.git
|
|
16
|
```
|
16
|
```
|
|
17
|
|
17
|
|
|
18
|
-Before we can write the REST endpoint itself, there's some initial project setup that's required. Or, you can skip straight to the [fun part]().
|
|
|
|
|
|
18
|
+Before we can write the REST service itself, there's some initial project setup that's required. Or, you can skip straight to the [fun part]().
|
|
19
|
|
19
|
|
|
20
|
Selecting Dependencies
|
20
|
Selecting Dependencies
|
|
21
|
----------------------
|
21
|
----------------------
|
|
22
|
-The sample in this Getting Started Guide will leverage Spring MVC and the Jackson JSON processor. Therefore, you'll need to declare the following library dependencies in your build:
|
|
|
|
|
|
22
|
+The sample in this Getting Started Guide will leverage Spring MVC and the Jackson JSON processor. Therefore, the following library dependencies are needed in the project's build configuration:
|
|
23
|
|
23
|
|
|
24
|
- org.springframework:spring-webmvc:3.2.2.RELEASE
|
24
|
- org.springframework:spring-webmvc:3.2.2.RELEASE
|
|
25
|
- com.fasterxml.jackson.core:jackson-core:2.1.4
|
25
|
- com.fasterxml.jackson.core:jackson-core:2.1.4
|
|
26
|
|
26
|
|
|
27
|
-Click here for details on how to map these dependencies to your specific build tool.
|
|
|
|
|
|
27
|
+Refer to the [Gradle Getting Started Guide]() or the [Maven Getting Started Guide]() for details on how to include these dependencies in your build.
|
|
28
|
|
28
|
|
|
29
|
Setting Up DispatcherServlet
|
29
|
Setting Up DispatcherServlet
|
|
30
|
----------------------------
|
30
|
----------------------------
|
|
31
|
-Spring REST endpoints are built as Spring MVC controllers. Therefore, we'll need to be sure that Spring's DispatcherServlet is configured. We can do that by creating a web application initializer class:
|
|
|
|
|
|
31
|
+Spring REST services are built as Spring MVC controllers. Therefore, we'll need to be sure that Spring's [`DispatcherServlet`](http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html) is configured. We can do that by creating a web application initializer class:
|
|
32
|
|
32
|
|
|
33
|
```java
|
33
|
```java
|
|
34
|
package hello;
|
34
|
package hello;
|
|
|
|
|
|
|
55
|
}
|
55
|
}
|
|
56
|
```
|
56
|
```
|
|
57
|
|
57
|
|
|
58
|
-By extending AbstractAnnotationConfigDispatcherServletInitializer, our web application initializer will get a DispatcherServlet that is configured with @Configuration-annotated classes. All we must do is tell it where those configuration classes are and what path(s) to map DispatcherServlet to.
|
|
|
|
|
|
58
|
+By extending [`AbstractAnnotationConfigDispatcherServletInitializer`](http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/servlet/support/AbstractAnnotationConfigDispatcherServletInitializer.html), our web application initializer will get a `DispatcherServlet` that is configured with [`@Configuration`](http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/context/annotation/Configuration.html)-annotated classes. All we must do is tell it where those configuration classes are and what path(s) to map `DispatcherServlet` to.
|
|
59
|
|
59
|
|
|
60
|
-With regard to the servlet path mappings, getServletMappings() returns a single-entry array of String specifying that DispatcherServlet should be mapped to "/".
|
|
|
|
|
|
60
|
+With regard to the servlet path mappings, `getServletMappings()` returns a single-entry array of `String` specifying that `DispatcherServlet` should be mapped to "/".
|
|
61
|
|
61
|
|
|
62
|
-The getRootConfigClasses() and getServletConfigClasses() methods specify the configuration classes. The Class array returned from getRootConfigClasses() specifies the classes for the root context provided to ContextLoaderListener. Similarly, the Class array returned from getServletConfigClasses() specifies the classes for the servlet application context provided to DispatcherServlet.
|
|
|
|
|
|
62
|
+The `getRootConfigClasses()` and `getServletConfigClasses()` methods specify the configuration classes. The `Class` array returned from `getRootConfigClasses()` specifies the classes for the root context provided to [`ContextLoaderListener`](http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/context/ContextLoaderListener.html). Similarly, the `Class` array returned from `getServletConfigClasses()` specifies the classes for the servlet application context provided to `DispatcherServlet`.
|
|
63
|
|
63
|
|
|
64
|
-For our purposes there will only be a servlet application context, so getRootConfigClasses() returns null. getServletConfigClasses(), however, specifies HelloWorldConfiguration as the only configuration class.
|
|
|
|
|
|
64
|
+For our purposes there will only be a servlet application context, so `getRootConfigClasses()` returns `null`. `getServletConfigClasses()`, however, specifies `HelloWorldConfiguration` as the only configuration class.
|
|
65
|
|
65
|
|
|
66
|
Creating a Configuration Class
|
66
|
Creating a Configuration Class
|
|
67
|
------------------------------
|
67
|
------------------------------
|
|
68
|
-Now that we have setup DispatcherServlet to handle requests for our application, we need to configure the Spring application context used by DispatcherServlet.
|
|
|
|
|
|
68
|
+Now that we have setup `DispatcherServlet` to handle requests for our application, we need to configure the Spring application context used by `DispatcherServlet`.
|
|
69
|
|
69
|
|
|
70
|
In our Spring configuration, we'll need to enable annotation-oriented Spring MVC. And we'll also need to tell Spring where it can find our endpoint controller class. The following configuration class takes care of both of those things:
|
70
|
In our Spring configuration, we'll need to enable annotation-oriented Spring MVC. And we'll also need to tell Spring where it can find our endpoint controller class. The following configuration class takes care of both of those things:
|
|
71
|
|
71
|
|
|
|
|
|
|
|
82
|
}
|
82
|
}
|
|
83
|
```
|
83
|
```
|
|
84
|
|
84
|
|
|
85
|
-The @EnableWebMvc annotation turns on annotation-oriented Spring MVC. And we've also annotated the configuration class with @ComponentScan to have it look for components (including controllers) in the hello package.
|
|
|
|
|
|
85
|
+The [`@EnableWebMvc`](http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html) annotation turns on annotation-oriented Spring MVC. And we've also annotated the configuration class with [`@ComponentScan`](http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/context/annotation/ComponentScan.html) to have it look for components (including controllers) in the `hello` package.
|
|
86
|
|
86
|
|
|
87
|
Creating a Representation Class
|
87
|
Creating a Representation Class
|
|
88
|
-------------------------------
|
88
|
-------------------------------
|
|
89
|
-With the essential Spring MVC configuration out of the way, it's time to get to the nuts and bolts of our REST endpoint by creating a resource representation class and an endpoint controller.
|
|
|
|
|
|
89
|
+With the essential Spring MVC configuration out of the way, it's time to get to the nuts and bolts of our REST service by creating a resource representation class and an endpoint controller.
|
|
90
|
|
90
|
|
|
91
|
Before we get too carried away with building the endpoint controller, we need to give some thought to what our API will look like.
|
91
|
Before we get too carried away with building the endpoint controller, we need to give some thought to what our API will look like.
|
|
92
|
|
92
|
|
|
|
|
|
|
|
99
|
}
|
99
|
}
|
|
100
|
```
|
100
|
```
|
|
101
|
|
101
|
|
|
102
|
-The id field is a unique identifier for the greeting, and content is the textual representation of the greeting.
|
|
|
|
|
|
102
|
+The `id` field is a unique identifier for the greeting, and `content` is the textual representation of the greeting.
|
|
103
|
|
103
|
|
|
104
|
To model the greeting representation, we’ll create a representation class:
|
104
|
To model the greeting representation, we’ll create a representation class:
|
|
105
|
|
105
|
|
|
|
|
|
|
|
131
|
|
131
|
|
|
132
|
Creating a Resource Controller
|
132
|
Creating a Resource Controller
|
|
133
|
------------------------------
|
133
|
------------------------------
|
|
134
|
-In Spring, REST endpoints are just Spring MVC controllers. The following Spring MVC controller handles a GET request for /hello-world and returns our Saying resource:
|
|
|
|
|
|
134
|
+In Spring, REST endpoints are just Spring MVC controllers. The following Spring MVC controller handles a GET request for /hello-world and returns our `Greeting` resource:
|
|
135
|
|
135
|
|
|
136
|
```java
|
136
|
```java
|
|
137
|
package hello;
|
137
|
package hello;
|
|
|
|
|
|
|
159
|
|
159
|
|
|
160
|
The key difference between a human-facing controller and a REST endpoint controller is in how the response is created. Rather than rely on a view (such as JSP) to render model data in HTML, an endpoint controller simply returns the data to be written directly to the body of the response.
|
160
|
The key difference between a human-facing controller and a REST endpoint controller is in how the response is created. Rather than rely on a view (such as JSP) to render model data in HTML, an endpoint controller simply returns the data to be written directly to the body of the response.
|
|
161
|
|
161
|
|
|
162
|
-The magic is in the @ResponseBody annotation. @ResponseBody tells Spring MVC to not render a model into a view, but rather to write the returned object into the response body. It does this by using one of Spring's message converters.
|
|
|
|
163
|
-
|
|
|
|
164
|
->__TODO__: briefly talk about what message converters do and list the ones that come out of the box with Spring}
|
|
|
|
165
|
-
|
|
|
|
166
|
-
|
|
|
|
167
|
-Building and Running the REST Endpoint
|
|
|
|
168
|
---------------------------------------
|
|
|
|
169
|
->**NOTE**: The following section probably needs to be reworked
|
|
|
|
170
|
- (and the build file that goes with it) to use a Servlet 3
|
|
|
|
171
|
- container (such as a modern Tomcat). At this point,
|
|
|
|
172
|
- these steps do not work since the sample code uses a
|
|
|
|
173
|
- web app initializer instead of web.xml.
|
|
|
|
174
|
-
|
|
|
|
175
|
-All of the pieces of our REST endpoint are in place. All that's left to do is to build it and run it.
|
|
|
|
176
|
-
|
|
|
|
177
|
-To run the sample, issue the following Gradle command:
|
|
|
|
178
|
-
|
|
|
|
179
|
-```sh
|
|
|
|
180
|
-$ gradle jettyRun
|
|
|
|
181
|
-```
|
|
|
|
182
|
-
|
|
|
|
183
|
-This will cause the application to be compiled and for a Jetty server to start on port 8080. You can then point your browser or other REST client (such as Spring's RestTemplate or the Spring REST Shell) at http://localhost:8080/HelloWorldRest/hello-world to see the result. Or you can try specifying a name parameter as in http://localhost:8080/HelloWorldRest/hello-world?name=Craig.
|
|
|
|
184
|
-
|
|
|
|
185
|
-If you simply want to build the code into a WAR file that you can deploy in your own server, issue the following Gradle command:
|
|
|
|
186
|
-
|
|
|
|
187
|
-```sh
|
|
|
|
188
|
-$ gradle build
|
|
|
|
189
|
-```
|
|
|
|
|
|
162
|
+The magic is in the [`@ResponseBody`](http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/bind/annotation/ResponseBody.html) annotation. `@ResponseBody` tells Spring MVC to not render a model into a view, but rather to write the returned object into the response body. It does this by using one of Spring's message converters. Because Jackson 2 is in the classpath, this means that [`MappingJackson2HttpMessageConverter`](http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.html) will handle the conversion of Greeting to JSON if the request's `Accept` header specifies that JSON should be returned.
|
|
190
|
|
163
|
|
|
|
|
164
|
+Building and Running the REST Service
|
|
|
|
165
|
+-------------------------------------
|
|
|
|
166
|
+>**NOTE**: This section is a very important section, because it shows the user how all of the work done up to this point comes together and runs. The challenge here, however, is that there's no *easy* way to run this application. Gradle's Jetty plugin seems easy and natural, but it uses an older, non-Servlet 3 version of Jetty, so the application initializer will not work. There is a Gradle Tomcat plugin, but it's quite involved setup-wise. And loading this into any IDE and running it is far more involved than either of the Gradle-based options. It would be really nice to leverage Spring Bootstrap/Catalyst for running the sample. That's likely what will happen, but at this point it's too risky of an option until bootstrap/catalyst stabilizes.
|
|
191
|
|
167
|
|
|
192
|
Next Steps
|
168
|
Next Steps
|
|
193
|
----------
|
169
|
----------
|
|
194
|
-Congratulations! You have just developed a simple REST endpoint using Spring. This is a basic foundation for building a complete REST API in Spring.
|
|
|
|
|
|
170
|
+Congratulations! You have just developed a simple REST service using Spring. This is a basic foundation for building a complete REST API in Spring.
|
|
195
|
|
171
|
|
|
196
|
-There's more to building REST APIs than is covered here. You may want to continue your exploration of Spring and REST with the following Getting Started guides:
|
|
|
|
|
|
172
|
+There's more to building REST services than is covered here. You may want to continue your exploration of Spring and REST with the following Getting Started guides:
|
|
197
|
|
173
|
|
|
198
|
-* Handling POST, PUT, and GET requests in REST endpoints
|
|
|
|
|
|
174
|
+* Handling POST, PUT, and GET requests in REST services
|
|
199
|
* Creating self-describing APIs with HATEOAS
|
175
|
* Creating self-describing APIs with HATEOAS
|
|
200
|
-* Securing a REST endpoint with HTTP Basic
|
|
|
|
201
|
-* Securing a REST endpoint with OAuth
|
|
|
|
|
|
176
|
+* Securing a REST service with HTTP Basic
|
|
|
|
177
|
+* Securing a REST service with OAuth
|
|
202
|
* Consuming REST APIs
|
178
|
* Consuming REST APIs
|
|
203
|
* Testing REST APIs
|
179
|
* Testing REST APIs
|
|
204
|
|
180
|
|