Я относительно новичок в Java и работал над своим личным проектом. Мне удалось построить его синхронно. Просто чтобы узнать больше, я хотел начать делать это асинхронно. Это система управления заказами, включающая сущности «Клиент», «Заказ» и «Элементы заказа». Первым методом, который я начал делать синхронным, был «createOrder».
Мой контроллер:
Я относительно новичок в Java и работал над своим личным проектом. Мне удалось построить его синхронно. Просто чтобы узнать больше, я хотел начать делать это асинхронно. Это система управления заказами, включающая сущности «Клиент», «Заказ» и «Элементы заказа». Первым методом, который я начал делать синхронным, был «createOrder». Мой контроллер: [code]@PostMapping("/place") public CompletableFuture createOrder(@RequestBody OrderRequest orderRequest) { String username = getAuthenticatedUsername(); return orderService.createOrder(orderRequest , username) .thenApply(order -> { OrderStatusResponse orderResponse = new OrderStatusResponse(ORDER_PLACED, order.getOrderId()); return new ResponseEntity(orderResponse, HttpStatus.OK); }) .exceptionally(ex -> { System.out.println(ex.getMessage()); return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR); }); } [/code] Моя служба: [code]public CompletableFuture createOrder(OrderRequest orderRequest) { try { String username = SecurityContextHolder.getContext().getAuthentication().getName(); Customer authenticatedCustomer = customerRepository.findByUsername(username) .orElseThrow(() -> new CustomerNotFoundException("Authenticated customer not found"));
validateOrderRequest(orderRequest);
Orders order = new Orders(); order.setCustomer(authenticatedCustomer); order.setStatus(ORDER_PLACED); order.setTimestamp(orderRequest.getTimestamp()); order.setTotalAmount(orderRequest.getTotalAmount());
List orderItems = orderRequest.getOrderItems().stream() .map(itemRequest -> new OrderItems(order, itemRequest.getProductId(), itemRequest.getQuantity(), itemRequest.getPrice())) .collect(Collectors.toList());
order.setOrderItems(orderItems);
return CompletableFuture.completedFuture(orderRepository.save(order)); } catch (DataIntegrityViolationException e) { throw new InvalidOrder("Unable to save order. Please check the provided data."); } } [/code] Моя конфигурация безопасности: [code]@Configuration @EnableWebSecurity public class SecurityConfig{
private final JwtAuthenticationFilter jwtAuthenticationFilter;
public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) { this.jwtAuthenticationFilter = jwtAuthenticationFilter; }
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(authorize -> authorize .requestMatchers("/api/login" , "/api/register", "/error").permitAll() // Open the register endpoint .requestMatchers("/api/orders/place").hasRole("USER") .anyRequest().authenticated() // Protect all other endpoints ) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) .exceptionHandling((exception) ->exception.accessDeniedPage("/error/404"));
return http.build(); }
@Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } } [/code] Как ни странно, сначала мой API авторизуется, и я вижу журналы размещения заказа. [code] Hibernate: select c1_0.customer_id,c1_0.email,c1_0.name,c1_0.password,c1_0.phone,c1_0.username from customer c1_0 where c1_0.username=? Hibernate: select c1_0.customer_id,c1_0.email,c1_0.name,c1_0.password,c1_0.phone,c1_0.username from customer c1_0 where c1_0.username=? Hibernate: insert into orders (customer_id,status,timestamp,total_amount) values (?,?,?,?) Hibernate: insert into order_items (order_id,price,product_id,quantity) values (?,?,?,?) Hibernate: insert into order_items (order_id,price,product_id,quantity) values (?,?,?,?) Hibernate: insert into order_items (order_id,price,product_id,quantity) values (?,?,?,?) Hibernate: insert into order_items (order_id,price,product_id,quantity) values (?,?,?,?) Hibernate: insert into order_items (order_id,price,product_id,quantity) values (?,?,?,?) Hibernate: insert into order_items (order_id,price,product_id,quantity) values (?,?,?,?) [/code] Но тогда ответ не появляется, отображается «Пустое тело ответа» с кодом ошибки 403. [code]HTTP/1.1 403 X-Content-Type-Options: nosniff X-XSS-Protection: 0 Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 X-Frame-Options: DENY Content-Length: 0 Date: Thu, 21 Nov 2024 22:00:44 GMT
// 5 seconds because i set a timeout. Response code: 403; Time: 5442ms (5 s 442 ms); Content length: 0 bytes (0 B) [/code] Я понятия не имею, почему это происходит. Я пытался сохранить контекст безопасности вручную в том же потоке, но это не сработало. />Что-то вроде, [code]SecurityContext context = SecurityContextHolder.getContext(); SecurityContextHolder.setContext(context); . . . . . . . SecurityContextHolder.clearContext(); [/code] Ожидал, что экземпляр клиента будет сохранен, но этого не произошло. Я ожидал ответа [code]{ "status": "ORDER PLACED", "orderId": x } [/code] Это тоже не сработало, есть идеи, как это можно исправить?