Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/fauna/java-sample-app
https://github.com/fauna/java-sample-app
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/fauna/java-sample-app
- Owner: fauna
- Created: 2024-08-28T15:00:06.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2024-10-15T23:20:52.000Z (2 months ago)
- Last Synced: 2024-10-17T09:41:08.255Z (2 months ago)
- Language: Java
- Size: 494 KB
- Stars: 1
- Watchers: 9
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Fauna Java sample app
This sample app shows how to use [Fauna](https://fauna.com) in a production
application.The app uses Java 17 with Gradle 8.9 and the [Fauna v10 JVM
driver](https://github.com/fauna/fauna-jvm) 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.
## Highlights
The sample app uses the following Fauna features:
- **[Document type
enforcement](https://docs.fauna.com/fauna/current/learn/schema/#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](https://docs.fauna.com/fauna/current/learn/schema/#schema-migrations)
let you safely change the schemas at any time.- **[Relationships](https://docs.fauna.com/fauna/current/learn/query/relationships/):**
Normalized references link documents across collections. The app's queries use
[projection](https://docs.fauna.com/fauna/current/reference/fql/projection/)
to dynamically retrieve linked documents, even when deeply nested. No complex
joins, aggregations, or duplication needed.- **[Computed
fields](https://docs.fauna.com/fauna/current/learn/schema/#computed-fields):**
Computed fields dynamically calculate their values at query time. For example,
each customer's `orders` field uses a query to fetch a set of filtered orders.
Similarly, each order's `total` is calculated at query time based on linked
product prices and quantity.- **[Constraints](https://docs.fauna.com/fauna/current/learn/schema/#unique-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)](https://docs.fauna.com/fauna/current/learn/data-model/user-defined-functions/):**
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 validate `status`
transitions for orders.## Requirements
To run the app, you'll need:
- A [Fauna account](https://dashboard.fauna.com/register). You can sign up for a
free account at https://dashboard.fauna.com/register.- Your preferred flavor of Java 17
- [Fauna CLI](https://docs.fauna.com/fauna/current/tools/shell/) v3.0.0 or later.
To install the CLI, run:
```sh
npm install -g fauna-shell@latest
```You should also be familiar with basic Fauna CLI commands and usage. For an
overview, see the [Fauna CLI
docs](https://docs.fauna.com/fauna/current/tools/shell/).## Setup
1. Clone the repo and navigate to the `java-sample-app` directory:
```sh
git clone [email protected]:fauna/java-sample-app.git
cd java-sample-app
```2. Log in to Fauna using the Fauna CLI:
```sh
fauna cloud-login
```When prompted, enter:
* **Endpoint name:** `cloud` (Press Enter)
* **Email address:** The email address for your Fauna account.
* **Password:** The password for your Fauna account.
* **Which endpoint would you like to set as default?** The `cloud-*`
endpoint for your preferred region group. For example, to use the US
region group, use `cloud-us`.The command requires an email and password login. If you log in to Fauna
using GitHub or Netlify, you can enable email and password login using the
[Forgot Password](https://dashboard.fauna.com/forgot-password) workflow.3. Use the Fauna CLI to create the `ECommerceJava` database:
```sh
fauna create-database ECommerceJava
```4. Create a
[`.fauna-project`](https://docs.fauna.com/fauna/current/tools/shell/#proj-config)
config file for the project:```sh
fauna project init
```When prompted, enter:
* `schema` as the schema directory.
* `dev` as the environment name.
* The default endpoint.
* `ECommerce` as the database.5. Push the `.fsl` files in the `schema` directory to the `ECommerceJava`
database:```sh
fauna schema push
```When prompted, accept and stage the schema.
6. Check the status of the staged schema:
```sh
fauna schema status
```7. When the status is `ready`, commit the staged schema to the database:
```sh
fauna schema commit
```The commit applies the staged schema to the database. The commit creates the
collections and user-defined functions (UDFs) defined in the `.fsl` files of the
`schema` directory.8. Create a key with the `server` role for the `ECommerceJava` database:
```sh
fauna create-key --environment='' ECommerceJava server
```Copy the returned `secret`. The app can use the key's secret to authenticate
requests to the database.## Add sample data
The app includes a setup script that adds sample documents to the
`ECommerceJava` database. From the root directory, run:```sh
FAUNA_SECRET= ./setup.sh
```You can view documents created by the script in the [Fauna
Dashboard](https://dashboard.fauna.com/).## Run the app
The app runs an HTTP API server. From the root directory, run:
```sh
FAUNA_SECRET= ./gradlew bootRun
```Once started, the local server is available at http://localhost:8080.
## HTTP API endpoints
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### Make API requests
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.```sh
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 .
```## Expand the app
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:1. If you haven't already, add the sample data:
```sh
FAUNA_SECRET= ./setup.sh
```If the app server is running, stop the server by pressing Ctrl+C.
2. In `schema/collections.fsl`, add the following `totalPurchaseAmt` computed
field definition to the `Customer` collection:```diff
collection Customer {
...
// Use a computed field to get the set of Orders for a customer.
compute orders: Set = (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`.
3. Push the updated `.fsl` files in the `schema` directory to the `ECommerceJava`
database to stage the changes:```sh
fauna schema push
```When prompted, accept and stage the schema.
4. Check the status of the staged schema:
```sh
fauna schema status
```5. When the status is `ready`, commit the staged schema changes to the
database:```sh
fauna schema commit
```6. In `CustomersController.java`, add the
`totalPurchaseAmt` field to the `response` FQL template:```diff
// 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.7. In `Customer.java`, add the
`totalPurchaseAmt` field and a related getter
to the `Customer` class:```diff
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 `Customer` class.8. Start the app server:
```sh
FAUNA_SECRET= ./gradlew bootRun
```9. With the local server running in a separate terminal tab, run the
following curl request to the `POST /customers` endpoint:```sh
curl -v http://localhost:8080/customers/999 | jq .
```The response includes the computed `totalPurchaseAmt` field:
```json
{
"id": "999",
"name": "Valued Customer",
"email": "[email protected]",
"address": {
"street": "Herengracht",
"city": "Amsterdam",
"state": "North Holland",
"postalCode": "1015BT",
"country": "Netherlands"
},
"totalPurchaseAmt": 36000
}
```