303 lines
11 KiB
Plaintext
303 lines
11 KiB
Plaintext
:toc:
|
|
:gs-rest-service: link:/guides/gs/rest-service
|
|
:spring_version: current
|
|
:icons: font
|
|
:source-highlighter: prettify
|
|
:project_id: gs-actuator-service
|
|
|
|
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready[Spring Boot Actuator]
|
|
is a subproject of Spring Boot. It adds several production grade services to your
|
|
application with little effort on your part. In this guide, you will build an application
|
|
and then see how to add these services.
|
|
|
|
== What You Will Build
|
|
|
|
This guide takes you through creating a "`Hello, world`" RESTful web service with Spring
|
|
Boot Actuator. You will build a service that accepts the following HTTP GET request:
|
|
|
|
====
|
|
[source,sh]
|
|
----
|
|
$ curl http://localhost:9000/hello-world
|
|
----
|
|
====
|
|
|
|
It responds with the following JSON:
|
|
|
|
====
|
|
[source,json]
|
|
----
|
|
{"id":1,"content":"Hello, World!"}
|
|
----
|
|
====
|
|
|
|
There are also many features added to your application for managing the service in a
|
|
production (or other) environment. The business functionality of the service you build is
|
|
the same as in {gs-rest-service}[Building a RESTful Web Service]. You do not need to use
|
|
that guide to take advantage of this one, although it might be interesting to compare the
|
|
results.
|
|
|
|
=== What You need
|
|
|
|
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/prereq_editor_jdk_buildtools.adoc[]
|
|
|
|
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/how_to_complete_this_guide.adoc[]
|
|
|
|
[[scratch]]
|
|
== Starting with Spring Initializr
|
|
|
|
You can use this https://start.spring.io/#!type=maven-project&groupId=com.example&artifactId=actuator-service&name=actuator-service&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.actuatorservice&dependencies=web,actuator[pre-initialized project] and click Generate to download a ZIP file. This project is configured to fit the examples in this tutorial.
|
|
|
|
To manually initialize the project:
|
|
|
|
. Navigate to https://start.spring.io.
|
|
This service pulls in all the dependencies you need for an application and does most of the setup for you.
|
|
. Choose either Gradle or Maven and the language you want to use. This guide assumes that you chose Java.
|
|
. Click *Dependencies* and select *Spring Web* and *Spring Boot Actuator*.
|
|
. Click *Generate*.
|
|
. Download the resulting ZIP file, which is an archive of a web application that is configured with your choices.
|
|
|
|
NOTE: If your IDE has the Spring Initializr integration, you can complete this process from your IDE.
|
|
|
|
NOTE: You can also fork the project from Github and open it in your IDE or other editor.
|
|
|
|
== Run the Empty Service
|
|
|
|
The Spring Initializr creates an empty application that you can use to get started. The
|
|
following shows the class created by the Spring Initializr:
|
|
|
|
====
|
|
[source,java,tabsize=2]
|
|
----
|
|
include::initial/src/main/java/com/example/actuatorservice/ActuatorServiceApplication.java[]
|
|
----
|
|
====
|
|
|
|
The `@SpringBootApplication` annotation provides a load of defaults (like the embedded
|
|
servlet container), depending on the contents of your classpath and other things. It also
|
|
turns on Spring MVC's `@EnableWebMvc` annotation, which activates web endpoints.
|
|
|
|
There are no endpoints defined in this application, but there is enough to launch things
|
|
and see some of Actuator's features. The `SpringApplication.run()` command knows how to
|
|
launch the web application. All you need to do is run the following command:
|
|
|
|
====
|
|
[source,bash,subs="attributes"]
|
|
----
|
|
$ ./gradlew clean build && java -jar build/libs/{project_id}-0.0.1-SNAPSHOT.jar
|
|
----
|
|
====
|
|
|
|
You have yet to write any code, so what is happening? To see the answer, wait for the
|
|
server to start, open another terminal, and try the following command (shown with its
|
|
output):
|
|
|
|
====
|
|
[source,bash]
|
|
----
|
|
$ curl localhost:8080
|
|
{"timestamp":1384788106983,"error":"Not Found","status":404,"message":""}
|
|
----
|
|
====
|
|
|
|
The output of the preceding command indicates that the server is running but that you have
|
|
not defined any business endpoints yet. Instead of a default container-generated HTML
|
|
error response, you see a generic JSON response from the Actuator `/error` endpoint. You
|
|
can see in the console logs from the server startup which endpoints are provided out of
|
|
the box. You can try a few of those endpoints, including the `/health` endpoint. The
|
|
following example shows how to do so:
|
|
|
|
====
|
|
[source,bash]
|
|
----
|
|
$ curl localhost:8080/actuator/health
|
|
{"status":"UP"}
|
|
----
|
|
====
|
|
|
|
The status is `UP`, so the actuator service is running.
|
|
|
|
See Spring Boot's
|
|
https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator[Actuator Project]
|
|
for more details.
|
|
|
|
[[initial]]
|
|
== Create a Representation Class
|
|
|
|
First, you need to give some thought to what your API will look like.
|
|
|
|
You want to handle GET requests for `/hello-world`, optionally with a name query
|
|
parameter. In response to such a request, you want to send back JSON, representing a
|
|
greeting, that looks something like the following:
|
|
|
|
====
|
|
[source,json]
|
|
----
|
|
{
|
|
"id": 1,
|
|
"content": "Hello, World!"
|
|
}
|
|
----
|
|
====
|
|
|
|
The `id` field is a unique identifier for the greeting, and `content` contains the textual
|
|
representation of the greeting.
|
|
|
|
To model the greeting representation, create a representation class. The following listing
|
|
(from `src/main/java/com/example/actuatorservice/Greeting.java`) shows the `Greeting`
|
|
class:
|
|
|
|
====
|
|
[source,java,tabsize=2]
|
|
----
|
|
include::complete/src/main/java/com/example/actuatorservice/Greeting.java[]
|
|
----
|
|
====
|
|
|
|
Now that you need to create the endpoint controller that will serve the representation
|
|
class.
|
|
|
|
== Create a Resource Controller
|
|
|
|
In Spring, REST endpoints are Spring MVC controllers. The following Spring MVC controller
|
|
(from `src/main/java/com/example/actuatorservice/HelloWorldController.java`) handles a GET
|
|
request for the `/hello-world` endpoint and returns the `Greeting` resource:
|
|
|
|
====
|
|
[source,java,tabsize=2]
|
|
----
|
|
include::complete/src/main/java/com/example/actuatorservice/HelloWorldController.java[]
|
|
----
|
|
====
|
|
|
|
The key difference between a human-facing controller (`Controller`) and a REST endpoint
|
|
controller (`RestController`) 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 returns the data
|
|
to be written directly to the body of the response.
|
|
|
|
The response is written using one of Spring's message converters. Because Jackson is in the classpath,
|
|
https://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/http/converter/json/JacksonJsonHttpMessageConverter.html[`JacksonJsonHttpMessageConverter`]
|
|
will handle the conversion of a `Greeting` object to JSON if the request's `Accept` header
|
|
specifies that JSON should be returned.
|
|
|
|
NOTE: How do you know Jackson is on the classpath? Either run `mvn dependency:tree` or
|
|
`./gradlew dependencies`, and you get a detailed tree of dependencies that includes
|
|
Jackson. You can also see that it comes from
|
|
https://github.com/spring-projects/spring-boot/tree/main/starter/spring-boot-starter-json[/spring-boot-starter-json],
|
|
itself imported by
|
|
https://github.com/spring-projects/spring-boot/tree/main/starter/spring-boot-starter-webmvc[spring-boot-starter-webmvc].
|
|
|
|
== Run the Application
|
|
|
|
You can run the application from a custom main class or directly from one of the
|
|
configuration classes. For this simple example, you can use the `SpringApplication` helper
|
|
class. Note that this is the application class that the Spring Initializr created for you,
|
|
and you need not even modify it for it to work for this simple application. The following
|
|
listing (from `src/main/java/com/example/actuatorservice/HelloWorldApplication.java`)
|
|
shows the application class:
|
|
|
|
====
|
|
[source,java,tabsize=2]
|
|
----
|
|
include::complete/src/main/java/com/example/actuatorservice/HelloWorldApplication.java[]
|
|
----
|
|
====
|
|
|
|
In a conventional Spring MVC application, you would add `@EnableWebMvc` to turn on key
|
|
behaviors, including configuration of a `DispatcherServlet`. But Spring Boot turns on this
|
|
annotation automatically when it detects *spring-webmvc* on your classpath. This sets you
|
|
up to build a controller in an upcoming step.
|
|
|
|
The `@SpringBootApplication` annotation also brings in a
|
|
https://docs.spring.io/spring/docs/{spring_version}/javadoc-api/org/springframework/context/annotation/ComponentScan.html[`@ComponentScan`]
|
|
annotation, which tells Spring to scan the `com.example.actuatorservice` package for those
|
|
controllers (along with any other annotated component classes).
|
|
|
|
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/build_an_executable_jar_mainhead.adoc[]
|
|
|
|
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/build_an_executable_jar_with_both.adoc[]
|
|
|
|
Once the service is running (because you ran `spring-boot:run` in a terminal), you can test it by running the following command in a separate terminal:
|
|
|
|
====
|
|
[source,bash]
|
|
----
|
|
$ curl localhost:8080/hello-world
|
|
{"id":1,"content":"Hello, Stranger!"}
|
|
----
|
|
====
|
|
|
|
== Switch to a Different Server Port
|
|
|
|
Spring Boot Actuator defaults to running on port 8080. By adding an
|
|
`application.properties` file, you can override that setting. The following listing (from
|
|
`src/main/resources/application.properties`)shows that file with the necessary changes:
|
|
|
|
====
|
|
[source,properties]
|
|
----
|
|
include::complete/src/main/resources/application.properties[]
|
|
----
|
|
====
|
|
|
|
Run the server again by running the following command in a terminal:
|
|
|
|
====
|
|
[subs="attributes"]
|
|
----
|
|
$ ./gradlew clean build && java -jar build/libs/{project_id}-0.0.1-SNAPSHOT.jar
|
|
----
|
|
====
|
|
|
|
The service now starts on port 9000 and actuator endpoints on port 9001.
|
|
|
|
You can test that it is working on port 9000 by running the following commands in a
|
|
terminal:
|
|
|
|
====
|
|
[source,bash]
|
|
----
|
|
$ curl localhost:8080/hello-world
|
|
curl: (52) Empty reply from server
|
|
$ curl localhost:9000/hello-world
|
|
{"id":1,"content":"Hello, Stranger!"}
|
|
$ curl localhost:9001/actuator/health
|
|
{"status":"UP"}
|
|
----
|
|
====
|
|
|
|
== Test Your Application
|
|
|
|
To check whether your application works, you should write unit and integration tests for
|
|
your application.
|
|
The test class in
|
|
`src/test/java/com/example/actuatorservice/HelloWorldApplicationTests.java`
|
|
ensures that
|
|
|
|
* Your controller is responsive.
|
|
* Your management endpoint is responsive.
|
|
|
|
Note that the tests start the application on a random port.
|
|
The following listing shows the test class:
|
|
|
|
====
|
|
[source,java,tabsize=2]
|
|
----
|
|
include::complete/src/test/java/com/example/actuatorservice/ActuatorServiceApplicationTests.java[]
|
|
----
|
|
====
|
|
|
|
== Summary
|
|
|
|
Congratulations! You have just developed a simple RESTful service by using Spring, and you
|
|
added some useful built-in services with Spring Boot Actuator.
|
|
|
|
== See Also
|
|
|
|
The following guides may also be helpful:
|
|
|
|
* https://spring.io/guides/gs/spring-boot/[Building an Application with Spring Boot]
|
|
* https://spring.io/guides/gs/serving-web-content/[Serving Web Content with Spring MVC]
|
|
|
|
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/main/footer.adoc[]
|