This sample app shows how to use Fauna in a production application.
The app uses Java 17 with Gradle 8.9 and the Fauna v10 JVM driver to create HTTP API endpoints for an e-commerce store. You can use the app's API endpoints to manage products, customers, and orders for the store.
The app uses Fauna schemas and queries to:
- 
Read and write data with strong consistency.
 - 
Define and handle relationships between resources, such as linking orders to products and customers.
 - 
Validate data changes against business logic.
 
The app's source code includes comments that highlight Fauna best practices.
The sample app uses the following Fauna features:
- 
Document type enforcement: Collection schemas enforce a structure for the app's documents. Fauna rejects document writes that don't conform to the schema, ensuring data consistency. Zero-downtime migrations let you safely change the schemas at any time.
 - 
Relationships: Normalized references link documents across collections. The app's queries use projection to dynamically retrieve linked documents, even when deeply nested. No complex joins, aggregations, or duplication needed.
 - 
Computed fields: Computed fields dynamically calculate their values at query time. For example, each customer's
ordersfield uses a query to fetch a set of filtered orders. Similarly, each order'stotalis calculated at query time based on linked product prices and quantity. - 
Constraints: The app uses constraints to ensure field values are valid. For example, the app uses unique constraints to ensure each customer has a unique email address and each product has a unique name. Similarly, check constraints ensure each customer has only one cart at a time and that product prices are not negative.
 - 
User-defined functions (UDFs): The app uses UDFs to store business logic as reusable queries. For example, the app uses a
checkout()UDF to process order updates.checkout()calls another UDF,validateOrderStatusTransition(), to validatestatustransitions for orders. 
To run the app, you'll need:
- 
A Fauna account. You can sign up for a free account at https://dashboard.fauna.com/register.
 - 
Your preferred flavor of Java 17.
 - 
To install the CLI, run:
npm install -g fauna-shell
 
- 
Clone the repo and navigate to the
java-sample-appdirectory:git clone git@github.com:fauna/java-sample-app.git cd java-sample-app - 
If you haven't already, log in to Fauna using the Fauna CLI:
fauna login
 - 
Use the CLI to create the
ECommerceJavadatabase:# Replace 'us' with your preferred region group: # 'us' (United States), 'eu' (Europe), or `global` (available to Pro accounts and above). fauna database create \ --name ECommerceJava \ --database us
 - 
Push the
.fslfiles in theschemadirectory to theECommerceJavadatabase:# Replace 'us' with your region group. fauna schema push \ --database us/ECommerceJavaWhen prompted, accept and stage the schema.
 - 
Check the status of the staged schema:
fauna schema status \ --database us/ECommerceJava
 - 
When the status is
ready, commit the staged schema to the database:fauna schema commit \ --database us/ECommerceJava
The commit applies the staged schema to the database. The commit creates the collections and user-defined functions (UDFs) defined in the
.fslfiles of theschemadirectory. - 
Create a key with the
serverrole for theECommerceJavadatabase:fauna query "Key.create({ role: 'server' })" \ --database us/ECommerceJavaCopy the returned
secret. The app can use the key's secret to authenticate requests to the database. 
The app includes a seed script that adds sample documents to the
ECommerceJava database. From the root directory, run:
chmod +x ./scripts/seed.sh
FAUNA_SECRET=<secret> ./scripts/seed.shYou can view documents created by the script in the Fauna Dashboard.
The app runs an HTTP API server. From the root directory, run:
FAUNA_SECRET=<secret> ./gradlew bootRunOnce started, the local server is available at http://localhost:8080.
The app's HTTP API endpoints are defined in *Controller files in the
java.sample.controllers.* modules.
An OpenAPI spec and Swagger UI docs for the endpoints are available at:
- OpenAPI spec: http://localhost:8080/v3/api-docs
 - Swagger UI: http://localhost:8080/swagger-ui.html
 
You can use the endpoints to make API requests that read and write data from
the ECommerceJava database.
For example, with the local server running in a separate terminal tab, run the
following curl request to the POST /products endpoint. The request creates a
Product collection document in the ECommerceJava database.
curl -v \
  http://localhost:8080/products \
  -H "Content-Type: application/json" \
  -d '{
    "name": "The Old Man and the Sea",
    "price": 899,
    "description": "A book by Ernest Hemingway",
    "stockQuantity": 10,
    "category": "books"
  }' | jq .You can further expand the app by adding fields and endpoints.
As an example, the following steps adds a computed totalPurchaseAmt field to
Customer documents and related API responses:
- 
If you haven't already, add the sample data:
FAUNA_SECRET=<secret> ./scripts/seed.sh
If the app server is running, stop the server by pressing Ctrl+C.
 - 
In
schema/collections.fsl, add the followingtotalPurchaseAmtcomputed field definition to theCustomercollection:collection Customer { ... // Use a computed field to get the set of Orders for a customer. compute orders: Set<Order> = (customer => Order.byCustomer(customer)) + // Use a computed field to calculate the customer's cumulative purchase total. + // The field sums purchase `total` values from the customer's linked Order documents. + compute totalPurchaseAmt: Number = (customer => customer.orders.fold(0, (sum, order) => { + let order: Any = order + sum + order.total + })) ... } ...Save
schema/collections.fsl. - 
Push the updated
.fslfiles in theschemadirectory to theECommerceJavadatabase to stage the changes:fauna schema push \ --database us/ECommerceJava
When prompted, accept and stage the schema.
 - 
Check the status of the staged schema:
fauna schema status \ --database us/ECommerceJava
 - 
When the status is
ready, commit the staged schema changes to the database:fauna schema commit \ --database us/ECommerceJava
 - 
In
CustomersController.java, add thetotalPurchaseAmtfield to theresponseFQL template:// Project Customer document fields for consistent responses. private final Query response = fql(""" customer { id, name, email, + address, + totalPurchaseAmt } """); `;Save
CustomersController.java.Customer-related endpoints use this template to project Customer document fields in responses.
 - 
In
Customer.java, add thetotalPurchaseAmtfield and a related getter to theCustomerclass:private String email; private Address address; + private int totalPurchaseAmt; + + public int getTotalPurchaseAmt() { + return totalPurchaseAmt; + } public String getId() { return id; }
Save
Customer.java.Customer-related endpoints return responses that conform to the
Customerclass. - 
Start the app server:
FAUNA_SECRET=<secret> ./gradlew bootRun
 - 
With the local server running in a separate terminal tab, run the following curl request to the
POST /customersendpoint:curl -v http://localhost:8080/customers/999 | jq .
The response includes the computed
totalPurchaseAmtfield:{ "id": "999", "name": "Valued Customer", "email": "fake@fauna.com", "address": { "street": "Herengracht", "city": "Amsterdam", "state": "North Holland", "postalCode": "1015BT", "country": "Netherlands" }, "totalPurchaseAmt": 36000 }