or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdapplication-framework.mddataset-management.mdindex.mdmapreduce-programs.mdplugin-framework.mdscheduling.mdservice-programs.mdspark-programs.mdsystem-services.mdtransactions.mdworker-programs.mdworkflow-programs.md

service-programs.mddocs/

0

# Service Programs

1

2

Service programs in CDAP provide long-running services including HTTP APIs, custom protocols, and background processing services with built-in lifecycle management and resource allocation.

3

4

## Core Service Interfaces

5

6

### Service

7

8

```java { .api }

9

public interface Service extends ProgramLifecycle<ServiceContext> {

10

void configure(ServiceConfigurer configurer);

11

}

12

```

13

14

Base interface for service programs providing configuration and lifecycle hooks.

15

16

### AbstractService

17

18

```java { .api }

19

public abstract class AbstractService implements Service {

20

public abstract void configure(ServiceConfigurer configurer);

21

22

@Override

23

public void initialize(ServiceContext context) throws Exception {

24

// Optional initialization logic

25

}

26

27

@Override

28

public void destroy() {

29

// Optional cleanup logic

30

}

31

}

32

```

33

34

Base implementation class for service programs.

35

36

### BasicService

37

38

```java { .api }

39

public class BasicService extends AbstractService {

40

private final HttpServiceHandler[] handlers;

41

42

public BasicService(HttpServiceHandler... handlers);

43

public BasicService(String name, HttpServiceHandler... handlers);

44

45

@Override

46

public void configure(ServiceConfigurer configurer);

47

}

48

```

49

50

Simple service implementation for HTTP handlers.

51

52

## HTTP Services

53

54

### HttpServiceHandler

55

56

```java { .api }

57

public interface HttpServiceHandler {

58

void initialize(HttpServiceContext context) throws Exception;

59

void destroy();

60

}

61

```

62

63

Base interface for HTTP request handlers.

64

65

### AbstractHttpServiceHandler

66

67

```java { .api }

68

public abstract class AbstractHttpServiceHandler implements HttpServiceHandler {

69

@Override

70

public void initialize(HttpServiceContext context) throws Exception {

71

// Optional initialization

72

}

73

74

@Override

75

public void destroy() {

76

// Optional cleanup

77

}

78

}

79

```

80

81

Base implementation for HTTP service handlers with annotation-based request mapping.

82

83

### HTTP Request and Response

84

85

```java { .api }

86

public class HttpServiceRequest {

87

public String getMethod();

88

public String getUri();

89

public Map<String, List<String>> getAllHeaders();

90

public String getHeader(String name);

91

public Map<String, String> getHeaders();

92

93

public ByteBuffer getContent();

94

public String getContentAsString();

95

public <T> T getContent(Type type);

96

}

97

98

public interface HttpServiceResponder {

99

void sendJson(int status, Object object);

100

void sendJson(Object object);

101

void sendString(int status, String data, Charset charset);

102

void sendString(String data);

103

void sendStatus(int status);

104

void sendError(int status, String errorMessage);

105

106

void send(int status, ByteBuffer content, String contentType);

107

void send(ByteBuffer content, String contentType);

108

109

ChunkResponder sendChunkStart(int status, Map<String, String> headers);

110

}

111

```

112

113

HTTP request and response handling interfaces.

114

115

### Content Handling

116

117

```java { .api }

118

public interface HttpContentConsumer {

119

void onReceived(ByteBuffer chunk, Transactional transactional) throws Exception;

120

void onFinish(HttpServiceResponder responder) throws Exception;

121

void onError(HttpServiceResponder responder, Throwable failureCause);

122

}

123

124

public interface HttpContentProducer {

125

ByteBuffer nextChunk(Transactional transactional) throws Exception;

126

void onFinish() throws Exception;

127

void onError(Throwable failureCause);

128

}

129

```

130

131

Interfaces for handling large request/response bodies with streaming support.

132

133

## Service Configuration

134

135

### ServiceConfigurer

136

137

```java { .api }

138

public interface ServiceConfigurer extends ProgramConfigurer, DatasetConfigurer, PluginConfigurer {

139

void addHandler(HttpServiceHandler handler);

140

void setInstances(int instances);

141

void setResources(Resources resources);

142

}

143

```

144

145

Interface for configuring service programs.

146

147

### HttpServiceConfigurer

148

149

```java { .api }

150

public interface HttpServiceConfigurer {

151

void setName(String name);

152

void setDescription(String description);

153

void setProperties(Map<String, String> properties);

154

void setResources(Resources resources);

155

}

156

```

157

158

Configuration interface for HTTP service handlers.

159

160

## Service Context

161

162

### ServiceContext

163

164

```java { .api }

165

public interface ServiceContext extends RuntimeContext, DatasetContext, ServiceDiscoverer {

166

int getInstanceCount();

167

int getInstanceId();

168

Map<String, String> getRuntimeArguments();

169

170

PluginContext getPluginContext();

171

Metrics getMetrics();

172

Admin getAdmin();

173

}

174

```

175

176

Runtime context for service programs.

177

178

### HttpServiceContext

179

180

```java { .api }

181

public interface HttpServiceContext extends ServiceContext {

182

HttpServiceHandlerSpecification getSpecification();

183

int getInstanceCount();

184

int getInstanceId();

185

}

186

```

187

188

HTTP-specific service context providing handler metadata.

189

190

## Usage Examples

191

192

### Basic HTTP Service

193

194

```java

195

public class UserService extends AbstractService {

196

197

@Override

198

public void configure(ServiceConfigurer configurer) {

199

configurer.setName("UserService");

200

configurer.setDescription("REST API for user management");

201

configurer.addHandler(new UserHandler());

202

configurer.setInstances(2);

203

configurer.setResources(new Resources(1024)); // 1GB memory

204

configurer.useDataset("users");

205

}

206

}

207

208

public class UserHandler extends AbstractHttpServiceHandler {

209

210

@UseDataSet("users")

211

private ObjectStore<User> userStore;

212

213

@GET

214

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

215

public void getUser(HttpServiceRequest request, HttpServiceResponder responder,

216

@PathParam("id") String userId) {

217

218

try {

219

User user = userStore.read(userId);

220

if (user != null) {

221

responder.sendJson(user);

222

} else {

223

responder.sendError(404, "User not found");

224

}

225

} catch (Exception e) {

226

responder.sendError(500, "Internal server error");

227

}

228

}

229

230

@POST

231

@Path("/users")

232

public void createUser(HttpServiceRequest request, HttpServiceResponder responder) {

233

234

try {

235

User user = request.getContent(User.class);

236

userStore.write(user.getId(), user);

237

responder.sendJson(201, user);

238

} catch (Exception e) {

239

responder.sendError(400, "Invalid user data");

240

}

241

}

242

243

@PUT

244

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

245

public void updateUser(HttpServiceRequest request, HttpServiceResponder responder,

246

@PathParam("id") String userId) {

247

248

try {

249

User existingUser = userStore.read(userId);

250

if (existingUser == null) {

251

responder.sendError(404, "User not found");

252

return;

253

}

254

255

User updatedUser = request.getContent(User.class);

256

updatedUser.setId(userId);

257

userStore.write(userId, updatedUser);

258

responder.sendJson(updatedUser);

259

} catch (Exception e) {

260

responder.sendError(500, "Update failed");

261

}

262

}

263

264

@DELETE

265

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

266

public void deleteUser(HttpServiceRequest request, HttpServiceResponder responder,

267

@PathParam("id") String userId) {

268

269

try {

270

User user = userStore.read(userId);

271

if (user != null) {

272

userStore.delete(userId);

273

responder.sendStatus(204);

274

} else {

275

responder.sendError(404, "User not found");

276

}

277

} catch (Exception e) {

278

responder.sendError(500, "Delete failed");

279

}

280

}

281

}

282

```

283

284

### Service with Large Content Handling

285

286

```java

287

public class FileUploadHandler extends AbstractHttpServiceHandler {

288

289

@UseDataSet("files")

290

private FileSet fileStorage;

291

292

@POST

293

@Path("/upload/{filename}")

294

public HttpContentConsumer upload(@PathParam("filename") String filename) {

295

296

return new HttpContentConsumer() {

297

private OutputStream outputStream;

298

private Location fileLocation;

299

300

@Override

301

public void onReceived(ByteBuffer chunk, Transactional transactional) throws Exception {

302

if (outputStream == null) {

303

fileLocation = fileStorage.getLocation(filename);

304

outputStream = fileLocation.getOutputStream();

305

}

306

307

byte[] bytes = new byte[chunk.remaining()];

308

chunk.get(bytes);

309

outputStream.write(bytes);

310

}

311

312

@Override

313

public void onFinish(HttpServiceResponder responder) throws Exception {

314

if (outputStream != null) {

315

outputStream.close();

316

}

317

318

responder.sendJson(200, Collections.singletonMap("status", "uploaded"));

319

}

320

321

@Override

322

public void onError(HttpServiceResponder responder, Throwable failureCause) {

323

try {

324

if (outputStream != null) {

325

outputStream.close();

326

}

327

if (fileLocation != null) {

328

fileLocation.delete();

329

}

330

} catch (IOException e) {

331

// Log error

332

}

333

334

responder.sendError(500, "Upload failed: " + failureCause.getMessage());

335

}

336

};

337

}

338

339

@GET

340

@Path("/download/{filename}")

341

public HttpContentProducer download(@PathParam("filename") String filename,

342

HttpServiceResponder responder) throws IOException {

343

344

Location fileLocation = fileStorage.getLocation(filename);

345

if (!fileLocation.exists()) {

346

responder.sendError(404, "File not found");

347

return null;

348

}

349

350

return new HttpContentProducer() {

351

private InputStream inputStream = fileLocation.getInputStream();

352

private final byte[] buffer = new byte[8192];

353

354

@Override

355

public ByteBuffer nextChunk(Transactional transactional) throws Exception {

356

int bytesRead = inputStream.read(buffer);

357

if (bytesRead == -1) {

358

return null; // End of file

359

}

360

361

return ByteBuffer.wrap(buffer, 0, bytesRead);

362

}

363

364

@Override

365

public void onFinish() throws Exception {

366

inputStream.close();

367

}

368

369

@Override

370

public void onError(Throwable failureCause) {

371

try {

372

inputStream.close();

373

} catch (IOException e) {

374

// Log error

375

}

376

}

377

};

378

}

379

}

380

```

381

382

### Service with Plugin Integration

383

384

```java

385

public class ProcessingService extends AbstractService {

386

387

@Override

388

public void configure(ServiceConfigurer configurer) {

389

configurer.setName("ProcessingService");

390

configurer.addHandler(new ProcessingHandler());

391

392

// Use transformation plugin

393

configurer.usePlugin("transform", "dataTransform", "transformer",

394

PluginProperties.builder()

395

.add("operation", "normalize")

396

.build());

397

}

398

}

399

400

public class ProcessingHandler extends AbstractHttpServiceHandler {

401

402

@UseDataSet("inputData")

403

private ObjectStore<DataRecord> inputStore;

404

405

@UseDataSet("outputData")

406

private ObjectStore<DataRecord> outputStore;

407

408

private DataTransformer transformer;

409

410

@Override

411

public void initialize(HttpServiceContext context) throws Exception {

412

super.initialize(context);

413

transformer = context.getPluginContext().newPluginInstance("transformer");

414

}

415

416

@POST

417

@Path("/process/{recordId}")

418

public void processRecord(HttpServiceRequest request, HttpServiceResponder responder,

419

@PathParam("recordId") String recordId) {

420

421

try {

422

DataRecord input = inputStore.read(recordId);

423

if (input == null) {

424

responder.sendError(404, "Record not found");

425

return;

426

}

427

428

DataRecord processed = transformer.transform(input);

429

outputStore.write(recordId, processed);

430

431

responder.sendJson(Collections.singletonMap("status", "processed"));

432

} catch (Exception e) {

433

responder.sendError(500, "Processing failed: " + e.getMessage());

434

}

435

}

436

}

437

```

438

439

### Multi-Handler Service

440

441

```java

442

public class APIGatewayService extends AbstractService {

443

444

@Override

445

public void configure(ServiceConfigurer configurer) {

446

configurer.setName("APIGateway");

447

configurer.setDescription("Unified API gateway service");

448

449

// Add multiple handlers for different API areas

450

configurer.addHandler(new UserHandler());

451

configurer.addHandler(new ProductHandler());

452

configurer.addHandler(new OrderHandler());

453

configurer.addHandler(new AuthHandler());

454

455

configurer.setInstances(3);

456

configurer.setResources(new Resources(2048, 2)); // 2GB, 2 cores

457

458

// Use common datasets

459

configurer.useDataset("users");

460

configurer.useDataset("products");

461

configurer.useDataset("orders");

462

configurer.useDataset("sessions");

463

}

464

}

465

```

466

467

Service programs provide the foundation for building REST APIs, real-time data processing endpoints, and custom protocol handlers within the CDAP platform.