diff --git a/backends-for-frontends/README.md b/backends-for-frontends/README.md new file mode 100644 index 000000000000..12038e821e38 --- /dev/null +++ b/backends-for-frontends/README.md @@ -0,0 +1,148 @@ +--- +title: "Backends For Frontends Pattern in Java: Tailoring APIs to Client Needs" +shortTitle: Backends For Frontends +description: "Learn the Backends For Frontends (BFF) design pattern in Java. Understand how to give each client type its own dedicated backend service, with real-world examples, code, and diagrams." +category: Architectural +language: en +tag: + - API design + - Architecture + - Client-server + - Decoupling + - Microservices +--- + +## Also known as + +* Backend For Frontend +* BFF Pattern + +## Intent of Backends For Frontends Pattern + +Provide each client-side application (mobile, desktop, chatbot, and so on) with its own dedicated +backend service, so every client gets an API shaped exactly for its own needs instead of sharing +one general-purpose backend with every other client. + +## Detailed Explanation of Backends For Frontends Pattern with Real-World Examples + +Real-world example + +> Imagine a retail company whose mobile app, desktop back-office tool, and support chatbot all +> need customer, cart, order and supplier data -- but a phone screen wants a short summary while +> the back-office desktop tool wants full order and stock detail. Rather than exposing one shared +> API that every client has to filter or over-fetch from, the company stands up a small BFF service +> for the mobile clients and a separate BFF service for the intranet clients. Each BFF calls only +> the downstream microservices its client needs and returns a payload shaped for that client. + +In plain words + +> Give every kind of client its own tailor-made backend, instead of forcing all clients through one +> one-size-fits-all API. + +Sam Newman, who popularized the pattern, says + +> Create separate backend services to be consumed by specific frontend applications or interfaces. + +## Architecture Diagram + +``` +node mobile{ + component iosapp as "ios app" + component androidapp as "android app" +} +node intranet{ + component desktop as "desktop app" + component chatbot +} +component bff as "BFF server"{ + component iosbff as "ios BFF" + component androidbff as "android BFF" + component chatbotbff as "chatbot BFF" + component desktopbff as "desktop BFF" +} +node intranetserv as "intranet services server"{ + component ss as "supplier service API" +} +cloud onlypublic as "public cloud"{ + component cas as "customer authentication service API" + component cs as "cart service API" +} +cloud cloudserv as "managed cloud"{ + component os as "order service API" +} +iosapp -- iosbff +androidapp -- androidbff +chatbot -- chatbotbff +desktop -- desktopbff +iosbff -- cas +androidbff -- cas +iosbff -- cs +androidbff -- cs +iosbff -- os +androidbff -- os +chatbotbff -- os +desktopbff -- os +chatbotbff -- ss +desktopbff -- ss +``` + +This example implements a simplified version of the diagram above with two client-facing BFFs +instead of four, to keep the demo focused: a **Mobile BFF** standing in for the ios/android BFFs, +and a **Desktop BFF** standing in for the desktop/chatbot BFFs. Both call into the same shared +downstream services (`AuthService`, `OrderService`), while `CartService` is only used by the +Mobile BFF and `SupplierService` is only reachable from the Desktop BFF, matching the fan-out +shown in the diagram. + +## Class Diagram + +![Backends For Frontends class diagram](./etc/backends-for-frontends.png) + +## When to Use the Backends For Frontends Pattern in Java + +* Different client types (mobile, web, desktop, voice/chat) need meaningfully different shapes, + granularity, or aggregation of the same underlying data. +* A single shared API has grown a large number of client-specific conditional branches, optional + fields, or query parameters to accommodate every consumer. +* Different client teams need to iterate on their own API independently without coordinating + changes through one shared backend team. +* Some clients (e.g. mobile) need aggressively trimmed payloads for bandwidth/latency reasons, + while others (e.g. an internal desktop tool) need much richer data. + +## Benefits and Trade-offs of Backends For Frontends Pattern + +Benefits: + +* Each client gets an API optimized for its own needs, improving performance and simplicity on + the client side. +* Client teams can evolve their BFF independently, reducing cross-team coordination. +* Downstream microservices stay generic and reusable; client-specific logic lives in the BFF + layer instead of leaking into shared services. + +Trade-offs: + +* Introduces additional services to build, deploy, and operate. +* Logic that is genuinely shared across clients can end up duplicated across BFFs if not + carefully factored out. +* Adds an extra network hop between the client and the downstream services. + +## How to Implement Backends For Frontends Pattern in Java + +1. Identify the distinct client types that need meaningfully different data shapes. +2. Define the downstream services each client's data actually depends on (`AuthService`, + `CartService`, `OrderService`, `SupplierService` in this example). +3. Create one BFF per client type, implementing a shared `ClientBff` contract, where each BFF + only depends on the downstream services its client needs. +4. Have each BFF aggregate and reshape the downstream data into a response DTO tailored to its + client (`MobileDashboardResponse`, `DesktopDashboardResponse`). +5. Wire the client applications to call their own BFF rather than the downstream services + directly. + +## Source Code + +* [Pattern: Backends For Frontends](https://samnewman.io/patterns/architectural/bff/) by Sam Newman +* [Microservices Patterns: With examples in Java](https://www.amazon.com/Microservices-Patterns-examples-Chris-Richardson/dp/1617294543) by Chris Richardson + +## References and Credits + +* [Building Microservices](https://www.oreilly.com/library/view/building-microservices-2nd/9781492034018/) by Sam Newman +* [Pattern: Backend for frontend (microservices.io)](https://microservices.io/patterns/apigateway.html) diff --git a/backends-for-frontends/etc/backends-for-frontends.png b/backends-for-frontends/etc/backends-for-frontends.png new file mode 100644 index 000000000000..f42c786fecf4 Binary files /dev/null and b/backends-for-frontends/etc/backends-for-frontends.png differ diff --git a/backends-for-frontends/etc/backends-for-frontends.urm.puml b/backends-for-frontends/etc/backends-for-frontends.urm.puml new file mode 100644 index 000000000000..b09c06742d27 --- /dev/null +++ b/backends-for-frontends/etc/backends-for-frontends.urm.puml @@ -0,0 +1,130 @@ +@startuml +package com.iluwatar.bff { + class App { + - LOGGER : Logger {static} + - USER_ID : String {static} + - PRODUCT_ID : String {static} + - DEMO_PRICE_USD : double {static} + - DEMO_STOCK_LEVEL : int {static} + + App() + + main(args : String[]) {static} + } +} +package com.iluwatar.bff.bff { + interface ClientBff { + + getDashboard(userId : String) : T {abstract} + } + class DesktopBff { + - authService : AuthService + - orderService : OrderService + - supplierService : SupplierService + + DesktopBff(auth : AuthService, orders : OrderService, suppliers : SupplierService) + + getDashboard(userId : String) : DesktopDashboardResponse + } + class MobileBff { + - MAX_RECENT_ORDERS : int {static} + - authService : AuthService + - cartService : CartService + - orderService : OrderService + + MobileBff(auth : AuthService, cart : CartService, orders : OrderService) + + getDashboard(userId : String) : MobileDashboardResponse + } +} +package com.iluwatar.bff.dto { + class DesktopDashboardResponse { + - greeting : String + - loyaltyTier : String + - orderStatuses : List + - supplierStockSummaries : List + + DesktopDashboardResponse(greeting : String, loyaltyTier : String, orderStatuses : List, supplierStockSummaries : List) + } + class MobileDashboardResponse { + - greeting : String + - cartItemCount : int + - cartTotalUsd : double + - recentOrderSummaries : List + + MobileDashboardResponse(greeting : String, cartItemCount : int, cartTotalUsd : double, recentOrderSummaries : List) + } +} +package com.iluwatar.bff.model { + class CartItem { + - product : Product + - quantity : int + + CartItem(product : Product, quantity : int) + + lineTotal() : double + } + class Order { + - id : String + - productName : String + - status : String + + Order(id : String, productName : String, status : String) + } + class Product { + - id : String + - name : String + - priceUsd : double + + Product(id : String, name : String, priceUsd : double) + } + class SupplierRecord { + - productId : String + - supplierName : String + - stockLevel : int + + SupplierRecord(productId : String, supplierName : String, stockLevel : int) + } + class User { + - id : String + - displayName : String + - loyaltyTier : String + + User(id : String, displayName : String, loyaltyTier : String) + } +} +package com.iluwatar.bff.service { + interface AuthService { + + getUser(userId : String) : User {abstract} + } + interface CartService { + + getCart(userId : String) : List {abstract} + } + interface OrderService { + + getOrders(userId : String) : List {abstract} + } + interface SupplierService { + + getSupplierRecords(productId : String) : List {abstract} + } +} +package com.iluwatar.bff.service.impl { + class InMemoryAuthService { + - users : Map + + InMemoryAuthService(userData : Map) + + getUser(userId : String) : User + } + class InMemoryCartService { + - cartsByUserId : Map> + + InMemoryCartService(carts : Map>) + + getCart(userId : String) : List + } + class InMemoryOrderService { + - ordersByUserId : Map> + + InMemoryOrderService(orders : Map>) + + getOrders(userId : String) : List + } + class InMemorySupplierService { + - recordsByProductId : Map> + + InMemorySupplierService(records : Map>) + + getSupplierRecords(productId : String) : List + } +} +DesktopBff ..|> ClientBff +MobileBff ..|> ClientBff +DesktopBff --> "-authService" AuthService +DesktopBff --> "-orderService" OrderService +DesktopBff --> "-supplierService" SupplierService +MobileBff --> "-authService" AuthService +MobileBff --> "-cartService" CartService +MobileBff --> "-orderService" OrderService +InMemoryAuthService ..|> AuthService +InMemoryCartService ..|> CartService +InMemoryOrderService ..|> OrderService +InMemorySupplierService ..|> SupplierService +CartItem --> "-product" Product +@enduml diff --git a/backends-for-frontends/pom.xml b/backends-for-frontends/pom.xml new file mode 100644 index 000000000000..8f1e454fa646 --- /dev/null +++ b/backends-for-frontends/pom.xml @@ -0,0 +1,67 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + + backends-for-frontends + + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.slf4j + slf4j-api + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.iluwatar.bff.App + + + + + + + diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/App.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/App.java new file mode 100644 index 000000000000..b76939c53fd4 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/App.java @@ -0,0 +1,109 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff; + +import com.iluwatar.bff.bff.DesktopBff; +import com.iluwatar.bff.bff.MobileBff; +import com.iluwatar.bff.model.CartItem; +import com.iluwatar.bff.model.Order; +import com.iluwatar.bff.model.Product; +import com.iluwatar.bff.model.SupplierRecord; +import com.iluwatar.bff.model.User; +import com.iluwatar.bff.service.impl.InMemoryAuthService; +import com.iluwatar.bff.service.impl.InMemoryCartService; +import com.iluwatar.bff.service.impl.InMemoryOrderService; +import com.iluwatar.bff.service.impl.InMemorySupplierService; +import java.util.List; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * {@link App} demonstrates the Backends For Frontends (BFF) pattern. + * + *

A single set of downstream microservices (customer authentication, cart, order and supplier + * services) is shared by every client. Two different client-facing gateways -- {@link MobileBff} + * for the mobile apps and {@link DesktopBff} for the intranet desktop/chatbot clients -- each call + * a different subset of those services and reshape the results into a response tailored to what + * their own client actually needs, rather than exposing one one-size-fits-all API to every client. + */ +public final class App { + + /** Logger for this class. */ + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + /** User id used in the demonstration. */ + private static final String USER_ID = "u-1"; + + /** Product id used in the demonstration. */ + private static final String PRODUCT_ID = "p-42"; + + /** Unit price of the demo product in US dollars. */ + private static final double DEMO_PRICE_USD = 79.99; + + /** Supplier stock level used in the demonstration. */ + private static final int DEMO_STOCK_LEVEL = 120; + + private App() { + // utility class + } + + /** + * Program entry point. + * + * @param args no argument sent + */ + public static void main(final String[] args) { + // shared downstream microservices, as drawn in the pattern diagram + var authService = new InMemoryAuthService(Map.of(USER_ID, new User(USER_ID, "Alice", "GOLD"))); + + var product = new Product(PRODUCT_ID, "Wireless Headphones", DEMO_PRICE_USD); + var cartService = new InMemoryCartService(Map.of(USER_ID, List.of(new CartItem(product, 2)))); + + var orderService = + new InMemoryOrderService( + Map.of( + USER_ID, + List.of( + new Order("o-1", "Wireless Headphones", "DELIVERED"), + new Order("o-2", "USB-C Cable", "IN_TRANSIT")))); + + var supplierService = + new InMemorySupplierService( + Map.of( + "Wireless Headphones", + List.of(new SupplierRecord(PRODUCT_ID, "Acme Audio Co.", DEMO_STOCK_LEVEL)))); + + // client-specific BFFs, each calling only the services their client needs + var mobileBff = new MobileBff(authService, cartService, orderService); + var desktopBff = new DesktopBff(authService, orderService, supplierService); + + var mobileResponse = mobileBff.getDashboard(USER_ID); + LOGGER.info("Mobile BFF response: {}", mobileResponse); + + var desktopResponse = desktopBff.getDashboard(USER_ID); + LOGGER.info("Desktop BFF response: {}", desktopResponse); + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/ClientBff.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/ClientBff.java new file mode 100644 index 000000000000..4c1d8d768ecb --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/ClientBff.java @@ -0,0 +1,44 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.bff; + +/** + * Common contract every client-specific Backend For Frontend implements: given a user id, build + * whatever response shape ({@code T}) that particular client needs. Each implementation is free to + * call a different subset of downstream services and aggregate them differently -- that freedom is + * the entire point of the pattern. + * + * @param the response DTO shape this BFF returns to its client + */ +public interface ClientBff { + + /** + * Builds the dashboard response for a given user, tailored to this BFF's client. + * + * @param userId identifier of the user requesting their dashboard + * @return the client-specific response + */ + T getDashboard(String userId); +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/DesktopBff.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/DesktopBff.java new file mode 100644 index 000000000000..1073f4556558 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/DesktopBff.java @@ -0,0 +1,94 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.bff; + +import com.iluwatar.bff.dto.DesktopDashboardResponse; +import com.iluwatar.bff.service.AuthService; +import com.iluwatar.bff.service.OrderService; +import com.iluwatar.bff.service.SupplierService; +import java.util.ArrayList; +import java.util.List; + +/** + * Backend For Frontend serving the intranet clients (desktop app, chatbot) from the diagram. It + * aggregates the auth, order and supplier services and reshapes the results into a richer, + * back-office style payload. Unlike {@link MobileBff}, it does not touch the cart service at all + * and it does reach into the intranet-only supplier service, matching the fan-out drawn in the + * pattern diagram. + */ +public final class DesktopBff implements ClientBff { + + /** The customer authentication service. */ + private final AuthService authService; + + /** The order service. */ + private final OrderService orderService; + + /** The supplier service (intranet-only). */ + private final SupplierService supplierService; + + /** + * Creates a desktop BFF wired to the downstream services it depends on. + * + * @param auth the customer authentication service + * @param orders the order service + * @param suppliers the supplier service + */ + public DesktopBff( + final AuthService auth, final OrderService orders, final SupplierService suppliers) { + this.authService = auth; + this.orderService = orders; + this.supplierService = suppliers; + } + + @Override + public DesktopDashboardResponse getDashboard(final String userId) { + var user = authService.getUser(userId); + var orders = orderService.getOrders(userId); + + var orderStatuses = + orders.stream() + .map(order -> order.id() + ": " + order.productName() + " [" + order.status() + "]") + .toList(); + + var supplierStockSummaries = new ArrayList(); + for (var order : orders) { + for (var supplierRecord : supplierService.getSupplierRecords(order.productName())) { + supplierStockSummaries.add( + supplierRecord.supplierName() + + ": " + + supplierRecord.stockLevel() + + " units of " + + order.productName()); + } + } + + return new DesktopDashboardResponse( + "Welcome back, " + user.displayName(), + user.loyaltyTier(), + List.copyOf(orderStatuses), + List.copyOf(supplierStockSummaries)); + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/MobileBff.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/MobileBff.java new file mode 100644 index 000000000000..a51a7c8a8201 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/MobileBff.java @@ -0,0 +1,86 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.bff; + +import com.iluwatar.bff.dto.MobileDashboardResponse; +import com.iluwatar.bff.service.AuthService; +import com.iluwatar.bff.service.CartService; +import com.iluwatar.bff.service.OrderService; +import java.util.List; + +/** + * Backend For Frontend serving the mobile clients (iOS app, Android app) from the diagram. It + * aggregates the auth, cart and order services and reshapes the results into a small payload suited + * to a phone screen and a limited-bandwidth connection. It never calls the supplier service: a + * mobile shopper has no use for back-office stock data, so this BFF simply does not expose it, + * rather than sending it and letting the client ignore it. + */ +public final class MobileBff implements ClientBff { + + /** Maximum number of recent order summaries to include in the mobile response. */ + private static final int MAX_RECENT_ORDERS = 3; + + /** The customer authentication service. */ + private final AuthService authService; + + /** The cart service. */ + private final CartService cartService; + + /** The order service. */ + private final OrderService orderService; + + /** + * Creates a mobile BFF wired to the downstream services it depends on. + * + * @param auth the customer authentication service + * @param cart the cart service + * @param orders the order service + */ + public MobileBff(final AuthService auth, final CartService cart, final OrderService orders) { + this.authService = auth; + this.cartService = cart; + this.orderService = orders; + } + + @Override + public MobileDashboardResponse getDashboard(final String userId) { + var user = authService.getUser(userId); + var cart = cartService.getCart(userId); + var orders = orderService.getOrders(userId); + + var cartTotal = cart.stream().mapToDouble(item -> item.lineTotal()).sum(); + var recentOrderSummaries = + orders.stream() + .limit(MAX_RECENT_ORDERS) + .map(order -> order.productName() + " (" + order.status() + ")") + .toList(); + + return new MobileDashboardResponse( + "Hi " + user.displayName() + "!", + cart.size(), + cartTotal, + List.copyOf(recentOrderSummaries)); + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/package-info.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/package-info.java new file mode 100644 index 000000000000..c338c3158023 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/bff/package-info.java @@ -0,0 +1,29 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/** + * Client-specific Backend For Frontend implementations: one per client type (mobile, desktop) that + * each aggregate a different subset of downstream services. + */ +package com.iluwatar.bff.bff; diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/dto/DesktopDashboardResponse.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/dto/DesktopDashboardResponse.java new file mode 100644 index 000000000000..7dd3895c060f --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/dto/DesktopDashboardResponse.java @@ -0,0 +1,47 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.dto; + +import java.util.List; + +/** + * The shape of data the desktop back-office client renders: richer than the mobile payload, + * including full order status and supplier stock levels that a mobile shopper never needs. + * + * @param greeting a short personalized greeting for the user + * @param loyaltyTier the user's loyalty program tier + * @param orderStatuses detailed "id: productName [status]" lines for every order + * @param supplierStockSummaries "supplierName: stockLevel units" lines for relevant products + */ +public record DesktopDashboardResponse( + String greeting, + String loyaltyTier, + List orderStatuses, + List supplierStockSummaries) { + /** No additional validation required. */ + public DesktopDashboardResponse { + // no-op + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/dto/MobileDashboardResponse.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/dto/MobileDashboardResponse.java new file mode 100644 index 000000000000..133f7742dfbe --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/dto/MobileDashboardResponse.java @@ -0,0 +1,44 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.dto; + +import java.util.List; + +/** + * The shape of data the mobile (iOS/Android) client actually renders: a lean payload with just + * enough for a small screen, deliberately excluding fields the desktop client needs. + * + * @param greeting a short personalized greeting for the user + * @param cartItemCount number of items currently in the user's cart + * @param cartTotalUsd total value of the user's cart in US dollars + * @param recentOrderSummaries short human-readable summaries of the user's most recent orders + */ +public record MobileDashboardResponse( + String greeting, int cartItemCount, double cartTotalUsd, List recentOrderSummaries) { + /** No additional validation required. */ + public MobileDashboardResponse { + // no-op + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/dto/package-info.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/dto/package-info.java new file mode 100644 index 000000000000..43a23d0dbc4e --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/dto/package-info.java @@ -0,0 +1,28 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/** + * Response DTOs shaped by each BFF for its specific client (mobile dashboard, desktop dashboard). + */ +package com.iluwatar.bff.dto; diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/model/CartItem.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/CartItem.java new file mode 100644 index 000000000000..a71c4848c791 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/CartItem.java @@ -0,0 +1,43 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.model; + +/** + * A single line item inside a user's shopping cart, as returned by the cart service API. + * + * @param product the product being purchased + * @param quantity number of units of the product + */ +public record CartItem(Product product, int quantity) { + + /** + * Computes the line total for this cart item. + * + * @return quantity multiplied by unit price + */ + public double lineTotal() { + return quantity * product.priceUsd(); + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/model/Order.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/Order.java new file mode 100644 index 000000000000..82a52d12a15f --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/Order.java @@ -0,0 +1,39 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.model; + +/** + * A past order returned by the order service API. + * + * @param id order identifier + * @param productName name of the ordered product + * @param status current fulfillment status, e.g. "DELIVERED", "IN_TRANSIT" + */ +public record Order(String id, String productName, String status) { + /** No additional validation required. */ + public Order { + // no-op + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/model/Product.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/Product.java new file mode 100644 index 000000000000..cbd9942649f9 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/Product.java @@ -0,0 +1,40 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.model; + +/** + * Simple product record returned by the downstream Cart/Order services. Represents the data a + * catalog or cart entry carries before each BFF trims or reshapes it for its own client. + * + * @param id product identifier + * @param name display name of the product + * @param priceUsd unit price in US dollars + */ +public record Product(String id, String name, double priceUsd) { + /** No additional validation required. */ + public Product { + // no-op + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/model/SupplierRecord.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/SupplierRecord.java new file mode 100644 index 000000000000..2cd22e03ac3f --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/SupplierRecord.java @@ -0,0 +1,40 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.model; + +/** + * A supplier stock record returned by the supplier service API, used by the desktop back-office + * client to show inventory information that mobile customers never need to see. + * + * @param productId identifier of the product this record refers to + * @param supplierName name of the supplying vendor + * @param stockLevel units currently available from this supplier + */ +public record SupplierRecord(String productId, String supplierName, int stockLevel) { + /** No additional validation required. */ + public SupplierRecord { + // no-op + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/model/User.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/User.java new file mode 100644 index 000000000000..5c3b9252f937 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/User.java @@ -0,0 +1,40 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.model; + +/** + * Authenticated user profile returned by the customer authentication service API. Kept + * intentionally minimal; each BFF decides which of these fields its client actually needs. + * + * @param id unique user identifier + * @param displayName human-readable name of the user + * @param loyaltyTier loyalty program tier, e.g. "GOLD", "SILVER", "STANDARD" + */ +public record User(String id, String displayName, String loyaltyTier) { + /** No additional validation required. */ + public User { + // no-op + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/model/package-info.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/package-info.java new file mode 100644 index 000000000000..37d2855a8671 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/model/package-info.java @@ -0,0 +1,30 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/** + * Domain model records shared across downstream services: User, Product, CartItem, Order, and + * SupplierRecord. Each BFF consumes these raw domain objects and reshapes them into its own + * client-specific DTO. + */ +package com.iluwatar.bff.model; diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/package-info.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/package-info.java new file mode 100644 index 000000000000..ede18f2b22f9 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/package-info.java @@ -0,0 +1,29 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/** + * Backends For Frontends pattern: a dedicated gateway per client type (mobile, desktop) that + * aggregates only the downstream services each client actually needs. + */ +package com.iluwatar.bff; diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/AuthService.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/AuthService.java new file mode 100644 index 000000000000..a87b75b48bb6 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/AuthService.java @@ -0,0 +1,43 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.service; + +import com.iluwatar.bff.model.User; + +/** + * Represents the customer authentication service API from the diagram: a downstream microservice + * shared by every client-specific BFF. Each BFF calls this the same way; only what they do with the + * result differs. + */ +public interface AuthService { + + /** + * Looks up the authenticated user profile for the given id. + * + * @param userId identifier of the user to look up + * @return the matching {@link User} + */ + User getUser(String userId); +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/CartService.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/CartService.java new file mode 100644 index 000000000000..7ae24fba64bc --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/CartService.java @@ -0,0 +1,43 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.service; + +import com.iluwatar.bff.model.CartItem; +import java.util.List; + +/** + * Represents the cart service API from the diagram. In this example only the mobile and android + * clients need cart data, so only {@link com.iluwatar.bff.bff.MobileBff} calls this service. + */ +public interface CartService { + + /** + * Retrieves the current cart contents for a user. + * + * @param userId identifier of the user whose cart is requested + * @return the list of items currently in the user's cart + */ + List getCart(String userId); +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/OrderService.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/OrderService.java new file mode 100644 index 000000000000..b8e6ee8fa03e --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/OrderService.java @@ -0,0 +1,43 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.service; + +import com.iluwatar.bff.model.Order; +import java.util.List; + +/** + * Represents the order service API from the diagram. This downstream service is shared by every + * client-specific BFF, matching the fan-out shown for "order service API" in the pattern diagram. + */ +public interface OrderService { + + /** + * Retrieves the order history for a user. + * + * @param userId identifier of the user whose orders are requested + * @return the list of past orders for the user + */ + List getOrders(String userId); +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/SupplierService.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/SupplierService.java new file mode 100644 index 000000000000..ac7c2dfbc849 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/SupplierService.java @@ -0,0 +1,43 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.service; + +import com.iluwatar.bff.model.SupplierRecord; +import java.util.List; + +/** + * Represents the supplier service API from the diagram, reachable only from the intranet services + * server. Only back-office style clients (desktop app, chatbot) call this service. + */ +public interface SupplierService { + + /** + * Retrieves supplier stock records for a product. + * + * @param productName name of the product to check stock for + * @return the list of supplier stock records for the product + */ + List getSupplierRecords(String productName); +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemoryAuthService.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemoryAuthService.java new file mode 100644 index 000000000000..5c2ffc35958f --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemoryAuthService.java @@ -0,0 +1,58 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.service.impl; + +import com.iluwatar.bff.model.User; +import com.iluwatar.bff.service.AuthService; +import java.util.Map; + +/** + * In-memory stand-in for the real customer authentication service API. Real deployments would + * replace this with an HTTP/gRPC client; the BFFs are written against the {@link AuthService} + * interface, so swapping the implementation later requires no change to any BFF. + */ +public final class InMemoryAuthService implements AuthService { + + /** Users stored in memory, keyed by user id. */ + private final Map users; + + /** + * Creates the service with a fixed backing map of users, keyed by user id. + * + * @param userData the user data this service serves + */ + public InMemoryAuthService(final Map userData) { + this.users = userData; + } + + @Override + public User getUser(final String userId) { + var user = users.get(userId); + if (user == null) { + throw new IllegalArgumentException("Unknown user id: " + userId); + } + return user; + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemoryCartService.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemoryCartService.java new file mode 100644 index 000000000000..fed3b59da2c8 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemoryCartService.java @@ -0,0 +1,51 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.service.impl; + +import com.iluwatar.bff.model.CartItem; +import com.iluwatar.bff.service.CartService; +import java.util.List; +import java.util.Map; + +/** In-memory stand-in for the real cart service API. */ +public final class InMemoryCartService implements CartService { + + /** Carts stored in memory, keyed by user id. */ + private final Map> cartsByUserId; + + /** + * Creates the service with a fixed backing map of carts, keyed by user id. + * + * @param carts the cart data this service serves + */ + public InMemoryCartService(final Map> carts) { + this.cartsByUserId = carts; + } + + @Override + public List getCart(final String userId) { + return cartsByUserId.getOrDefault(userId, List.of()); + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemoryOrderService.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemoryOrderService.java new file mode 100644 index 000000000000..979956d06244 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemoryOrderService.java @@ -0,0 +1,51 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.service.impl; + +import com.iluwatar.bff.model.Order; +import com.iluwatar.bff.service.OrderService; +import java.util.List; +import java.util.Map; + +/** In-memory stand-in for the real order service API. */ +public final class InMemoryOrderService implements OrderService { + + /** Order histories stored in memory, keyed by user id. */ + private final Map> ordersByUserId; + + /** + * Creates the service with a fixed backing map of order histories, keyed by user id. + * + * @param orders the order data this service serves + */ + public InMemoryOrderService(final Map> orders) { + this.ordersByUserId = orders; + } + + @Override + public List getOrders(final String userId) { + return ordersByUserId.getOrDefault(userId, List.of()); + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemorySupplierService.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemorySupplierService.java new file mode 100644 index 000000000000..ac2d351db3a5 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/InMemorySupplierService.java @@ -0,0 +1,51 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.service.impl; + +import com.iluwatar.bff.model.SupplierRecord; +import com.iluwatar.bff.service.SupplierService; +import java.util.List; +import java.util.Map; + +/** In-memory stand-in for the real supplier service API, reachable only from the intranet. */ +public final class InMemorySupplierService implements SupplierService { + + /** Supplier records stored in memory, keyed by product name. */ + private final Map> recordsByProductName; + + /** + * Creates the service with a fixed backing map of supplier records, keyed by product name. + * + * @param records the supplier data this service serves + */ + public InMemorySupplierService(final Map> records) { + this.recordsByProductName = records; + } + + @Override + public List getSupplierRecords(final String productName) { + return recordsByProductName.getOrDefault(productName, List.of()); + } +} diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/package-info.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/package-info.java new file mode 100644 index 000000000000..fbdb5d026bc8 --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/impl/package-info.java @@ -0,0 +1,29 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/** + * In-memory implementations of the downstream service API interfaces, used for the pattern + * demonstration. Production deployments would replace these with real HTTP/gRPC clients. + */ +package com.iluwatar.bff.service.impl; diff --git a/backends-for-frontends/src/main/java/com/iluwatar/bff/service/package-info.java b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/package-info.java new file mode 100644 index 000000000000..05bfcb3911df --- /dev/null +++ b/backends-for-frontends/src/main/java/com/iluwatar/bff/service/package-info.java @@ -0,0 +1,29 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/** + * Downstream service API interfaces shared by all BFFs: AuthService, CartService, OrderService, and + * SupplierService. Each BFF wires in only the services its client requires. + */ +package com.iluwatar.bff.service; diff --git a/backends-for-frontends/src/test/java/com/iluwatar/bff/AppTest.java b/backends-for-frontends/src/test/java/com/iluwatar/bff/AppTest.java new file mode 100644 index 000000000000..d06d945c8c33 --- /dev/null +++ b/backends-for-frontends/src/test/java/com/iluwatar/bff/AppTest.java @@ -0,0 +1,41 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import org.junit.jupiter.api.Test; + +/** + * Tests that {@link App}'s demo entry point runs end-to-end without throwing, following the + * convention used throughout this repository for pattern demo apps. + */ +class AppTest { + + @Test + void mainShouldRunWithoutException() { + assertDoesNotThrow(() -> App.main(new String[] {})); + } +} diff --git a/backends-for-frontends/src/test/java/com/iluwatar/bff/bff/DesktopBffTest.java b/backends-for-frontends/src/test/java/com/iluwatar/bff/bff/DesktopBffTest.java new file mode 100644 index 000000000000..d4a2331b101b --- /dev/null +++ b/backends-for-frontends/src/test/java/com/iluwatar/bff/bff/DesktopBffTest.java @@ -0,0 +1,77 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.bff; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.iluwatar.bff.model.Order; +import com.iluwatar.bff.model.SupplierRecord; +import com.iluwatar.bff.model.User; +import com.iluwatar.bff.service.impl.InMemoryAuthService; +import com.iluwatar.bff.service.impl.InMemoryOrderService; +import com.iluwatar.bff.service.impl.InMemorySupplierService; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; + +/** Tests for {@link DesktopBff}. */ +class DesktopBffTest { + + private static final String USER_ID = "u-1"; + + @Test + void shouldAggregateOrdersAndSupplierStockIntoDesktopShape() { + var authService = new InMemoryAuthService(Map.of(USER_ID, new User(USER_ID, "Alice", "GOLD"))); + var orderService = + new InMemoryOrderService( + Map.of(USER_ID, List.of(new Order("o-1", "Headphones", "DELIVERED")))); + var supplierService = + new InMemorySupplierService( + Map.of("Headphones", List.of(new SupplierRecord("p-1", "Acme Audio", 30)))); + + var bff = new DesktopBff(authService, orderService, supplierService); + var response = bff.getDashboard(USER_ID); + + assertEquals("Welcome back, Alice", response.greeting()); + assertEquals("GOLD", response.loyaltyTier()); + assertTrue(response.orderStatuses().get(0).contains("Headphones")); + assertTrue(response.supplierStockSummaries().get(0).contains("Acme Audio")); + } + + @Test + void shouldReturnNoSupplierSummariesWhenNoOrdersExist() { + var authService = + new InMemoryAuthService(Map.of(USER_ID, new User(USER_ID, "Carol", "STANDARD"))); + var orderService = new InMemoryOrderService(Map.of(USER_ID, List.of())); + var supplierService = new InMemorySupplierService(Map.of()); + + var bff = new DesktopBff(authService, orderService, supplierService); + var response = bff.getDashboard(USER_ID); + + assertEquals(0, response.orderStatuses().size()); + assertEquals(0, response.supplierStockSummaries().size()); + } +} diff --git a/backends-for-frontends/src/test/java/com/iluwatar/bff/bff/MobileBffTest.java b/backends-for-frontends/src/test/java/com/iluwatar/bff/bff/MobileBffTest.java new file mode 100644 index 000000000000..f05a0be99b61 --- /dev/null +++ b/backends-for-frontends/src/test/java/com/iluwatar/bff/bff/MobileBffTest.java @@ -0,0 +1,83 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bff.bff; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.iluwatar.bff.model.CartItem; +import com.iluwatar.bff.model.Order; +import com.iluwatar.bff.model.Product; +import com.iluwatar.bff.model.User; +import com.iluwatar.bff.service.impl.InMemoryAuthService; +import com.iluwatar.bff.service.impl.InMemoryCartService; +import com.iluwatar.bff.service.impl.InMemoryOrderService; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; + +/** Tests for {@link MobileBff}. */ +class MobileBffTest { + + private static final String USER_ID = "u-1"; + + @Test + void shouldAggregateCartAndOrdersIntoMobileShape() { + var authService = new InMemoryAuthService(Map.of(USER_ID, new User(USER_ID, "Alice", "GOLD"))); + var product = new Product("p-1", "Headphones", 50.0); + var cartService = new InMemoryCartService(Map.of(USER_ID, List.of(new CartItem(product, 2)))); + var orderService = + new InMemoryOrderService( + Map.of(USER_ID, List.of(new Order("o-1", "Headphones", "DELIVERED")))); + + var bff = new MobileBff(authService, cartService, orderService); + var response = bff.getDashboard(USER_ID); + + assertEquals("Hi Alice!", response.greeting()); + assertEquals(1, response.cartItemCount()); + assertEquals(100.0, response.cartTotalUsd()); + assertTrue(response.recentOrderSummaries().get(0).contains("Headphones")); + } + + @Test + void shouldCapRecentOrderSummariesAtThree() { + var authService = new InMemoryAuthService(Map.of(USER_ID, new User(USER_ID, "Bob", "SILVER"))); + var cartService = new InMemoryCartService(Map.of(USER_ID, List.of())); + var orderService = + new InMemoryOrderService( + Map.of( + USER_ID, + List.of( + new Order("o-1", "A", "DELIVERED"), + new Order("o-2", "B", "DELIVERED"), + new Order("o-3", "C", "DELIVERED"), + new Order("o-4", "D", "DELIVERED")))); + + var bff = new MobileBff(authService, cartService, orderService); + var response = bff.getDashboard(USER_ID); + + assertEquals(3, response.recentOrderSummaries().size()); + } +} diff --git a/pom.xml b/pom.xml index b856945f3b1e..577e4d2811ea 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,7 @@ anti-corruption-layer arrange-act-assert async-method-invocation + backends-for-frontends balking bloc bridge