Quarkus gRPC extension that enables implementing and consuming gRPC services with reactive and imperative programming models.
—
Core functionality for implementing gRPC services with reactive programming support. Services are implemented as CDI beans with automatic lifecycle management and integration with Quarkus's dependency injection system.
Qualifies a CDI bean as a gRPC service implementation. The annotated class will be automatically registered as a gRPC service and made available for client connections.
/**
* Qualifies a gRPC service.
*/
@Qualifier
@Target({ FIELD, PARAMETER, TYPE })
@Retention(RUNTIME)
public @interface GrpcService {
}Usage Example:
import io.quarkus.grpc.GrpcService;
import io.smallrye.mutiny.Uni;
@GrpcService
public class GreetingService implements MutinyGreetingGrpc.GreetingImplBase {
@Override
public Uni<HelloReply> sayHello(HelloRequest request) {
return Uni.createFrom().item(
HelloReply.newBuilder()
.setMessage("Hello " + request.getName())
.build()
);
}
@Override
public Multi<HelloReply> sayHelloStream(HelloRequest request) {
return Multi.createFrom().items(
HelloReply.newBuilder().setMessage("Hello").build(),
HelloReply.newBuilder().setMessage(request.getName()).build()
);
}
}Marker interface used to identify Mutiny-based gRPC service implementations. Services implementing this interface use reactive return types (Uni and Multi) instead of traditional gRPC StreamObserver patterns.
/**
* Used to mark a Mutiny service interface generated for a gRPC service.
*/
public interface MutinyService {
}Usage Example:
import io.quarkus.grpc.GrpcService;
import io.quarkus.grpc.MutinyService;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.Multi;
@GrpcService
public class ProductService implements MutinyService {
// Unary call: request -> response
public Uni<Product> getProduct(ProductRequest request) {
return productRepository.findById(request.getId())
.onItem().ifNull().failWith(new StatusRuntimeException(
Status.NOT_FOUND.withDescription("Product not found")));
}
// Server streaming: request -> stream of responses
public Multi<Product> listProducts(ListProductsRequest request) {
return productRepository.findByCategory(request.getCategory());
}
// Client streaming: stream of requests -> response
public Uni<BulkCreateResponse> createProducts(Multi<Product> products) {
return products
.onItem().transform(productRepository::save)
.collect().asList()
.onItem().transform(savedProducts ->
BulkCreateResponse.newBuilder()
.setCount(savedProducts.size())
.build());
}
// Bidirectional streaming: stream of requests -> stream of responses
public Multi<ProcessResult> processProducts(Multi<Product> products) {
return products
.onItem().transform(this::processProduct)
.onItem().transform(result ->
ProcessResult.newBuilder()
.setStatus(result.isSuccess() ? "SUCCESS" : "FAILED")
.build());
}
}Marker interface for generated Mutiny gRPC services. This interface is typically implemented by code-generated classes that provide the Mutiny-based service interface.
/**
* Used to mark a generated Mutiny gRPC service.
*/
public interface MutinyGrpc {
}Marker interface for convenient Mutiny beans generated for gRPC services. These beans provide additional convenience methods and integrations.
/**
* Used to mark a convenient Mutiny bean generated for a gRPC service.
*/
public interface MutinyBean {
}Marker interface for generated Mutiny gRPC stubs. These stubs are used internally by the framework for client-side communication.
/**
* A marker interface that represents a generated Mutiny gRPC stub.
*/
public interface MutinyStub {
}Services can handle errors using standard Mutiny error handling patterns or by throwing gRPC StatusRuntimeException:
@GrpcService
public class UserService implements MutinyService {
public Uni<User> getUser(GetUserRequest request) {
return userRepository.findById(request.getId())
.onItem().ifNull().failWith(() ->
new StatusRuntimeException(
Status.NOT_FOUND.withDescription("User not found")))
.onFailure(IllegalArgumentException.class).transform(ex ->
new StatusRuntimeException(
Status.INVALID_ARGUMENT.withDescription(ex.getMessage())));
}
}gRPC services are full CDI beans and support all CDI features:
@GrpcService
@ApplicationScoped
public class OrderService implements MutinyService {
@Inject
OrderRepository orderRepository;
@Inject
PaymentService paymentService;
@ConfigProperty(name = "order.tax-rate", defaultValue = "0.1")
Double taxRate;
public Uni<Order> createOrder(CreateOrderRequest request) {
return Uni.createFrom().item(request)
.onItem().transform(this::validateOrder)
.onItem().transformToUni(orderRepository::save)
.onItem().transformToUni(order ->
paymentService.processPayment(order)
.onItem().transform(payment -> order.withPayment(payment)));
}
}Install with Tessl CLI
npx tessl i tessl/maven-io-quarkus--quarkus-grpc