Java RESTful Web App
In this guide we will build a web application that accepts HTTP requests to store and retrieve data in the Tigris backend. The application uses Spring Boot framework.
This is a simplified implementation of an e-commerce use case - this is just one of many use cases for how you could interact with Tigris!
Now let's get started locally with Tigris.
Startup Tigris locally via Docker
Install Tigris CLI
Use the command below to install the CLI on macOS
brew install tigrisdata/tigris/tigris-cli
Use the command below to install the CLI on linux
curl -sSL https://tigris.dev/cli-linux | sudo tar -xz -C /usr/local/bin
Alternative ways of installation can be found here.
Start Tigris development environment
tigris dev start
Once this command has completed, Tigris will be available on port 8081
.
Setting up and starting the application
Clone the starter application code repository
git clone https://github.com/tigrisdata/tigris-starter-java.git
cd tigris-starter-java
Build the project
The next step is to build the project
mvn clean install
Run the application
Next run the application from your favorite IDE. An example using IntelliJ IDEA is shown below
A successful launch of the application will end with the log entry
[main] INFO c.t.starter.spring.TigrisInitializer - Finished initializing Tigris
Testing the application
Try out the REST API at http://localhost:8080/swagger.html
Let's create a user and a product.
Create a User
curl http://localhost:8080/users/create \
-X POST \
-H 'Content-Type: application/json' \
-d '{
"name": "Jania McGrory",
"balance": 6045.7
}'
Create Products
curl http://localhost:8080/products/create \
-X POST \
-H 'Content-Type: application/json' \
-d '{
"name": "Vanilla Beans",
"quantity": 6358,
"price": 4.39
}'
curl http://localhost:8080/products/create \
-X POST \
-H 'Content-Type: application/json' \
-d '{
"name": "Avocado oil",
"quantity": 100,
"price": 45
}'
These newly added User and Product documents were persisted in the Tigris backend.
Read from db
curl http://localhost:8080/users/read/1
curl http://localhost:8080/products/read/1
Search for products
Search for products named "vanilla"
curl http://localhost:8080/products/search \
-X POST \
-H 'Content-Type: application/json' \
-d '{
"q": "vanilla",
"searchFields": ["name"],
}'
Extend the application
Now let's set up a HTTP handler that will leverage Tigris to insert data into the orders collection while updating the data in the users and products collections.
One of the main features of Tigris is the ability to perform ACID transactions. We will perform the insert and update operations in a transaction ensuring that the collections are consistently updated.
Open the project in your favorite IDE and add the following to
com.tigrisdata.starter.controller.OrderController
Additional Imports
import java.util.Collections;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import com.tigrisdata.db.client.UpdateFields;
HTTP handler
@PostMapping("{user_id}/{product_id}/{qty}")
public ResponseEntity<String> purchase(
@PathVariable("user_id") int userId,
@PathVariable("product_id") int productId,
@PathVariable("qty") int quantity)
throws TigrisException {
tigrisStarterDatabase.transact(
session -> {
try {
// read the user and product documents
User user = userCollection.readOne(session, Filters.eq("id", userId)).get();
Product product = productCollection.readOne(session, Filters.eq("id", productId)).get();
// ensure that a user is never allowed to purchase products worth more than
// their available balance, and that we never create orders that exceed the
// amount of available product
if (product.getQuantity() >= quantity
&& product.getPrice() * quantity <= user.getBalance()) {
double orderTotal = product.getPrice() * quantity;
double newUserBalance = user.getBalance() - orderTotal;
int newProductQuantity = product.getQuantity() - quantity;
userCollection.update(
session,
Filters.eq("id", userId),
UpdateFields.newBuilder().set("balance", newUserBalance).build());
productCollection.update(
session,
Filters.eq("id", productId),
UpdateFields.newBuilder().set("quantity", newProductQuantity).build());
orderCollection.insert(
session,
new Order(
userId,
orderTotal,
Collections.singletonList(new Order.ProductItem(productId, quantity))));
} else {
// throw this to automatically rollback current transaction
throw new IllegalStateException("Not enough balance");
}
} catch (TigrisException ex) {
// handle this or throw this to automatically rollback current transaction
throw new IllegalStateException(ex);
}
});
// transaction successful
return ResponseEntity.status(HttpStatus.OK).body("Purchased successfully");
}
Run the application again and use the newly added HTTP endpoint to create an order.
Create an Order
curl -X 'POST' 'http://localhost:8080/order/1/1/20'
Understanding what just happened
The starter project includes the Java model classes corresponding to the
three collections users, products and orders located in the Java
package com.tigrisdata.starter.collections
.
When you launched the application, Tigris Spring autoconfigurer created the database and registered the schema with the Tigris backend based on the three collection models based on your configuration.
You wrote a new HTTP handler that used Tigris' transaction feature. The transaction involved reading data, validating that certain conditions around the product quantity and user's balance are met, and finally inserting a new order together with updating the users and products collections.