or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/maven-io-quarkus--quarkus-rest-client-jackson-deployment

Quarkus deployment extension that provides build-time configuration and processing for integrating Jackson JSON serialization with the reactive REST client.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/io.quarkus/quarkus-rest-client-jackson-deployment@3.23.x

To install, run

npx @tessl/cli install tessl/maven-io-quarkus--quarkus-rest-client-jackson-deployment@3.23.0

0

# Quarkus REST Client Jackson Deployment

1

2

A Quarkus deployment extension that provides build-time configuration and processing for integrating Jackson JSON serialization/deserialization with the reactive REST client. This extension handles the automatic registration of Jackson message body readers and writers for JSON processing in REST client implementations, enabling seamless JSON data binding for client-side REST communication in Quarkus applications.

3

4

## Package Information

5

6

- **Package Name**: quarkus-rest-client-jackson-deployment

7

- **Package Type**: maven

8

- **Language**: Java

9

- **Installation**: Include in your Maven project dependencies or add as a Quarkus extension

10

11

```xml

12

<dependency>

13

<groupId>io.quarkus</groupId>

14

<artifactId>quarkus-rest-client-jackson-deployment</artifactId>

15

<version>3.23.0</version>

16

</dependency>

17

```

18

19

Add via Quarkus CLI:

20

```bash

21

quarkus extension add rest-client-reactive-jackson

22

```

23

24

## Core Imports

25

26

For deployment extension usage (typically in build processors):

27

28

```java

29

import io.quarkus.rest.client.reactive.jackson.deployment.RestClientReactiveJacksonProcessor;

30

import io.quarkus.deployment.builditem.FeatureBuildItem;

31

import io.quarkus.deployment.annotations.BuildStep;

32

```

33

34

For runtime usage (in REST client interfaces):

35

36

```java

37

import io.quarkus.rest.client.reactive.jackson.ClientObjectMapper;

38

import com.fasterxml.jackson.databind.ObjectMapper;

39

import io.quarkus.rest.client.reactive.jackson.runtime.serialisers.JacksonUtil;

40

```

41

42

For message body processing:

43

44

```java

45

import io.quarkus.rest.client.reactive.jackson.runtime.serialisers.ClientJacksonMessageBodyReader;

46

import io.quarkus.rest.client.reactive.jackson.runtime.serialisers.ClientJacksonMessageBodyWriter;

47

import org.jboss.resteasy.reactive.client.spi.RestClientRequestContext;

48

```

49

50

## Basic Usage

51

52

### Using the Extension

53

54

The extension is automatically activated when added to your Quarkus project. No additional configuration is required for basic JSON processing.

55

56

```java

57

import jakarta.ws.rs.GET;

58

import jakarta.ws.rs.POST;

59

import jakarta.ws.rs.Path;

60

import jakarta.ws.rs.PathParam;

61

import jakarta.ws.rs.Produces;

62

import jakarta.ws.rs.Consumes;

63

import jakarta.ws.rs.core.MediaType;

64

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

65

66

@RegisterRestClient(baseUri = "https://api.example.com")

67

public interface UserService {

68

69

@GET

70

@Path("/users/{id}")

71

@Produces(MediaType.APPLICATION_JSON)

72

User getUser(@PathParam("id") Long id);

73

74

@POST

75

@Path("/users")

76

@Consumes(MediaType.APPLICATION_JSON)

77

@Produces(MediaType.APPLICATION_JSON)

78

User createUser(CreateUserRequest request);

79

}

80

```

81

82

### Custom Object Mapper Configuration

83

84

Define a custom ObjectMapper for specific REST client configurations:

85

86

```java

87

import io.quarkus.rest.client.reactive.jackson.ClientObjectMapper;

88

import com.fasterxml.jackson.databind.ObjectMapper;

89

import com.fasterxml.jackson.databind.DeserializationFeature;

90

91

@RegisterRestClient(baseUri = "https://api.example.com")

92

public interface UserService {

93

94

@ClientObjectMapper

95

static ObjectMapper objectMapper(ObjectMapper defaultObjectMapper) {

96

return defaultObjectMapper.copy()

97

.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)

98

.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

99

}

100

101

@GET

102

@Path("/users/{id}")

103

User getUser(@PathParam("id") Long id);

104

}

105

```

106

107

## Architecture

108

109

The extension integrates with Quarkus' build-time optimization system and consists of several key components:

110

111

- **Build-time Processing**: `RestClientReactiveJacksonProcessor` handles feature registration and bean configuration during build

112

- **Runtime Serialization**: Jackson-based message body readers and writers handle JSON processing during runtime

113

- **CDI Integration**: Automatic bean registration for dependency injection compatibility

114

- **Native Image Support**: Proper configuration for GraalVM native compilation

115

- **Context Resolution**: Support for per-client ObjectMapper configuration via JAX-RS context resolution

116

117

## Capabilities

118

119

### Build-time Feature Registration

120

121

Automatically registers the REST_CLIENT_JACKSON feature and configures required components.

122

123

```java { .api }

124

public class RestClientReactiveJacksonProcessor {

125

126

/**

127

* Registers the REST_CLIENT_JACKSON feature

128

*/

129

@BuildStep

130

void feature(BuildProducer<FeatureBuildItem> features);

131

132

/**

133

* Configures Vert.x JSON reinitialization for native compilation

134

*/

135

@BuildStep

136

ReinitializeVertxJsonBuildItem vertxJson();

137

138

/**

139

* Registers ClientObjectMapper annotation for client context resolution

140

*/

141

@BuildStep

142

void additionalProviders(BuildProducer<AnnotationToRegisterIntoClientContextBuildItem> annotation);

143

144

/**

145

* Registers Jackson message body readers and writers as CDI beans.

146

* Only registers if Jackson provider is already defined in the application.

147

*/

148

@BuildStep

149

void additionalProviders(

150

List<ResteasyReactiveJacksonProviderDefinedBuildItem> jacksonProviderDefined,

151

BuildProducer<AdditionalBeanBuildItem> additionalBean,

152

BuildProducer<MessageBodyReaderBuildItem> additionalReaders,

153

BuildProducer<MessageBodyWriterBuildItem> additionalWriters);

154

155

/**

156

* Configures native image support by registering cleanup task service provider

157

*/

158

@BuildStep

159

void nativeSupport(BuildProducer<ServiceProviderBuildItem> serviceProviderProducer);

160

}

161

```

162

163

### Custom Object Mapper Configuration

164

165

Annotation for defining per-client ObjectMapper instances with custom configuration.

166

167

```java { .api }

168

/**

169

* Annotation for defining custom ObjectMapper for specific REST client.

170

* Must be placed on static methods in REST Client interfaces.

171

*/

172

@Retention(RetentionPolicy.RUNTIME)

173

@Target(ElementType.METHOD)

174

public @interface ClientObjectMapper {

175

}

176

```

177

178

**Usage Requirements:**

179

- Must be placed on static methods in REST Client interfaces

180

- Method can optionally accept default ObjectMapper as parameter

181

- Should return ObjectMapper instance with desired configuration

182

- Use `copy()` method on default mapper to inherit base settings

183

184

**Usage Examples:**

185

186

Simple custom mapper:

187

```java

188

@ClientObjectMapper

189

static ObjectMapper objectMapper() {

190

return new ObjectMapper()

191

.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

192

}

193

```

194

195

Inheriting from default mapper:

196

```java

197

@ClientObjectMapper

198

static ObjectMapper objectMapper(ObjectMapper defaultObjectMapper) {

199

return defaultObjectMapper.copy()

200

.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)

201

.configure(JsonParser.Feature.ALLOW_COMMENTS, true);

202

}

203

```

204

205

### ObjectMapper Context Resolution

206

207

Utility for resolving ObjectMapper instances from JAX-RS context, enabling per-client customization.

208

209

```java { .api }

210

/**

211

* Utility class for resolving ObjectMapper from REST client context

212

*/

213

final class JacksonUtil {

214

215

/**

216

* Resolves ObjectMapper from REST client context, falling back to default if not found.

217

* Supports per-client ObjectMapper customization via @ClientObjectMapper annotation.

218

*

219

* @param responseMediaType the media type of the response

220

* @param context the REST client request context containing configuration

221

* @return ObjectMapper instance (custom or default)

222

*/

223

static ObjectMapper getObjectMapperFromContext(MediaType responseMediaType, RestClientRequestContext context);

224

}

225

```

226

227

### JSON Message Processing

228

229

Runtime components that handle JSON serialization and deserialization for REST client communication.

230

231

```java { .api }

232

/**

233

* Jackson-based message body reader for client-side JSON deserialization

234

*/

235

public class ClientJacksonMessageBodyReader extends AbstractJsonMessageBodyReader

236

implements ClientMessageBodyReader<Object> {

237

238

private final ObjectMapper mapper;

239

240

/**

241

* Constructor with ObjectMapper dependency injection.

242

* The injected mapper serves as default but can be overridden per-client.

243

*

244

* @param mapper default ObjectMapper instance injected by CDI

245

*/

246

@Inject

247

public ClientJacksonMessageBodyReader(ObjectMapper mapper);

248

249

/**

250

* Standard JAX-RS reader method for JSON deserialization.

251

* Uses default ObjectMapper without context resolution.

252

*/

253

@Override

254

public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations,

255

MediaType mediaType, MultivaluedMap<String, String> httpHeaders,

256

InputStream entityStream) throws IOException, WebApplicationException;

257

258

/**

259

* Client-specific reader method with REST client context support.

260

* Resolves ObjectMapper from context using JacksonUtil, enabling per-client customization.

261

*/

262

@Override

263

public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations,

264

MediaType mediaType, MultivaluedMap<String, String> httpHeaders,

265

InputStream entityStream, RestClientRequestContext context)

266

throws IOException, WebApplicationException;

267

}

268

269

/**

270

* Jackson-based message body writer for client-side JSON serialization

271

*/

272

public class ClientJacksonMessageBodyWriter implements ClientMessageBodyWriter<Object> {

273

274

private final ObjectMapper mapper;

275

276

/**

277

* Constructor with ObjectMapper dependency injection.

278

* The injected mapper serves as default but can be overridden per-client.

279

*

280

* @param mapper default ObjectMapper instance injected by CDI

281

*/

282

@Inject

283

public ClientJacksonMessageBodyWriter(ObjectMapper mapper);

284

285

/**

286

* Indicates if type is writable for JSON serialization.

287

* Always returns true for JSON media types.

288

*

289

* @return true if the type can be serialized to JSON

290

*/

291

@Override

292

public boolean isWriteable(Class type, Type genericType, Annotation[] annotations,

293

MediaType mediaType);

294

295

/**

296

* Standard JAX-RS writer method for JSON serialization.

297

* Uses default ObjectMapper without context resolution.

298

*/

299

@Override

300

public void writeTo(Object o, Class<?> type, Type genericType, Annotation[] annotations,

301

MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,

302

OutputStream entityStream) throws IOException, WebApplicationException;

303

304

/**

305

* Client-specific writer method with REST client context support.

306

* Resolves ObjectMapper from context using JacksonUtil, enabling per-client customization.

307

*/

308

@Override

309

public void writeTo(Object o, Class<?> type, Type genericType, Annotation[] annotations,

310

MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,

311

OutputStream entityStream, RestClientRequestContext context)

312

throws IOException, WebApplicationException;

313

}

314

```

315

316

### Resource Cleanup

317

318

Automatic cleanup of ObjectMapper caches when REST clients are closed.

319

320

```java { .api }

321

/**

322

* Cleanup task for ClientObjectMapper mappings when REST client is closed

323

*/

324

public class JacksonCleanupRestClientClosingTask implements RestClientClosingTask {

325

326

/**

327

* Cleans up cached ObjectMapper mappings for the closing client

328

*/

329

@Override

330

public void close(Context context);

331

}

332

```

333

334

## Supported Media Types

335

336

### JSON Deserialization (Reading)

337

- `application/json` - Standard JSON format

338

- `application/x-ndjson` - Newline delimited JSON

339

- `application/stream+json` - JSON streaming format

340

341

### JSON Serialization (Writing)

342

- `application/json` - Standard JSON format

343

344

## Error Handling

345

346

The extension handles JSON processing errors gracefully:

347

348

- **JsonParseException**: Invalid JSON from server responses are caught and wrapped in `ClientWebApplicationException` with HTTP 200 status

349

- **Context Resolution**: Failed ObjectMapper context resolution falls back to default mapper

350

- **Resource Cleanup**: Automatic cleanup prevents memory leaks when clients are closed

351

352

## Configuration

353

354

The extension uses the standard Quarkus configuration prefix `quarkus.rest-client-reactive.` for any REST client related settings.

355

356

## Dependencies

357

358

### Required Dependencies

359

- `io.quarkus:quarkus-rest-jackson-common-deployment` - Common Jackson deployment utilities

360

- `io.quarkus:quarkus-rest-client-deployment` - REST client deployment foundation

361

- `io.quarkus:quarkus-rest-client-jackson` - Runtime components

362

363

### Framework Integration

364

- **Jackson**: `com.fasterxml.jackson.databind.ObjectMapper` for JSON processing

365

- **JAX-RS**: Standard `jakarta.ws.rs` APIs for HTTP handling

366

- **RESTEasy Reactive**: `org.jboss.resteasy.reactive` framework integration

367

- **Vert.x**: `io.vertx.core.json` for JsonObject and JsonArray support

368

- **Quarkus CDI**: `jakarta.inject` for dependency injection

369

370

## Types

371

372

```java { .api }

373

/**

374

* Key class for caching ObjectMapper resolvers per REST client configuration

375

*/

376

public final class ResolverMapKey {

377

378

/**

379

* Creates a new resolver map key

380

*/

381

public ResolverMapKey(Configuration configuration, Class<?> restClientClass);

382

383

/**

384

* Gets the JAX-RS configuration

385

*/

386

public Configuration getConfiguration();

387

388

/**

389

* Gets the REST client class

390

*/

391

public Class<?> getRestClientClass();

392

393

@Override

394

public boolean equals(Object o);

395

396

@Override

397

public int hashCode();

398

}

399

400

/**

401

* Build item indicating that Vert.x JSON needs reinitialization for native compilation

402

*/

403

public final class ReinitializeVertxJsonBuildItem extends SimpleBuildItem {

404

}

405

406

/**

407

* Build item for registering annotations that should be available in client context

408

*/

409

public final class AnnotationToRegisterIntoClientContextBuildItem extends MultiBuildItem {

410

public AnnotationToRegisterIntoClientContextBuildItem(DotName annotation);

411

public DotName getAnnotation();

412

}

413

414

/**

415

* Marker build item indicating Jackson provider has been defined for RESTEasy Reactive

416

*/

417

public final class ResteasyReactiveJacksonProviderDefinedBuildItem extends SimpleBuildItem {

418

}

419

```