Task/member2#35
Merged
Merged
Conversation
added 5 commits
May 23, 2026 23:40
- Updated AuctionRepositoryTest, BidRepositoryTest, DatabaseManagerTest, and UserRepositoryTest to use temporary SQLite database files instead of in-memory databases for better isolation and persistence during tests. - Changed user roles from SELLER and BIDDER to USER in the test setup for consistency. - Added new integration tests for GalleryDetailBid and stress tests for concurrent bidding and polling. - Introduced ThumbnailExecutor for managing thumbnail loading in a separate thread pool. - Added a placeholder image for use in the application. - Created a CSV export file for auction data.
…ous view tracking
| // allow gallery to request showing a particular hero index after loading | ||
| public void showHeroImageIndex(int index) { | ||
| switch (index) { | ||
| case 0: if (heroImageView.getImage() != null) heroImageView.setImage(heroImageView.getImage()); break; |
| public void showHeroImageIndex(int index) { | ||
| switch (index) { | ||
| case 0: if (heroImageView.getImage() != null) heroImageView.setImage(heroImageView.getImage()); break; | ||
| case 1: if (thumb1View.getImage() != null) heroImageView.setImage(thumb1View.getImage()); break; |
| switch (index) { | ||
| case 0: if (heroImageView.getImage() != null) heroImageView.setImage(heroImageView.getImage()); break; | ||
| case 1: if (thumb1View.getImage() != null) heroImageView.setImage(thumb1View.getImage()); break; | ||
| case 2: if (thumb2View.getImage() != null) heroImageView.setImage(thumb2View.getImage()); break; |
| } | ||
|
|
||
| @FXML | ||
| private void handleThumb1Click(javafx.scene.input.MouseEvent e) { |
| } | ||
|
|
||
| @FXML | ||
| private void handleThumb2Click(javafx.scene.input.MouseEvent e) { |
| } | ||
|
|
||
| @FXML | ||
| private void handleThumb3Click(javafx.scene.input.MouseEvent e) { |
| } | ||
|
|
||
| @FXML | ||
| private void handleNavigateToLogin(MouseEvent event) { |
There was a problem hiding this comment.
Pull request overview
This PR expands the JavaFX client experience around browsing auctions and bidding, adds client-side polling/thumbnail loading utilities, improves RMI startup robustness on the server, and introduces new integration/stress tests while switching repository tests to file-backed SQLite for better isolation.
Changes:
- Implement gallery search, dynamic auction cards, and async thumbnail loading/caching; add richer auction detail view with polling and bid placement UI.
- Improve server startup behavior by setting/printing
java.rmi.server.hostnameand reusing an existing RMI registry when possible. - Add new integration/stress tests and switch existing repository tests from
:memory:SQLite to temporary file DBs.
Reviewed changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| src/test/java/com/auction/stress/ConcurrentBiddingAndPollingStressTest.java | Adds concurrency stress test for bidding and shutdown behavior test for PollingService. |
| src/test/java/com/auction/server/repository/UserRepositoryTest.java | Uses temp file SQLite DB per test instead of :memory:. |
| src/test/java/com/auction/server/repository/DatabaseManagerTest.java | Uses temp file SQLite DB per test instead of :memory:. |
| src/test/java/com/auction/server/repository/BidRepositoryTest.java | Uses temp file SQLite DB per test instead of :memory:. |
| src/test/java/com/auction/server/repository/AuctionRepositoryTest.java | Uses temp file SQLite DB per test instead of :memory:. |
| src/test/java/com/auction/integration/GalleryDetailBidIntegrationTest.java | Adds end-to-end integration coverage for gallery/detail and bid flow. |
| src/main/resources/fxml/login.fxml | Restructures login layout and keeps admin troubleshooting panel. |
| src/main/resources/fxml/gallery.fxml | Wires search field/button and binds gallery nodes via fx:id for controller rendering. |
| src/main/resources/fxml/auction_detail.fxml | Replaces placeholders with real labels/inputs, image views, and bid controls. |
| src/main/resources/css/style.css | Adds styling hooks for image placeholders/thumbnails. |
| src/main/java/com/auction/server/core/ServerLauncher.java | Attempts to auto-set java.rmi.server.hostname for client reachability. |
| src/main/java/com/auction/server/core/ServerBootstrap.java | Reuses existing RMI registry on port if already exported. |
| src/main/java/com/auction/client/service/ThumbnailExecutor.java | Introduces shared daemon thread pool for thumbnail/background tasks. |
| src/main/java/com/auction/client/service/PollingService.java | Implements scheduled polling loop and shutdown behavior. |
| src/main/java/com/auction/client/core/ClientContext.java | Adds previousViewName to improve navigation/back behavior. |
| src/main/java/com/auction/client/controllers/UserDashboardController.java | Sets previous view before navigation to gallery/detail. |
| src/main/java/com/auction/client/controllers/RegistrationController.java | Adds handler to navigate back to login from registration screen. |
| src/main/java/com/auction/client/controllers/GalleryController.java | Implements gallery loading, search/filtering, card rendering, and thumbnail loading. |
| src/main/java/com/auction/client/controllers/ConnectController.java | Improves UX messaging/defaults when no servers are discovered. |
| exports/my_auctions_export.csv | Adds a CSV header file (appears to be a generated artifact). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
30
to
+41
| public void startPolling(int auctionId, Consumer<AuctionItem> onUpdate) { | ||
| // TODO: schedule getAuctionById every 2s, call onUpdate with result | ||
| scheduler = Executors.newSingleThreadScheduledExecutor(); | ||
| scheduler.scheduleAtFixedRate(() -> { | ||
| try{ | ||
| AuctionItem item = service.getAuctionById(auctionId); | ||
| onUpdate.accept(item); | ||
| } catch(Exception e){ | ||
| System.err.println(e.getMessage()); | ||
| e.printStackTrace(); | ||
| } | ||
| }, 0, 2, TimeUnit.SECONDS); |
Comment on lines
33
to
+41
| @FXML | ||
| public void initialize() { | ||
| // TODO: load active auctions, display in grid/list, fetch thumbnails | ||
| try { | ||
| var context = ClientContext.getInstance(); | ||
| var service = context.getRmiProvider().getService(); | ||
| List<AuctionItem> items = service.getActiveAuctions(); | ||
| allAuctions = (items == null) ? java.util.List.of() : items; | ||
| Platform.runLater(() -> renderAuctions(allAuctions)); | ||
| } catch (Exception e) { |
Comment on lines
+108
to
+151
| loadThumbnailAsync(item.getId(), 0, thumbView); | ||
|
|
||
| Button view = new Button("View"); | ||
| view.getStyleClass().addAll("primary-button"); | ||
| view.setOnAction(evt -> { | ||
| try { | ||
| ClientContext context = ClientContext.getInstance(); | ||
| context.setPreviousViewName("gallery.fxml"); | ||
| Object ctrl = context.getViewLoader().loadView("auction_detail.fxml"); | ||
| if (ctrl instanceof AuctionDetailController) { | ||
| ((AuctionDetailController) ctrl).loadAuction(item.getId()); | ||
| } | ||
| } catch (IOException ex) { | ||
| ex.printStackTrace(); | ||
| } | ||
| }); | ||
|
|
||
| // small thumbnail rail (up to 3 thumbnails) | ||
| javafx.scene.layout.HBox rail = new javafx.scene.layout.HBox(6); | ||
| for (int i = 0; i < 3; i++) { | ||
| ImageView small = new ImageView(); | ||
| small.setFitWidth(64); | ||
| small.setFitHeight(48); | ||
| small.setPreserveRatio(true); | ||
| small.getStyleClass().add("image-thumb"); | ||
| final int idx = i; | ||
| small.setOnMouseClicked(e -> { | ||
| try { | ||
| ClientContext context = ClientContext.getInstance(); | ||
| context.setPreviousViewName("gallery.fxml"); | ||
| Object ctrl = context.getViewLoader().loadView("auction_detail.fxml"); | ||
| if (ctrl instanceof AuctionDetailController) { | ||
| ((AuctionDetailController) ctrl).loadAuction(item.getId()); | ||
| ((AuctionDetailController) ctrl).showHeroImageIndex(idx); | ||
| } | ||
| } catch (IOException ex) { | ||
| ex.printStackTrace(); | ||
| } | ||
| }); | ||
| // prefetch hero on hover for snappier detail view | ||
| small.setOnMouseEntered(e -> loadThumbnailToCache(item.getId(), 0)); | ||
| loadThumbnailAsync(item.getId(), i, small); | ||
| rail.getChildren().add(small); | ||
| } |
Comment on lines
216
to
+225
| @FXML | ||
| private void handleBackToDashboard() { | ||
| try { | ||
| com.auction.client.core.ClientContext.getInstance().getViewLoader().loadView("user_dashboard.fxml"); | ||
| } catch (java.io.IOException e) { | ||
| throw new RuntimeException(e); | ||
| ClientContext context = ClientContext.getInstance(); | ||
| String targetView = context.getPreviousViewName(); | ||
| if (targetView == null || targetView.isBlank()) { | ||
| targetView = "user_dashboard.fxml"; | ||
| } | ||
| context.getViewLoader().loadView(targetView); | ||
| } catch (IOException e) { |
| @FXML private javafx.scene.image.ImageView thumb1View; | ||
| @FXML private javafx.scene.image.ImageView thumb2View; | ||
| @FXML private javafx.scene.image.ImageView thumb3View; | ||
| private final java.util.concurrent.Executor executor = java.util.concurrent.Executors.newCachedThreadPool(); |
Comment on lines
+16
to
+26
| if (existing == null || existing.isBlank()) { | ||
| try { | ||
| String hostAddr = InetAddress.getLocalHost().getHostAddress(); | ||
| System.setProperty("java.rmi.server.hostname", hostAddr); | ||
| System.out.println("[RTDAS] Set java.rmi.server.hostname to " + hostAddr); | ||
| } catch (Exception ex) { | ||
| System.err.println("[RTDAS] Failed to auto-detect hostname: " + ex.getMessage()); | ||
| } | ||
| } else { | ||
| System.out.println("[RTDAS] java.rmi.server.hostname=" + existing); | ||
| } |
Comment on lines
+446
to
+464
| .image-placeholder, | ||
| .image-thumb { | ||
| -fx-background-color: #0b0f15; | ||
| -fx-background-radius: 12px; | ||
| -fx-border-color: rgba(48, 54, 61, 0.9); | ||
| -fx-border-radius: 12px; | ||
| -fx-border-width: 1px; | ||
| -fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.28), 14, 0, 0, 4); | ||
| } | ||
|
|
||
| .image-thumb { | ||
| -fx-background-radius: 10px; | ||
| -fx-border-radius: 10px; | ||
| } | ||
|
|
||
| .image-placeholder:hover, | ||
| .image-thumb:hover { | ||
| -fx-border-color: #58a6ff; | ||
| } |
| @@ -0,0 +1 @@ | |||
| AuctionID,Title,Category,StartingPrice,FinalPrice,Winner,Status,StartTime,EndTime | |||
Comment on lines
+98
to
+126
| var pool = Executors.newFixedThreadPool(bidders); | ||
| CountDownLatch done = new CountDownLatch(bidders); | ||
|
|
||
| for (int i = 0; i < bidders; i++) { | ||
| final String token = bidderTokens.get(i); | ||
| final long bump = i + 1; | ||
| pool.submit(() -> { | ||
| try { | ||
| for (int attempt = 0; attempt < 5; attempt++) { | ||
| AuctionItem snapshot = service.getAuctionById(auctionId); | ||
| long current = snapshot.getCurrentBidCents(); | ||
| long minIncrement = (current + 19) / 20; | ||
| long amount = current + minIncrement + bump; | ||
| try { | ||
| service.placeBid(auctionId, amount, current, token); | ||
| } catch (AuctionException ignored) { | ||
| // expected under contention; retry with fresh snapshot | ||
| } | ||
| } | ||
| } catch (Exception ignored) { | ||
| } finally { | ||
| done.countDown(); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| assertTrue(done.await(15, TimeUnit.SECONDS), "Concurrent bid workers did not complete in time"); | ||
| pool.shutdownNow(); | ||
|
|
Comment on lines
+142
to
146
| com.auction.client.core.ClientContext context = com.auction.client.core.ClientContext.getInstance(); | ||
| context.setCurrentAuctionId(selected.getId()); | ||
| context.setPreviousViewName("user_dashboard.fxml"); | ||
| context.getViewLoader().loadView("auction_detail.fxml"); | ||
| } catch (java.io.IOException e) { |
bella-247
approved these changes
May 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.