0
# Service Implementation
1
2
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.
3
4
## Capabilities
5
6
### @GrpcService Annotation
7
8
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.
9
10
```java { .api }
11
/**
12
* Qualifies a gRPC service.
13
*/
14
@Qualifier
15
@Target({ FIELD, PARAMETER, TYPE })
16
@Retention(RUNTIME)
17
public @interface GrpcService {
18
}
19
```
20
21
**Usage Example:**
22
23
```java
24
import io.quarkus.grpc.GrpcService;
25
import io.smallrye.mutiny.Uni;
26
27
@GrpcService
28
public class GreetingService implements MutinyGreetingGrpc.GreetingImplBase {
29
30
@Override
31
public Uni<HelloReply> sayHello(HelloRequest request) {
32
return Uni.createFrom().item(
33
HelloReply.newBuilder()
34
.setMessage("Hello " + request.getName())
35
.build()
36
);
37
}
38
39
@Override
40
public Multi<HelloReply> sayHelloStream(HelloRequest request) {
41
return Multi.createFrom().items(
42
HelloReply.newBuilder().setMessage("Hello").build(),
43
HelloReply.newBuilder().setMessage(request.getName()).build()
44
);
45
}
46
}
47
```
48
49
### MutinyService Interface
50
51
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.
52
53
```java { .api }
54
/**
55
* Used to mark a Mutiny service interface generated for a gRPC service.
56
*/
57
public interface MutinyService {
58
}
59
```
60
61
**Usage Example:**
62
63
```java
64
import io.quarkus.grpc.GrpcService;
65
import io.quarkus.grpc.MutinyService;
66
import io.smallrye.mutiny.Uni;
67
import io.smallrye.mutiny.Multi;
68
69
@GrpcService
70
public class ProductService implements MutinyService {
71
72
// Unary call: request -> response
73
public Uni<Product> getProduct(ProductRequest request) {
74
return productRepository.findById(request.getId())
75
.onItem().ifNull().failWith(new StatusRuntimeException(
76
Status.NOT_FOUND.withDescription("Product not found")));
77
}
78
79
// Server streaming: request -> stream of responses
80
public Multi<Product> listProducts(ListProductsRequest request) {
81
return productRepository.findByCategory(request.getCategory());
82
}
83
84
// Client streaming: stream of requests -> response
85
public Uni<BulkCreateResponse> createProducts(Multi<Product> products) {
86
return products
87
.onItem().transform(productRepository::save)
88
.collect().asList()
89
.onItem().transform(savedProducts ->
90
BulkCreateResponse.newBuilder()
91
.setCount(savedProducts.size())
92
.build());
93
}
94
95
// Bidirectional streaming: stream of requests -> stream of responses
96
public Multi<ProcessResult> processProducts(Multi<Product> products) {
97
return products
98
.onItem().transform(this::processProduct)
99
.onItem().transform(result ->
100
ProcessResult.newBuilder()
101
.setStatus(result.isSuccess() ? "SUCCESS" : "FAILED")
102
.build());
103
}
104
}
105
```
106
107
### MutinyGrpc Interface
108
109
Marker interface for generated Mutiny gRPC services. This interface is typically implemented by code-generated classes that provide the Mutiny-based service interface.
110
111
```java { .api }
112
/**
113
* Used to mark a generated Mutiny gRPC service.
114
*/
115
public interface MutinyGrpc {
116
}
117
```
118
119
### MutinyBean Interface
120
121
Marker interface for convenient Mutiny beans generated for gRPC services. These beans provide additional convenience methods and integrations.
122
123
```java { .api }
124
/**
125
* Used to mark a convenient Mutiny bean generated for a gRPC service.
126
*/
127
public interface MutinyBean {
128
}
129
```
130
131
### MutinyStub Interface
132
133
Marker interface for generated Mutiny gRPC stubs. These stubs are used internally by the framework for client-side communication.
134
135
```java { .api }
136
/**
137
* A marker interface that represents a generated Mutiny gRPC stub.
138
*/
139
public interface MutinyStub {
140
}
141
```
142
143
## Error Handling in Services
144
145
Services can handle errors using standard Mutiny error handling patterns or by throwing gRPC `StatusRuntimeException`:
146
147
```java
148
@GrpcService
149
public class UserService implements MutinyService {
150
151
public Uni<User> getUser(GetUserRequest request) {
152
return userRepository.findById(request.getId())
153
.onItem().ifNull().failWith(() ->
154
new StatusRuntimeException(
155
Status.NOT_FOUND.withDescription("User not found")))
156
.onFailure(IllegalArgumentException.class).transform(ex ->
157
new StatusRuntimeException(
158
Status.INVALID_ARGUMENT.withDescription(ex.getMessage())));
159
}
160
}
161
```
162
163
## CDI Integration
164
165
gRPC services are full CDI beans and support all CDI features:
166
167
```java
168
@GrpcService
169
@ApplicationScoped
170
public class OrderService implements MutinyService {
171
172
@Inject
173
OrderRepository orderRepository;
174
175
@Inject
176
PaymentService paymentService;
177
178
@ConfigProperty(name = "order.tax-rate", defaultValue = "0.1")
179
Double taxRate;
180
181
public Uni<Order> createOrder(CreateOrderRequest request) {
182
return Uni.createFrom().item(request)
183
.onItem().transform(this::validateOrder)
184
.onItem().transformToUni(orderRepository::save)
185
.onItem().transformToUni(order ->
186
paymentService.processPayment(order)
187
.onItem().transform(payment -> order.withPayment(payment)));
188
}
189
}
190
```