or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-usage.mdconfiguration.mdexception-handling.mdindex.mdinterceptors.mdreactive-streaming.mdservice-implementation.md

service-implementation.mddocs/

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

```