- - Quick start guides
- - How Jumpydoll works
- - Tutorials
- - Java/Spring Boot tutorial
- - Step 1: Introduction
- - Step 2: Setting up the project
- - Step 3: Building the first API endpoint
- - Step 4: Storing data in MongoDB Atlas
- - Step 5: Adding more API endpoints
- - Step 6: Creating a user interface
- - Step 7: Conclusion
Step 5: Adding more API endpoints - Java/Spring Boot tutorial
In this step, you will add more methods to your TodoController to update and delete tasks
Adding an update method
A to-do list should be able to track which tasks have been completed. To do this, you'll need to be able to update the data in the task. Updates are commonly performed using the HTTP PUT method.
To add an update method, create a new method in the TodoController called updateTask. This method should accept a String called id
,
which identifies which task should be deleted. The id is generated when the item is added to MongoDB. It should also accept a Task object
containing the new data. RESTful APIs often include the ID in the URL when retrieving, deleting, and updating items. You should annotate this
method with a PutMapping, where the path is /api/tasks/{id}'. You can then read the id by annotating the id parameter with
@PathVariable("id")`.
Your new method should look like this:
@PutMapping(value = "/api/tasks/{id}", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> updateTask(@PathVariable("id") String id, @RequestBody Task task) {
// Add update code here
}
Inside the method, you'll need to check if the item if it exists. You can check if it exists by calling taskRepository.findById
, which
returns an Optional. Optional is a Java object that represents a value that may or may not exist. Compared to simply returning null, Optional
is more explicit about a return value that might not exist. You can check if the value exists by calling the .isEmpty()
method on the
returned Optional. If it is empty then return an empty response with HttpStatus.NOT_FOUND
.
If the item exists, you'll also want to check that the id in the new item matches the id in the path. If they don't match, there was
probably a mistake when sending the request so we don't want to proceed. Return an empty response with HttpStatus.BAD_REQUEST
. If the item
exists and the IDs match, then we know to proceed with the update. Set the finished
and description
fields of the existing Task to that of the new Task, and save the Task.
public ResponseEntity<?> updateTask(@PathVariable("id") String id, @RequestBody Task task) {
Optional<Task> existingTaskOptional = taskRepository.findById(id);
if (existingTaskOptional.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Task existingTask = existingTaskOptional.get();
if (!id.equals(task.getId())) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
existingTask.setDescription(task.getDescription());
existingTask.setFinished(task.isFinished());
Task savedItem = taskRepository.save(existingTask);
return new ResponseEntity<>(savedItem, HttpStatus.OK);
}
You can restart your application and test the new method using curl. Retrieve an existing item with
curl -X GET http://localhost:8080/jumpydoll-todo-list/api/tasks
Pick one task in the array and copy the JSON value. Change the value of finished
to true
. For example, your new task might look like this:
{"id":"<id_goes_here>","description":"Add and UPDATE and DELETE method","createTime":1656361195961,"finished":true}
Use curl to call the new method. Use the HTTP PUT method and pass in the new task in the body like so:
curl -X PUT http://localhost:8080/jumpydoll-todo-list/api/tasks/<id_goes_here> -H 'Content-Type: application/json' -d '{"id":"<id_goes_here>","description":"Add and UPDATE and DELETE method","createTime":1656361195961,"finished":true}'
You should see the updated item as a response. If you retrieve all the tasks again, you'll see that the updated item has now been saved.
Adding a delete method
Sometime you'll want to remove an item from the to-do list. Deletion is a very common operation in web services.
To add a delete method, create a new method in the TodoController called deleteTask
. This method should also accept id
as a string
to identify the task to be deleted. Annotate the id
parameter with @PathVariable("id")
again. Since you only need to identify the item
to delete, you don't need any other input. Annotate the deleteTask
method with a DeleteMapping, where the path
is /api/tasks/{id}
.
Your new method should look like this:
@DeleteMapping(value = "/api/tasks/{id}")
public ResponseEntity<Task> deleteTask(@PathVariable("id") String id) {
// Add deletion code here
}
Inside the method, you'll need to check if the item if it exists. You can check if it exists by calling taskRepository.findById
, which
returns an Optional. Optional is a Java object that represents a value that may or may not exist. Compared to simply returning null, Optional
is more explicit about a return value that might not exist. You can check if the value exists by calling the .isEmpty()
method on the
returned Optional. If it is empty then return an empty response with HttpStatus.NOT_FOUND
. If it does exist, call
taskRepository.delete(task.get())
to delete the item and then return an empty response with HttpStatus.OK
.
@DeleteMapping(value = "/api/tasks/{id}")
public ResponseEntity<?> deleteTask(@PathVariable("id") String id) {
Optional<Task> task = taskRepository.findById(id);
if (task.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
taskRepository.delete(task.get());
return new ResponseEntity<>(HttpStatus.OK);
}
You can test your method using curl. Retrieve an existing item with
curl -X GET http://localhost:8080/jumpydoll-todo-list/api/tasks
Pick a task and run the command below, replacing <id_goes_here>
with the ID of the item you selected.
curl -X DELETE http://localhost:8080/jumpydoll-todo-list/api/tasks/<id_goes_here>
You should get no response. If you retrieve all the tasks again, you'll see that the item you delete is no longer there.
Pushing your changes
Now that you have added all of the essential API endpoints, you've completed a good amount of work. The code works locally, but let's try running it on Jumpydoll so others can use it. To get everything set up, go to the management page of your app.
First, you'll need to set up your environment variables. Remember when you added the MongoDB connection string to the run configuration in
your IDE? We use an environment variable instead of hardcoding the value to protect the database. If the connection string was public,
other people would be able to use it and connect directly to your database, which presents a security risk. The only way people should be
able to interact with your database is through your APIs. At the bottom of the management page, you will see the "Environment variables"
section. Click the edit button, then add a key-value pair. The name should be MONGODB_CONNECTION_URI
and the value should be the MongoDB
connection string from earlier. Click the checkmark to save the environment variables.
Now you'll want to push all of your new files to the GitHub repository. In your IDE, Click on Git > Commit. You will be brought to a list
of files that you've added or changed. Make sure all of the files are checked (there should be five of them). For the commit message, type
in Create the to-do list API
. Click on "Commit and Push". This saves the changes in a commit and pushes the changes to GitHub. From there,
your project will start building automatically and be deployed to Jumpydoll.
After the build completes, you can now run the same curl commands against the public URL. Since both your local version and the public version use the same MongoDB database, you should see an identical response. Try a public curl command now:
curl -X GET https://[user].app.jumpydoll.com/jumpydoll-todo-list/api/tasks
You should see the same result as the last time you ran it against localhost. You can also try running the POST, PUT, and DELETE commands.
Next, you'll learn how to build a web page to replace the curl commands and make it user-friendly.