Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
S

spring-restbucks

> 编程语言
Open source

Implementation of the sample from REST in Practice based on Spring projects

1.3K stars0 likes1 views
WebsiteGitHub

About

Implementation of the sample from REST in Practice based on Spring projects

Spring Restbucks

This project is a sample implementation of the Restbucks application described in the book REST in Practice by Jim Webber, Savas Parastatidis and Ian Robinson. It's a showcase for bringing different Spring eco-system technologies together to implement a REST web service. The application uses HAL as the primary representation format. The server implementation is accompanied by a hypermedia-aware Android client that adapts to changes on the server dynamically.

Quickstart

From the command line do:

bash
git clone https://github.com/odrotbohm/spring-restbucks.git
cd spring-restbucks/server
mvn clean package
java -jar target/*.jar

To send requests to the server application, you have several choices:

1. Use the embedded HAL Explorer.

The application ships with HAL Explorer embedded, so simply browsing to http://localhost:8080/explorer/index.html#uri=/ will allow you to explore the web service.

To get or create an order via HAL Explorer, you can start by either getting existing orders or placing a new order:

  • To get existing orders, click on the HTTP Get Request button for the restbucks:orders relation under Links. In the pop-up, click Go!, then expand any of the orders listed under Embedded Resources and click on self.
  • To place a new order, click on the HTTP Request button under the template titled Place an order under HAL-FORMS Template Elements.

Once you have an order displayed in HAL Explorer, you can submit payment:

  • Click on the HTTP Request for the template titled Go to checkout under HAL-FORMS Template Elements. This template appears for all orders with status Payment expected.
  • Enter any 16-digit number into the Credit card nuumber field and click Go!
  • You will see an error, because the card number is not in the database.
  • Enter 1234123412341234 and the payment will succeed. Ollie has got you covered :)

Note, that the curie links in the representations are currently not backed by any documents served but they will be in the future. Imagine simple HTML pages being served documenting the individual relation types.

2. Use the Android client.

Refer to the section The Android client below for more information.

3. Use the provided bash scripts.

Two bash scripts are provided to generate traffic. Both require curl and jq.

Single-run script: scripts/generate-traffic.sh

By default it places a single order (first available drink, default location), pays with the built-in demo card (1234123412341234), and polls until a receipt link appears. You can run multiple or varied scenarios, force errors, add delays, and more.

Usage examples:

  • Single, default order:
    ./scripts/generate-traffic.sh
  • All scenarios from file (in order):
    ./scripts/generate-traffic.sh --scenarios scripts/order-scenarios.json
  • One scenario by name with forced error:
    ./scripts/generate-traffic.sh --scenarios scripts/order-scenarios.json --scenario java_chip_takeaway --force-error INVALID_CARD
  • Cycle through all scenarios repeatedly (stop with Ctrl+C):
    ./scripts/generate-traffic.sh --scenarios scripts/order-scenarios.json --cycle
  • One random scenario per run:
    ./scripts/generate-traffic.sh --scenarios scripts/order-scenarios.json --random-scenario
  • Cycle with a new random scenario each time (0–3 s delay between runs by default):
    ./scripts/generate-traffic.sh --scenarios scripts/order-scenarios.json --random-scenario --cycle
  • No delay between runs:
    ./scripts/generate-traffic.sh --scenarios scripts/order-scenarios.json --cycle --no-delay

Options for generate-traffic.sh:

  • --scenarios or --scenarios= — JSON file of scenarios (e.g. scripts/order-scenarios.json). Without --scenario, runs all scenarios in order; with --scenario , runs only that scenario.
  • --scenario or --scenario= — Run only the named scenario.
  • --cycle — With --scenarios: repeat indefinitely (Ctrl+C to stop). Without --scenario cycles through all; with --scenario repeats that scenario.
  • --random-scenario — With --scenarios and no --scenario: run one scenario chosen at random. With --cycle, pick a new random scenario each iteration.
  • --delay-max — Random delay 0..MS milliseconds between scenario runs (default 3000). Use --no-delay for no delay.
  • --force-error [INVALID_CARD|DOUBLE_PAY] — INVALID_CARD: invalid card, expect failure. DOUBLE_PAY: pay twice, second payment fails. Omitted value defaults to INVALID_CARD.
  • --base-url — Target base URL (default http://localhost:8080).
  • --verbose / -v — DEBUG-level payload dumps.

Parallel users: scripts/run-parallel-traffic.sh

Runs multiple “users” in parallel, each executing generate-traffic.sh with --scenarios scripts/order-scenarios.json --random-scenario --cycle. Output is prefixed with [n]> for user number n. A single Ctrl+C stops all users.

Usage (run from the server directory):

  • Default 5 parallel users:
    ./scripts/run-parallel-traffic.sh
  • 10 parallel users:
    ./scripts/run-parallel-traffic.sh 10
  • With verbose output per user:
    ./scripts/run-parallel-traffic.sh 3 --verbose

IDE setup notes

Eclipse

For the usage inside an IDE do the following:

  1. Make sure you have an Eclipse with m2e installed (preferably STS).

  2. Install Lombok.

    1. Download it from the project page.
    2. Run the JAR (double click or java -jar …).
    3. Point it to your Eclipse installation, run the install.
    4. Restart Eclipse.
  3. Import the checked out code through File > Import > Existing Maven Project…

IntelliJ

  1. After opening the project in IntelliJ, right click on server/pom.xml and select Add as Maven Project.
  2. If you would like to execute tests in the Run panel (activated by right-clicking on server/src/test/java/org/springsource/restbucks and selecting Run Tests in 'restbucks'), you will need to edit Maven plugin configurations. Open the Maven tool window and find the list of plugins included in the project. Expand byte-buddy, right click on transform-extended, and select Execute After Build and Execute After Rebuild.

Project description

The project uses:

  • Spring Boot
  • Spring (MVC)
  • Spring Data JPA
  • Spring Data REST
  • Spring HATEOAS
  • Spring Plugin
  • Spring Security
  • Spring Session
  • Spring Modulith
  • jMolecules

The implementation consists of mainly two parts, the order and the payment part. The Orders are exposed as REST resources using Spring Data RESTs capability to automatically expose Spring Data JPA repositories contained in the application. The Payment process and the REST application protocol described in the book are implemented manually using a Spring MVC controller (PaymentController).

Here's what the individual projects used contribute to the sample in from a high-level point of view:

Spring Data JPA

The Spring Data repository mechanism is used to reduce the effort to implement persistence for the domain objects to the declaration of an interface per aggregate root. See OrderRepository and PaymentRepository for example. Beyond that, using the repository abstract enables the Spring Data REST module to do its work.

Spring Data REST

We're using Spring Data REST to expose the OrderRepository as REST resource without additional effort.

Spring HATEOAS

Spring HATEOAS provides a generic Resource abstraction that we leverage to create hypermedia-driven representations. Spring Data REST also leverages this abstraction so that we can deploy ResourceProcessor implementations (e.g. PaymentorderResourceProcessor) to enrich the representations for Order instance with links to the PaymentController. Read more on that below in the Hypermedia section.

The final important piece is the EntityLinks abstraction that allows to create Link instance in a type-safe manner avoiding the repetition of URI templates and parts all over the place. See PaymentLinks for example usage.

Spring Plugin

The Spring Plugin library provides means to collect Spring beans by type and exposing them for selection based on a selection criterion. It basically forms the foundation for the EntityLinks mechanism provided in Spring HATEOAS and our custom extension RestResourceEntityLinks.

Spring Security / Spring Session

The spring-session branch contains additional configuration to secure the service using Spring Security, HTTP Basic authentication and Spring Session's HTTP header based session strategy to allow clients to obtain a security token via the X-Auth-Token header and using that for subsequent requests.

If you check out the branch and run the sample you should be able to follow this interaction (I am using HTTPie here)

$ http :8080
HTTP/1.1 401 Unauthorized
…
WWW-Authenticate: Basic realm="Spring RESTBucks"

You can now authenticate using the default credentials (the password password is configured in application.properties).

$ http :8080 --auth=user:password
HTTP/1.1 200 OK
Content-Type: application/hal+json;charset=UTF-8
–
X-Auth-Token: ef005d62-b69b-4675-b920-d340a238e857

Now you can use the presented auth token in further requests:

$ http :8080 X-Auth-Token:ef005d62-b69b-4675-b920-d340a238e857
HTTP/1.1 200 OK
Content-Type: application/hal+json;charset=UTF-8
–

Spring Modulith

Spring Modulith supports modular architecture in monoliths. It treats each root-level package as a separate module with top-level public members exposed as API and all other code protected as module-internal (unless explicitly specified otherwise). Through tests, it verifies compliance to modular architecture rules and also generates documentation for architecturally relevant components of the system. See DocumentationTest and also target/spring-modulith-docs/, once the test has been executed.

Additionally, we are using Spring Modulith to isolate a single module for integration testing in OrdersIntegrationTest. We are also using Spring Modulith, together with Spring Framework's in-memory messaging capabilities, to handle event-driven interactions between modules with additional support for transaction management. See the use of ApplicationModuleListener in Engine.

Finally, Spring Modulith is being used to extract distributed tracing from module interactions. To enable this functionality, see the Observability section below.

Documentation / Client Stub Generation

The restdocs branch contains the test for the order payment process augmented with setup to generate Asciidoctor snippets documenting the executed requests and expectations on the responses. These snippets are included from the general Asciidoctor documents in src/main/asciidoc, turned into HTML and packaged into the application itself during the build (run mvn clean package). The docs are then pointed to by a CURIE link in the HAL response (see Restbucks.curieProvider()) so that they

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Java

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言