or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-transaction-management.mddatasource-auto-proxying.mdhttp-transaction-propagation.mdindex.mdsaga-pattern-support.md

http-transaction-propagation.mddocs/

0

# HTTP Transaction Propagation

1

2

The HTTP transaction propagation capability provides automatic transaction context propagation across HTTP service calls in web applications. It supports both javax and Jakarta EE servlet environments, enabling distributed transactions to seamlessly flow between microservices.

3

4

## Installation and Setup

5

6

HTTP transaction propagation is enabled by default in web applications:

7

8

```properties

9

# Enable HTTP transaction context propagation (default: true)

10

seata.client.http.interceptor-enabled=true

11

12

# Additional HTTP configuration

13

seata.client.http.request-headers=TX_XID,TX_BRANCH_ID

14

seata.client.http.response-headers=TX_XID

15

```

16

17

## Core Components

18

19

### Web MVC Configurers

20

21

Automatic configuration of request interceptors for transaction context handling.

22

23

#### Jakarta EE Support

24

25

```java { .api }

26

@Bean

27

@ConditionalOnClass(name = "jakarta.servlet.http.HttpServletRequest")

28

public JakartaSeataWebMvcConfigurer jakartaSeataWebMvcConfigurer();

29

```

30

31

**Returns:** `JakartaSeataWebMvcConfigurer` - Web MVC configurer for Jakarta EE environments

32

33

#### Javax Servlet Support

34

35

```java { .api }

36

@Bean

37

@ConditionalOnMissingBean(JakartaSeataWebMvcConfigurer.class)

38

public SeataWebMvcConfigurer seataWebMvcConfigurer();

39

```

40

41

**Returns:** `SeataWebMvcConfigurer` - Web MVC configurer for javax servlet environments

42

43

## Automatic Transaction Context Propagation

44

45

### Incoming HTTP Requests

46

47

Transaction context is automatically extracted from incoming HTTP requests:

48

49

```java

50

@RestController

51

public class OrderController {

52

53

@Autowired

54

private OrderService orderService;

55

56

@PostMapping("/orders")

57

public ResponseEntity<Order> createOrder(@RequestBody Order order) {

58

// Transaction context is automatically available here

59

// if this request is part of a distributed transaction

60

61

Order createdOrder = orderService.createOrder(order);

62

return ResponseEntity.ok(createdOrder);

63

}

64

}

65

```

66

67

### Outgoing HTTP Requests

68

69

Transaction context is automatically propagated to outgoing HTTP requests:

70

71

```java

72

@Service

73

public class PaymentService {

74

75

@Autowired

76

private RestTemplate restTemplate;

77

78

@GlobalTransactional

79

public void processPayment(String orderId, BigDecimal amount) {

80

// Transaction context will be automatically added to HTTP headers

81

// when making calls to other services

82

83

PaymentRequest request = new PaymentRequest(orderId, amount);

84

85

// This call will include transaction headers automatically

86

PaymentResponse response = restTemplate.postForObject(

87

"http://payment-service/payments",

88

request,

89

PaymentResponse.class

90

);

91

}

92

}

93

```

94

95

## RestTemplate Integration

96

97

### Automatic Interceptor Registration

98

99

Seata automatically configures RestTemplate with transaction context interceptors:

100

101

```java

102

@Configuration

103

public class RestTemplateConfig {

104

105

@Bean

106

public RestTemplate restTemplate() {

107

RestTemplate restTemplate = new RestTemplate();

108

// Seata interceptors are automatically added

109

// No manual configuration required

110

return restTemplate;

111

}

112

}

113

```

114

115

### Manual RestTemplate Configuration

116

117

For custom RestTemplate configurations:

118

119

```java

120

@Configuration

121

public class CustomRestTemplateConfig {

122

123

@Bean

124

public RestTemplate customRestTemplate() {

125

RestTemplate restTemplate = new RestTemplate();

126

127

// Add custom interceptors

128

List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();

129

interceptors.add(new CustomInterceptor());

130

131

// Seata interceptors will be added automatically

132

restTemplate.setInterceptors(interceptors);

133

134

return restTemplate;

135

}

136

}

137

```

138

139

## WebClient Integration

140

141

For reactive applications using WebClient:

142

143

```java

144

@Configuration

145

public class WebClientConfig {

146

147

@Bean

148

public WebClient webClient() {

149

return WebClient.builder()

150

// Seata filters are automatically configured

151

.build();

152

}

153

}

154

```

155

156

```java

157

@Service

158

public class ReactivePaymentService {

159

160

@Autowired

161

private WebClient webClient;

162

163

@GlobalTransactional

164

public Mono<PaymentResponse> processPaymentAsync(String orderId, BigDecimal amount) {

165

PaymentRequest request = new PaymentRequest(orderId, amount);

166

167

return webClient.post()

168

.uri("http://payment-service/payments")

169

.bodyValue(request)

170

.retrieve()

171

.bodyToMono(PaymentResponse.class);

172

// Transaction context propagated automatically

173

}

174

}

175

```

176

177

## HTTP Headers for Transaction Context

178

179

### Standard Transaction Headers

180

181

Seata uses specific HTTP headers to propagate transaction context:

182

183

```java { .api }

184

// Request headers containing transaction context

185

public static final String TX_XID = "TX_XID"; // Global transaction ID

186

public static final String TX_BRANCH_ID = "TX_BRANCH_ID"; // Branch transaction ID

187

public static final String TX_APPLICATION_NAME = "TX_APPLICATION_NAME"; // Application identifier

188

public static final String TX_SERVICE_GROUP = "TX_SERVICE_GROUP"; // Service group name

189

```

190

191

### Custom Header Configuration

192

193

Configure additional headers for transaction propagation:

194

195

```properties

196

# Custom request headers to propagate

197

seata.client.http.request-headers=TX_XID,TX_BRANCH_ID,CUSTOM_HEADER

198

199

# Custom response headers to extract

200

seata.client.http.response-headers=TX_XID,TX_STATUS

201

```

202

203

## Auto-Configuration Details

204

205

HTTP transaction propagation is configured through `SeataHttpAutoConfiguration`:

206

207

```java { .api }

208

@Configuration(proxyBeanMethods = false)

209

@ConditionalOnWebApplication

210

@ConditionalOnMissingBean(SeataWebMvcConfigurer.class)

211

@ConditionalOnProperty(prefix = "seata.client.http", name = "interceptor-enabled", havingValue = "true", matchIfMissing = true)

212

@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)

213

public class SeataHttpAutoConfiguration {

214

215

@Bean

216

@ConditionalOnClass(name = "jakarta.servlet.http.HttpServletRequest")

217

public JakartaSeataWebMvcConfigurer jakartaSeataWebMvcConfigurer();

218

219

@Bean

220

@ConditionalOnMissingBean(JakartaSeataWebMvcConfigurer.class)

221

public SeataWebMvcConfigurer seataWebMvcConfigurer();

222

}

223

```

224

225

**Activation Conditions:**

226

- Web application context required

227

- `seata.client.http.interceptor-enabled=true` (default)

228

- Automatically detects Jakarta EE vs javax servlet environments

229

230

## Microservices Integration

231

232

### Service-to-Service Communication

233

234

Example of distributed transaction across multiple microservices:

235

236

```java

237

// Order Service

238

@Service

239

public class OrderService {

240

241

@Autowired

242

private PaymentServiceClient paymentClient;

243

244

@Autowired

245

private InventoryServiceClient inventoryClient;

246

247

@GlobalTransactional

248

public Order createOrder(Order order) {

249

// 1. Save order locally

250

Order savedOrder = orderRepository.save(order);

251

252

// 2. Call Payment Service (transaction context propagated)

253

PaymentResponse payment = paymentClient.processPayment(

254

order.getCustomerId(),

255

order.getTotalAmount()

256

);

257

258

// 3. Call Inventory Service (transaction context propagated)

259

InventoryResponse inventory = inventoryClient.reserveItems(

260

order.getItems()

261

);

262

263

// If any step fails, all services will rollback

264

return savedOrder;

265

}

266

}

267

```

268

269

```java

270

// Payment Service

271

@RestController

272

public class PaymentController {

273

274

@PostMapping("/payments")

275

public PaymentResponse processPayment(@RequestBody PaymentRequest request) {

276

// This method automatically participates in the distributed transaction

277

// initiated by the Order Service

278

279

return paymentService.processPayment(request);

280

}

281

}

282

```

283

284

### Feign Client Integration

285

286

For Spring Cloud Feign clients:

287

288

```java

289

@FeignClient(name = "payment-service")

290

public interface PaymentServiceClient {

291

292

@PostMapping("/payments")

293

PaymentResponse processPayment(@RequestBody PaymentRequest request);

294

// Transaction headers automatically added by Seata interceptors

295

}

296

```

297

298

## Gateway Integration

299

300

### Spring Cloud Gateway

301

302

For API Gateway scenarios:

303

304

```java

305

@Configuration

306

public class GatewayConfig {

307

308

@Bean

309

public GlobalFilter seataTransactionFilter() {

310

return (exchange, chain) -> {

311

// Transaction context is automatically handled

312

// for requests passing through the gateway

313

return chain.filter(exchange);

314

};

315

}

316

}

317

```

318

319

### Zuul Integration

320

321

For Zuul proxy configurations:

322

323

```java

324

@Component

325

public class SeataZuulFilter extends ZuulFilter {

326

327

@Override

328

public String filterType() {

329

return "pre";

330

}

331

332

@Override

333

public int filterOrder() {

334

return 1;

335

}

336

337

@Override

338

public boolean shouldFilter() {

339

return true;

340

}

341

342

@Override

343

public Object run() {

344

// Transaction context automatically propagated

345

// through Zuul proxy requests

346

return null;

347

}

348

}

349

```

350

351

## Error Handling and Timeout

352

353

### HTTP Client Timeout Configuration

354

355

Configure timeouts for HTTP calls within distributed transactions:

356

357

```properties

358

# RestTemplate timeout configuration

359

seata.client.http.connect-timeout=5000

360

seata.client.http.read-timeout=30000

361

362

# Circuit breaker integration

363

resilience4j.circuitbreaker.instances.payment-service.timeout-duration=PT30S

364

```

365

366

### Error Propagation

367

368

HTTP errors are automatically handled within the transaction context:

369

370

```java

371

@Service

372

public class OrderService {

373

374

@GlobalTransactional(rollbackFor = {HttpClientErrorException.class, HttpServerErrorException.class})

375

public Order createOrder(Order order) {

376

try {

377

// Service calls with automatic error handling

378

PaymentResponse payment = paymentClient.processPayment(order);

379

InventoryResponse inventory = inventoryClient.reserveItems(order);

380

381

return orderRepository.save(order);

382

383

} catch (HttpClientErrorException e) {

384

// 4xx errors trigger transaction rollback

385

log.error("Client error in distributed transaction", e);

386

throw e;

387

388

} catch (HttpServerErrorException e) {

389

// 5xx errors trigger transaction rollback

390

log.error("Server error in distributed transaction", e);

391

throw e;

392

}

393

}

394

}

395

```

396

397

## Security Integration

398

399

### Authentication Token Propagation

400

401

Combine transaction context with security tokens:

402

403

```java

404

@Configuration

405

public class SecurityConfig {

406

407

@Bean

408

public RestTemplate secureRestTemplate() {

409

RestTemplate restTemplate = new RestTemplate();

410

411

// Add custom interceptors for security

412

List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();

413

interceptors.add(new BearerTokenInterceptor());

414

415

// Seata transaction interceptors are added automatically

416

restTemplate.setInterceptors(interceptors);

417

418

return restTemplate;

419

}

420

}

421

```

422

423

### Custom Security Headers

424

425

Configure additional security headers alongside transaction headers:

426

427

```properties

428

# Include security headers with transaction context

429

seata.client.http.request-headers=TX_XID,TX_BRANCH_ID,Authorization,X-User-ID

430

```

431

432

## Performance and Monitoring

433

434

### HTTP Request Monitoring

435

436

Monitor transaction context propagation:

437

438

```properties

439

# Enable HTTP transaction logging

440

logging.level.io.seata.integration.http=DEBUG

441

442

# Monitor request/response headers

443

logging.level.org.springframework.web.client.RestTemplate=DEBUG

444

```

445

446

### Performance Optimization

447

448

```properties

449

# Connection pool optimization for HTTP clients

450

seata.client.http.max-connections=200

451

seata.client.http.max-connections-per-route=20

452

453

# Keep-alive configuration

454

seata.client.http.keep-alive-duration=PT60S

455

```

456

457

## Troubleshooting

458

459

### Common Issues

460

461

1. **Transaction Context Not Propagated**: Check interceptor configuration and web application context

462

2. **Header Missing**: Verify HTTP header configuration and client setup

463

3. **Timeout Issues**: Adjust HTTP client timeout settings

464

4. **Security Conflicts**: Ensure security interceptors don't interfere with transaction headers

465

466

### Debug Configuration

467

468

```properties

469

# Debug HTTP transaction propagation

470

logging.level.io.seata.integration.http=DEBUG

471

logging.level.io.seata.core.context=DEBUG

472

473

# Monitor HTTP headers

474

logging.level.org.springframework.web.servlet.mvc.method.annotation=DEBUG

475

```

476

477

### Testing Transaction Propagation

478

479

Verify transaction context propagation in tests:

480

481

```java

482

@SpringBootTest

483

@Transactional

484

public class TransactionPropagationTest {

485

486

@Test

487

public void testTransactionContextPropagation() {

488

// Start global transaction

489

String xid = GlobalTransactionContext.getCurrentOrCreate().getXid();

490

491

// Make HTTP call

492

ResponseEntity<String> response = restTemplate.getForEntity("/test", String.class);

493

494

// Verify transaction headers were sent

495

assertThat(response.getHeaders().get("TX_XID")).contains(xid);

496

}

497

}

498

```