### Client Connection Handler and Message Loop (Java) Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt This Java code defines the AuctionHandler class, responsible for managing individual client connections. The constructor initializes input/output streams, assigns a unique client ID, and starts a new handler thread. The run method continuously reads messages from the client, deserializes them, and dispatches them for handling. It ensures proper cleanup of resources and client removal upon connection closure or errors. ```java public AuctionHandler(Socket socket, Database database, ConcurrentHashMap auctionSemaphores) throws IOException { this.socket = socket; this.input = new BufferedReader(new InputStreamReader(socket.getInputStream())); this.output = new PrintWriter(socket.getOutputStream(), true); this.auctionSemaphores = auctionSemaphores; this.database = database; this.gson = new GsonBuilder().create(); this.clientId = UUID.randomUUID(); connectedClients.put(clientId, output); System.out.println("NEW CLIENT: " + clientId + " | CLIENT COUNT: " + connectedClients.size()); this.start(); // Start handler thread } @Override public void run() { try { while (!socket.isClosed()) { String jsonMessage = input.readLine(); if (jsonMessage == null) { System.out.println("Connection closed by client"); break; } AuctionMessage message = gson.fromJson(jsonMessage, AuctionMessage.class); handleMessage(message); } } catch (IOException e) { System.err.println("Connection error: " + e.getMessage()); } finally { connectedClients.remove(clientId); closeConnection(); } } ``` -------------------------------- ### Java Server Initialization and Connection Handling Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt Initializes the Bidly auction server on a specified port and registers a shutdown hook for graceful termination. The server accepts persistent socket connections, and each connection is handled by a dedicated thread. Dependencies include the core.Server class. ```java import core.Server; public class Main { public static void main(String[] args) { Server server = new Server(8080); // Graceful shutdown hook Runtime.getRuntime().addShutdownHook(new Thread(() -> { System.out.println("Shutting down server..."); server.shutdown(); })); // Start accepting connections server.start(); // Blocks until server.shutdown() is called } } // Expected Output: // Server started on port 8080 // NEW CLIENT: a3c7e9d1-4f8b-4c3a-9e2f-1d3c4b5a6e7f | CLIENT COUNT: 0 ``` -------------------------------- ### Placing a Bid - JSON and Java with Concurrency Control Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt Illustrates the JSON format for client requests to place bids and the server's responses (accepted or rejected). It includes Java code that handles bid placement, performing price validation and utilizing a semaphore for concurrency control to manage simultaneous bid attempts. ```json // Client Request: { "type": "PLACE_BID", "data": { "productId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "bidder": "alice", "price": 155.00 } } // Server Response (Accepted): { "type": "BID_ACCEPTED", "data": "Bid accepted" } // Server Response (Rejected): { "type": "BID_REJECTED", "data": "Bid rejected. Minimum allowed bid is 155.00 (current price 150.00 + minimum increment 5.00)" } ``` ```java // Bid processing with concurrency control (AuctionHandler.java:101-145) private void handlePlaceBid(AuctionMessage message) { JsonObject data = gson.toJsonTree(message.getData()).getAsJsonObject(); BidMessage bidMessage = gson.fromJson(data, BidMessage.class); UUID auctionId = bidMessage.getProductId(); CountingSemaphore cs = auctionSemaphores.computeIfAbsent( auctionId, k -> new CountingSemaphore(1) ); cs.P(); // Acquire lock try { Auction auction = database.getAuction(auctionId); if (auction == null) { writeResponse(new AuctionMessage( MessageType.BID_REJECTED, "Auction not found" )); return; } if (auction.canBid(bidMessage.getPrice())) { Bid bid = new Bid( UUID.randomUUID(), bidMessage.getBidder(), bidMessage.getProductId(), bidMessage.getPrice() ); database.saveBid(bid); writeResponse(new AuctionMessage( MessageType.BID_ACCEPTED, "Bid accepted" )); broadcastAuctionUpdate(); } else { BigDecimal minimumAllowedBid = auction.getMinimumBidIncrement() .add(auction.getCurrentPrice()); writeResponse(new AuctionMessage( MessageType.BID_REJECTED, String.format( "Bid rejected. Minimum allowed bid is %s (current price %s + minimum increment %s)", minimumAllowedBid, auction.getCurrentPrice(), auction.getMinimumBidIncrement() ) )); } } finally { cs.V(); // Release lock } } ``` -------------------------------- ### Place a Bid Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt Allows a client to place a bid on a specific product. The backend validates the bid price against the current price and minimum bid increment, and uses a semaphore for concurrency control. ```APIDOC ## Place a Bid ### Description Allows a client to place a bid on a specific product. The backend validates the bid price against the current price and minimum bid increment, and uses a semaphore for concurrency control. ### Method POST ### Endpoint /bid ### Parameters #### Request Body - **type** (string) - Required - The type of the message, should be "PLACE_BID". - **data** (object) - Required - Contains the bid details. - **productId** (string) - Required - The ID of the product to bid on. - **bidder** (string) - Required - The username of the bidder. - **price** (number) - Required - The amount of the bid. ### Request Example ```json { "type": "PLACE_BID", "data": { "productId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "bidder": "alice", "price": 155.00 } } ``` ### Response #### Success Response (200 - BID_ACCEPTED) - **type** (string) - The type of the response, should be "BID_ACCEPTED". - **data** (string) - A confirmation message, e.g., "Bid accepted". #### Rejected Response (200 - BID_REJECTED) - **type** (string) - The type of the response, should be "BID_REJECTED". - **data** (string) - A message explaining why the bid was rejected, including the minimum allowed bid. #### Response Example (Accepted) ```json { "type": "BID_ACCEPTED", "data": "Bid accepted" } ``` #### Response Example (Rejected) ```json { "type": "BID_REJECTED", "data": "Bid rejected. Minimum allowed bid is 155.00 (current price 150.00 + minimum increment 5.00)" } ``` ``` -------------------------------- ### Listing Active Auctions - JSON and Java Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt Demonstrates the JSON structure for requesting and receiving active auction data, including current prices and bidding history. It also shows Java code for retrieving active auctions and their associated bids from a database. ```json // Client Request: { "type": "LIST_AUCTIONS", "data": null } // Server Response: { "type": "LIST_AUCTIONS", "data": [ { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "name": "Vintage Camera", "startingPrice": 100.00, "currentPrice": 150.00, "startTime": 1728500000, "endTime": 1729000000, "seller": "john_doe", "minimumBidIncrement": 5.00, "status": "PENDING", "biddingHistory": [ { "id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6", "userName": "alice", "auctionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "price": 150.00, "timestamp": 1728600000 } ] } ] } ``` ```java // Database auction retrieval (Database.java:16-20) public List loadActiveAuctions() { List activeAuctions = new ArrayList<>(auctions.values()); activeAuctions.forEach(this::loadBidsForAuction); return activeAuctions; } // Loading bids for each auction (Database.java:22-25) private void loadBidsForAuction(Auction auction) { Set bids = auctionBids.getOrDefault(auction.getId(), new HashSet<>()); bids.forEach(auction::addBid); } ``` -------------------------------- ### Java Database Operations for Auctions and Bids Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt This Java code defines an in-memory database for managing auctions and bids. It includes thread-safe methods for initializing the database, creating auctions, saving bids, and checking for unique auction names. The `Database` class uses HashMaps to store auction and bid data, ensuring efficient lookups and modifications. ```java public class Database { private final Map auctions; private final Map> auctionBids; public Database(Map auctions, Map> auctionBids) { this.auctions = auctions; this.auctionBids = auctionBids; } public void createAuction(Auction auction) { auctions.put(auction.getId(), auction); auctionBids.putIfAbsent(auction.getId(), new HashSet<>()); } public void saveBid(Bid bid) { Auction auction = auctions.get(bid.getAuctionId()); if (auction != null) { Set bids = auctionBids.computeIfAbsent( bid.getAuctionId(), k -> new HashSet<>() ); bids.add(bid); auction.addBid(bid); } } public boolean isAuctionNameTaken(String name) { String normalizedName = name.toLowerCase(); return auctions.values().stream() .anyMatch(auction -> auction.getName().toLowerCase().equals(normalizedName) ); } } ``` -------------------------------- ### Java Auction Creation Handling Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt Handles the creation of new auctions on the server side. It validates the uniqueness of the auction name before creating it and persisting it to the database. Upon successful creation, it sends an acceptance response to the client and broadcasts an update to all connected clients. This method synchronizes on the lowercase auction name to prevent race conditions. ```java // Server-side handling (AuctionHandler.java:147-175) private void handleCreateAuction(AuctionMessage message) { JsonObject data = gson.toJsonTree(message.getData()).getAsJsonObject(); String auctionName = data.get("name").getAsString().toLowerCase(); synchronized (auctionName.intern()) { if (database.isAuctionNameTaken(auctionName)) { writeResponse(new AuctionMessage( MessageType.AUCTION_CREATION_REJECTED, "Auction name already taken" )); return; } Auction auction = new Auction( data.get("name").getAsString(), data.get("startingPrice").getAsBigDecimal(), data.get("endTime").getAsLong(), data.get("seller").getAsString(), data.get("minimumBidIncrement").getAsBigDecimal() ); auction.setId(UUID.randomUUID()); database.createAuction(auction); writeResponse(new AuctionMessage( MessageType.AUCTION_CREATION_ACCEPTED, auction.getId() )); broadcastAuctionUpdate(); } } ``` -------------------------------- ### Broadcast Auction Updates to Clients (Java) Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt This Java code broadcasts the current list of active auctions to all connected clients. It loads auction data from the database and serializes it into an AuctionMessage before sending it to each client's PrintWriter. This is triggered after successful auction creation or bid placement. It handles potential exceptions during broadcasting. ```java private static void broadcastAuctionUpdate() { try { List auctions = database.loadActiveAuctions(); AuctionMessage message = new AuctionMessage( MessageType.LIST_AUCTIONS, auctions ); System.out.println("Broadcasting auction update to " + connectedClients.size()); for (PrintWriter client : connectedClients.values()) { client.println(gson.toJson(message)); } } catch (Exception e) { System.err.println("Error broadcasting auction update: " + e.getMessage()); } } ``` -------------------------------- ### Custom Counting Semaphore Implementation (Java) Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt This Java code provides a custom implementation of a counting semaphore. It allows for controlling access to a limited number of resources. The P() method decrements the semaphore value, blocking if it's zero, while the V() method increments it and notifies waiting threads. This is used for auction-level concurrency control. ```java public class CountingSemaphore { int value; public CountingSemaphore(int initValue) { this.value = initValue; } public synchronized void P() { while (value == 0) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } value--; } public synchronized void V() { value++; notify(); } } ``` -------------------------------- ### List Active Auctions Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt Retrieves a list of all active auctions, including their current prices and bidding history. This endpoint is used by clients to display available auctions. ```APIDOC ## List Active Auctions ### Description Retrieves a list of all active auctions, including their current prices and bidding history. This endpoint is used by clients to display available auctions. ### Method POST ### Endpoint /auctions ### Parameters #### Request Body - **type** (string) - Required - The type of the message, should be "LIST_AUCTIONS". - **data** (null) - Required - This field should be null for this request. ### Request Example ```json { "type": "LIST_AUCTIONS", "data": null } ``` ### Response #### Success Response (200) - **type** (string) - The type of the response, should be "LIST_AUCTIONS". - **data** (array) - An array of auction objects. - **id** (string) - The unique identifier for the auction. - **name** (string) - The name of the auction item. - **startingPrice** (number) - The initial price of the auction. - **currentPrice** (number) - The current highest bid price. - **startTime** (integer) - The Unix timestamp when the auction started. - **endTime** (integer) - The Unix timestamp when the auction will end. - **seller** (string) - The username of the auction seller. - **minimumBidIncrement** (number) - The minimum amount by which a bid must increase. - **status** (string) - The current status of the auction (e.g., "PENDING", "ACTIVE", "ENDED"). - **biddingHistory** (array) - An array of bid objects for this auction. - **id** (string) - The unique identifier for the bid. - **userName** (string) - The username of the bidder. - **auctionId** (string) - The ID of the auction this bid belongs to. - **price** (number) - The price of the bid. - **timestamp** (integer) - The Unix timestamp when the bid was placed. #### Response Example ```json { "type": "LIST_AUCTIONS", "data": [ { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "name": "Vintage Camera", "startingPrice": 100.00, "currentPrice": 150.00, "startTime": 1728500000, "endTime": 1729000000, "seller": "john_doe", "minimumBidIncrement": 5.00, "status": "PENDING", "biddingHistory": [ { "id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6", "userName": "alice", "auctionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "price": 150.00, "timestamp": 1728600000 } ] } ] } ``` ``` -------------------------------- ### Message Protocol Definitions (Java) Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt This Java code defines the message types and structure used for communication between the client and server in the Bidly application. MessageType is an enum listing all supported operations, while AuctionMessage is a class that encapsulates the message type and associated data, ensuring a standardized communication protocol. ```java public enum MessageType { LIST_AUCTIONS, ERROR_LIST_AUCTIONS, PLACE_BID, BID_ACCEPTED, BID_REJECTED, CREATE_AUCTION, AUCTION_CREATION_ACCEPTED, AUCTION_CREATION_REJECTED, ERROR } ``` ```java public class AuctionMessage implements Serializable { private final MessageType type; private final Object data; public AuctionMessage(MessageType type, Object data) { this.type = type; this.data = data; } public MessageType getType() { return type; } public Object getData() { return data; } } ``` -------------------------------- ### Bid Validation Logic in Auction Model - Java Source: https://context7.com/fahreddinozcan/bidly-backend/llms.txt Details the Java method within the Auction model responsible for validating bid amounts. This logic checks if the bid is placed before the auction ends and if it meets the minimum bid increment requirement based on the current price. ```java // Bid validation method (Auction.java:128-135) public boolean canBid(BigDecimal bidAmount) { // Check if auction has ended if (System.currentTimeMillis() / 1000 >= endTime) { return false; } // Validate bid meets minimum increment requirement BigDecimal minimumBid = currentPrice.add(minimumBidIncrement); return bidAmount.compareTo(minimumBid) >= 0; } // Example usage: Auction auction = new Auction( "Laptop", new BigDecimal("500.00"), System.currentTimeMillis() / 1000 + 3600, "seller123", new BigDecimal("10.00") ); // Valid bid boolean valid = auction.canBid(new BigDecimal("510.00")); // true // Invalid bid (below minimum increment) boolean invalid = auction.canBid(new BigDecimal("505.00")); // false ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.