RESTful API for Game Store, developed with Spring Boot in Java.
Six RESTful APIs for the Game Store web application.
API | Description | URL |
---|---|---|
GET /api/products | Get all products | GET http://localhost:8080/api/products |
GET /api/products/{id} | Get a product by ID | GET http://localhost:8080/api/products/1 |
POST /api/products | Add a new product | POST http://localhost:8080/api/products |
PUT /api/products/{id} | Update a product | PUT http://localhost:8080/api/products/1 |
DELETE /api/products/{id} | Delete a product | DELETE http://localhost:8080/api/products/1 |
POST /api/upload | Upload an image | POST http://localhost:8080/api/upload |
git clone https://github.com/jojozhuang/restful-api-springboot.git
Build and bootRun.
Access http://localhost:8080/api/products in web browser or PostMan, you should get the following JSON as response.
[
{
"id":3,
"productName":"Wireless Controller",
"price":19.99,
"image":"http://localhost:8080/images/controller.jpg"
},
{
"id":2,
"productName":"Wii",
"price":269.0,
"image":"http://localhost:8080/images/wii.jpg"
},
{
"id":1,
"productName":"Xbox 360",
"price":299.0,
"image":"http://localhost:8080/images/xbox360.jpg"
}
]
Change base url of images. Edit application.properties
file, set spring.profiles.active
to prod
.
spring.profiles.active=prod
Then, restart the app. In addition, you can also run the app in production mode with java -jar
. First, package the app.
mvn package
Then, launch the application with java -jar
and append --spring.profiles.active=prod
.
java -jar target/restful-spring-boot-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
Add Config Vars
to enable production mode in heroku. Go to https://dashboard.heroku.com/apps/game-store-springboot/settings, add key value as follows.
- KEY: SPRING_PROFILES_ACTIVE
- VALUE: prod
The available RESTful API on Heroku is
For example, request https://game-store-springboot.herokuapp.com/api/products to get all products.
Build
./gradlew build
Create manifest.yml, deploy with jre 11.
applications:
- name: game-store-springboot
memory: 800MB
path: build/libs/game-store-springboot-0.0.1-SNAPSHOT.jar
buildpacks:
- https://github.com/cloudfoundry/java-buildpack.git
env:
# see https://github.tools.sap/cloud-curriculum/materials/blob/main/cloud-platforms/cloud-foundry/java-memory-allocation.md
JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 11.+}, memory_calculator: { stack_threads: 200 }}'
MALLOC_ARENA_MAX: 4
Push to cf with random route.
cf push --random-route
Create postgresql database service on cf.
cf create-service postgresql-db trial game-store-db
Check cf service.
cf services
Update manifest.yml by adding database service.
applications:
- name: game-store-springboot
memory: 800MB
path: build/libs/game-store-springboot-0.0.1-SNAPSHOT.jar
buildpacks:
- https://github.com/cloudfoundry/java-buildpack.git
env:
# see https://github.tools.sap/cloud-curriculum/materials/blob/main/cloud-platforms/cloud-foundry/java-memory-allocation.md
JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 11.+}, memory_calculator: { stack_threads: 200 }}'
MALLOC_ARENA_MAX: 4
services:
- game-store-db
Push to cf.
cf push
Bind service
cf bind-service game-store-springboot game-store-db
Ensure your env variable changes take effect.
cf restage game-store-springboot
https://github.com/SAP/cf-java-logging-support
Use cf-java-logging-support
to enhance log messages with metadata extracted from HTTP headers of incoming requests.
<properties>
<cf-logging-version>3.3.0</cf-logging-version>
</properties>
<dependency>
<groupId>com.sap.hcp.cf.logging</groupId>
<artifactId>cf-java-logging-support-logback</artifactId>
<version>${cf-logging-version}</version>
</dependency>
Forward the Correlation ID obtained from LogContext.getCorrelationId()
in your restTemplate for outgoing requests.
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add((request, body, execution) -> {
request.getHeaders().set(HttpHeaders.CORRELATION_ID.getName(), LogContext.getCorrelationId());
return execution.execute(request, body);
});
return restTemplate;
}
Test locally. Trigger any api, you should see the correlation_id
attribute in the log.
"correlation_id":"8720dd36-bc3b-40ce-8783-dbacbad23da1"
This id is from the X-CorrelationID
attribute of the http request header. You can find it in postman.
Push to cf, Build.
mvn package
Push to cf.
cf push
Create an instance of the application-logs
service with the name app-logs
.
cf create-service application-logs lite app-logs
Bind the logging service to app bulletinboard-ads
.
cf bind-service bulletinboard-ads app-logs
Ensure your env variable changes take effect.
cf restage bulletinboard-ads
Test
Call api in postman. Note down the value of x-correlationid
or vcap_request_id
in header, eg. "6aa0528c-b1c6-4de1-4c6a-3c6af618b4ff".
curl --location --request GET 'https://game-store-springboot-chatty-vicuna-nj.cfapps.us10.hana.ondemand.com/api/products'
Then open https://logs.cf.us10.hana.ondemand.com in your browser. You may need to sign in, but afterwards you should be seeing a Kibana dashboard.
You should see correlation_id
in the latest log. And its value is "6aa0528c-b1c6-4de1-4c6a-3c6af618b4ff".
curl --location --request GET 'https://game-store-springboot-chatty-vicuna-nj.cfapps.us10.hana.ondemand.com/api/products'
Inspect the environment of your app.
cf env game-store-springboot
Check the logs.
cf logs game-store-springboot --recent
Remove binding
cf unbind-service game-store-springboot game-store-db
Delete service
cf delete-service game-store-db
Recreate database service
cf create-service postgresql-db trial game-store-db
cf bind-service game-store-springboot game-store-db
Restage app
cf restage game-store-springboot
Read portfolio Game Store(Angular) or Game Store(React) to learn how these RESTful APIs are consumed by Angular and React applications.
Read tutorial Building RESTful API with Spring Boot to learn how this RESTful API is built.
./gradlew build sonarqube --info
- Run with
--stacktrace
option to get the stack trace. - Run with
--debug
option to get more log output. - Run with
--scan
to get full insights.