|
5 | 5 | import org.springframework.web.bind.annotation.RequestMapping; |
6 | 6 | import org.springframework.web.bind.annotation.RestController; |
7 | 7 | import org.springframework.web.bind.annotation.CrossOrigin; |
| 8 | +import org.springframework.web.bind.annotation.PathVariable; |
8 | 9 | import org.springframework.http.MediaType; |
| 10 | +import org.springframework.http.HttpStatus; |
| 11 | +import org.springframework.http.ResponseEntity; |
9 | 12 | import org.springframework.util.StreamUtils; |
10 | 13 | import java.io.*; |
| 14 | +import java.net.URI; |
11 | 15 | import org.springframework.web.bind.annotation.ResponseBody; |
12 | 16 | import org.apache.commons.io.IOUtils; |
13 | 17 | import java.util.concurrent.ThreadLocalRandom; |
14 | 18 | import java.util.HashMap; |
| 19 | +import java.util.Optional; |
15 | 20 | import org.springframework.web.bind.annotation.RequestParam; |
16 | 21 | import java.util.concurrent.TimeoutException; |
17 | 22 | import org.springframework.web.bind.annotation.RequestHeader; |
@@ -44,15 +49,67 @@ public String home() { |
44 | 49 | value = "/banners/{id}", |
45 | 50 | produces = MediaType.IMAGE_JPEG_VALUE |
46 | 51 | ) |
47 | | - public @ResponseBody byte[] getImageWithMediaType() throws IOException { |
48 | | - logger.info("/banners/{id} called"); |
49 | | - int randomNum = ThreadLocalRandom.current().nextInt(1, 3 + 1); |
50 | | - String imagePath = "/static/ads/ad" + randomNum + ".jpg"; |
51 | | - InputStream in = getClass() |
52 | | - .getResourceAsStream(imagePath); |
| 52 | + public @ResponseBody byte[] getImageWithMediaType(@PathVariable String id) throws IOException { |
| 53 | + logger.info("/banners/{} called", id); |
| 54 | + |
| 55 | + // Map the image path to the correct static file |
| 56 | + String imagePath; |
| 57 | + switch (id) { |
| 58 | + case "1.jpg": |
| 59 | + imagePath = "/static/ads/ad1.jpg"; |
| 60 | + break; |
| 61 | + case "2.jpg": |
| 62 | + imagePath = "/static/ads/ad2.jpg"; |
| 63 | + break; |
| 64 | + case "3.jpg": |
| 65 | + imagePath = "/static/ads/ad3.jpg"; |
| 66 | + break; |
| 67 | + default: |
| 68 | + // Fallback to random image if unknown |
| 69 | + int randomNum = ThreadLocalRandom.current().nextInt(1, 3 + 1); |
| 70 | + imagePath = "/static/ads/ad" + randomNum + ".jpg"; |
| 71 | + logger.warn("Unknown image id: {}, using random image", id); |
| 72 | + } |
| 73 | + |
| 74 | + InputStream in = getClass().getResourceAsStream(imagePath); |
| 75 | + if (in == null) { |
| 76 | + logger.error("Image not found: {}", imagePath); |
| 77 | + throw new IOException("Image not found: " + imagePath); |
| 78 | + } |
53 | 79 | return IOUtils.toByteArray(in); |
54 | 80 | } |
55 | 81 |
|
| 82 | + @CrossOrigin(origins = {"*"}) |
| 83 | + @RequestMapping("/click/{id}") |
| 84 | + public ResponseEntity<Void> handleAdClick(@PathVariable Long id) { |
| 85 | + logger.info("Ad click for id: " + id); |
| 86 | + |
| 87 | + Optional<Advertisement> adOptional = advertisementRepository.findById(id); |
| 88 | + if (adOptional.isPresent()) { |
| 89 | + Advertisement ad = adOptional.get(); |
| 90 | + String clickUrl = ad.getClickUrl(); |
| 91 | + |
| 92 | + // Log the click for analytics |
| 93 | + logger.info("Redirecting ad '{}' (id: {}) to: {}", ad.getName(), id, clickUrl); |
| 94 | + |
| 95 | + if (clickUrl != null && !clickUrl.isEmpty()) { |
| 96 | + // Return a redirect response to the click URL |
| 97 | + return ResponseEntity.status(HttpStatus.FOUND) |
| 98 | + .location(URI.create(clickUrl)) |
| 99 | + .build(); |
| 100 | + } else { |
| 101 | + // Default redirect if no clickUrl is set |
| 102 | + logger.warn("No clickUrl set for ad id: " + id + ", redirecting to homepage"); |
| 103 | + return ResponseEntity.status(HttpStatus.FOUND) |
| 104 | + .location(URI.create("/")) |
| 105 | + .build(); |
| 106 | + } |
| 107 | + } else { |
| 108 | + logger.error("Ad not found for id: " + id); |
| 109 | + return ResponseEntity.notFound().build(); |
| 110 | + } |
| 111 | + } |
| 112 | + |
56 | 113 | @CrossOrigin(origins = {"*"}) |
57 | 114 | @RequestMapping( |
58 | 115 | value = "/ads", |
@@ -95,9 +152,56 @@ public static void main(String[] args) { |
95 | 152 | public CommandLineRunner initDb(AdvertisementRepository repository) { |
96 | 153 | return args -> { |
97 | 154 | if (repository.count() == 0) { |
98 | | - repository.save(new Advertisement("Discount Clothing", "1.jpg")); |
99 | | - repository.save(new Advertisement("Cool Hats", "2.jpg")); |
100 | | - repository.save(new Advertisement("Nice Bags", "3.jpg")); |
| 155 | + // Create ads with meaningful click URLs that point to relevant frontend pages |
| 156 | + // Based on actual image content, the files are mislabeled |
| 157 | + // Image 1.jpg shows Discount Clothing content, 2.jpg shows Cool Hats content |
| 158 | + repository.save(new Advertisement("Discount Clothing", "1.jpg", "/discount-clothing")); |
| 159 | + repository.save(new Advertisement("Cool Hats", "2.jpg", "/cool-hats")); |
| 160 | + repository.save(new Advertisement("Nice Bags", "3.jpg", "/nice-bags")); |
| 161 | + logger.info("Initialized database with 3 advertisements with click URLs"); |
| 162 | + } else { |
| 163 | + // Always update existing ads to ensure they have the correct click URLs |
| 164 | + List<Advertisement> existingAds = repository.findAll(); |
| 165 | + boolean needsUpdate = false; |
| 166 | + |
| 167 | + for (Advertisement ad : existingAds) { |
| 168 | + String oldClickUrl = ad.getClickUrl(); |
| 169 | + switch (ad.getName()) { |
| 170 | + case "Discount Clothing": |
| 171 | + if (!"/discount-clothing".equals(oldClickUrl) || !"1.jpg".equals(ad.getPath())) { |
| 172 | + ad.setClickUrl("/discount-clothing"); |
| 173 | + ad.setPath("1.jpg"); |
| 174 | + needsUpdate = true; |
| 175 | + logger.info("Updated '{}' clickUrl from '{}' to '/discount-clothing' and path to '1.jpg'", ad.getName(), oldClickUrl); |
| 176 | + } |
| 177 | + break; |
| 178 | + case "Cool Hats": |
| 179 | + if (!"/cool-hats".equals(oldClickUrl) || !"2.jpg".equals(ad.getPath())) { |
| 180 | + ad.setClickUrl("/cool-hats"); |
| 181 | + ad.setPath("2.jpg"); |
| 182 | + needsUpdate = true; |
| 183 | + logger.info("Updated '{}' clickUrl from '{}' to '/cool-hats' and path to '2.jpg'", ad.getName(), oldClickUrl); |
| 184 | + } |
| 185 | + break; |
| 186 | + case "Nice Bags": |
| 187 | + if (!"/nice-bags".equals(oldClickUrl) || !"3.jpg".equals(ad.getPath())) { |
| 188 | + ad.setClickUrl("/nice-bags"); |
| 189 | + ad.setPath("3.jpg"); |
| 190 | + needsUpdate = true; |
| 191 | + logger.info("Updated '{}' clickUrl from '{}' to '/nice-bags' and path to '3.jpg'", ad.getName(), oldClickUrl); |
| 192 | + } |
| 193 | + break; |
| 194 | + default: |
| 195 | + logger.info("Unknown ad name: '{}', leaving clickUrl unchanged", ad.getName()); |
| 196 | + } |
| 197 | + } |
| 198 | + |
| 199 | + if (needsUpdate) { |
| 200 | + repository.saveAll(existingAds); |
| 201 | + logger.info("Successfully updated existing ads with correct click URLs"); |
| 202 | + } else { |
| 203 | + logger.info("All ads already have correct click URLs, no update needed"); |
| 204 | + } |
101 | 205 | } |
102 | 206 | }; |
103 | 207 | } |
|
0 commit comments