package com.example.trading.oms.grpc; import com.example.trading.contracts.v1.OrderServiceGrpc; import com.example.trading.contracts.v1.SubmitOrderRequest; import com.example.trading.contracts.v1.SubmitOrderResponse; import com.example.trading.oms.application.OrderApplicationService; import com.example.trading.oms.order.InvalidOrderException; import io.grpc.Status; import io.grpc.stub.StreamObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.grpc.server.service.GrpcService; @GrpcService public class OrderGrpcService extends OrderServiceGrpc.OrderServiceImplBase { private static final Logger log = LoggerFactory.getLogger(OrderGrpcService.class); private final OrderApplicationService orders; public OrderGrpcService(OrderApplicationService orders) { this.orders = orders; } @Override public void submitOrder(SubmitOrderRequest request, StreamObserver observer) { SubmitOrderResponse response; try { response = orders.submitOrder(request); } catch (InvalidOrderException ex) { observer.onError(Status.INVALID_ARGUMENT.withDescription(ex.getMessage()).asRuntimeException()); return; } catch (Exception ex) { log.error("Unexpected SubmitOrder failure", ex); observer.onError(Status.INTERNAL.withDescription("Order processing failed").asRuntimeException()); return; } // Keep observer callbacks outside the business exception handler so a transport // failure cannot cause a second terminal callback after successful completion. log.info("OMS decision: senderCompId={} ClOrdID={} tradingDate={} orderId={} Decision={} rejectReason={}", request.getSenderCompId(), request.getClientOrderId(), request.getTradingDate(), response.getOrderId(), response.getDecision(), response.getRejectReason()); observer.onNext(response); observer.onCompleted(); } }