0
# Annotation-Based Services
1
2
Declarative service configuration using annotations for HTTP method mapping, event handling, parameter injection, and component registration. This provides a simplified programming model for building Atmosphere applications.
3
4
## Capabilities
5
6
### Service Configuration Annotations
7
8
Core annotations for defining Atmosphere services with declarative configuration.
9
10
```java { .api }
11
/**
12
* Mark classes as Atmosphere services with path mapping and configuration
13
*/
14
@Target({ElementType.TYPE})
15
@Retention(RetentionPolicy.RUNTIME)
16
public @interface AtmosphereHandlerService {
17
/**
18
* URL path pattern for this service
19
* @return path pattern string
20
*/
21
String path() default "/";
22
23
/**
24
* Broadcaster to use for this service
25
* @return Broadcaster class
26
*/
27
Class<? extends Broadcaster> broadcaster() default Broadcaster.class;
28
29
/**
30
* Interceptors to apply to this service
31
* @return array of AtmosphereInterceptor classes
32
*/
33
Class<? extends AtmosphereInterceptor>[] interceptors() default {};
34
35
/**
36
* Atmosphere properties for configuration
37
* @return array of property key-value pairs
38
*/
39
String[] atmosphereConfig() default {};
40
}
41
42
/**
43
* Managed service with automatic lifecycle management
44
*/
45
@Target({ElementType.TYPE})
46
@Retention(RetentionPolicy.RUNTIME)
47
public @interface ManagedService {
48
/**
49
* URL path pattern for this managed service
50
* @return path pattern string
51
*/
52
String path() default "/";
53
54
/**
55
* Broadcaster to use for this service
56
* @return Broadcaster class
57
*/
58
Class<? extends Broadcaster> broadcaster() default Broadcaster.class;
59
60
/**
61
* Atmosphere configuration properties
62
* @return array of property key-value pairs
63
*/
64
String[] atmosphereConfig() default {};
65
}
66
67
/**
68
* Meteor-style service configuration
69
*/
70
@Target({ElementType.TYPE})
71
@Retention(RetentionPolicy.RUNTIME)
72
public @interface MeteorService {
73
/**
74
* URL path pattern
75
* @return path string
76
*/
77
String path() default "/";
78
79
/**
80
* Serializer class for message processing
81
* @return Serializer class
82
*/
83
Class<?> serializer() default Object.class;
84
}
85
```
86
87
**Usage Examples:**
88
89
```java
90
@AtmosphereHandlerService(path = "/chat/{room}")
91
public class ChatHandler implements AtmosphereHandler {
92
// Handler implementation
93
}
94
95
@ManagedService(path = "/api/notifications")
96
public class NotificationService {
97
// Managed service methods
98
}
99
100
@MeteorService(path = "/meteor/data")
101
public class DataService {
102
// Meteor-style service
103
}
104
```
105
106
### HTTP Method Mapping Annotations
107
108
Annotations for mapping HTTP methods to service methods in managed services.
109
110
```java { .api }
111
/**
112
* Map method to HTTP GET requests
113
*/
114
@Target({ElementType.METHOD})
115
@Retention(RetentionPolicy.RUNTIME)
116
public @interface Get {
117
}
118
119
/**
120
* Map method to HTTP POST requests
121
*/
122
@Target({ElementType.METHOD})
123
@Retention(RetentionPolicy.RUNTIME)
124
public @interface Post {
125
}
126
127
/**
128
* Map method to HTTP PUT requests
129
*/
130
@Target({ElementType.METHOD})
131
@Retention(RetentionPolicy.RUNTIME)
132
public @interface Put {
133
}
134
135
/**
136
* Map method to HTTP DELETE requests
137
*/
138
@Target({ElementType.METHOD})
139
@Retention(RetentionPolicy.RUNTIME)
140
public @interface Delete {
141
}
142
```
143
144
**Usage Examples:**
145
146
```java
147
@ManagedService(path = "/api/users")
148
public class UserService {
149
150
@Get
151
public void onConnect(AtmosphereResource resource) {
152
resource.suspend();
153
}
154
155
@Post
156
public void onPost(AtmosphereResource resource) {
157
// Handle POST request
158
}
159
160
@Put
161
public void onPut(AtmosphereResource resource) {
162
// Handle PUT request
163
}
164
165
@Delete
166
public void onDelete(AtmosphereResource resource) {
167
// Handle DELETE request
168
}
169
}
170
```
171
172
### Event Handling Annotations
173
174
Annotations for handling lifecycle events and messages in managed services.
175
176
```java { .api }
177
/**
178
* Mark method to be called when resource is ready (suspended)
179
*/
180
@Target({ElementType.METHOD})
181
@Retention(RetentionPolicy.RUNTIME)
182
public @interface Ready {
183
}
184
185
/**
186
* Mark method to be called when client disconnects
187
*/
188
@Target({ElementType.METHOD})
189
@Retention(RetentionPolicy.RUNTIME)
190
public @interface Disconnect {
191
}
192
193
/**
194
* Mark method to be called when connection is resumed
195
*/
196
@Target({ElementType.METHOD})
197
@Retention(RetentionPolicy.RUNTIME)
198
public @interface Resume {
199
}
200
201
/**
202
* Mark method to handle incoming messages
203
*/
204
@Target({ElementType.METHOD})
205
@Retention(RetentionPolicy.RUNTIME)
206
public @interface Message {
207
/**
208
* Encoder classes for outgoing messages
209
* @return array of Encoder classes
210
*/
211
Class<? extends Encoder>[] encoders() default {};
212
213
/**
214
* Decoder classes for incoming messages
215
* @return array of Decoder classes
216
*/
217
Class<? extends Decoder>[] decoders() default {};
218
}
219
220
/**
221
* Mark method to handle heartbeat events
222
*/
223
@Target({ElementType.METHOD})
224
@Retention(RetentionPolicy.RUNTIME)
225
public @interface Heartbeat {
226
}
227
```
228
229
**Usage Examples:**
230
231
```java
232
@ManagedService(path = "/chat")
233
public class ChatService {
234
235
@Ready
236
public void onReady(AtmosphereResource resource) {
237
System.out.println("Client connected and ready");
238
}
239
240
@Message(decoders = {JsonDecoder.class}, encoders = {JsonEncoder.class})
241
public ChatMessage onMessage(ChatMessage message) {
242
// Process incoming chat message
243
return new ChatMessage("Echo: " + message.getText());
244
}
245
246
@Disconnect
247
public void onDisconnect(AtmosphereResourceEvent event) {
248
System.out.println("Client disconnected");
249
}
250
251
@Resume
252
public void onResume(AtmosphereResourceEvent event) {
253
System.out.println("Connection resumed");
254
}
255
256
@Heartbeat
257
public void onHeartbeat(AtmosphereResourceEvent event) {
258
System.out.println("Heartbeat received");
259
}
260
}
261
```
262
263
### Parameter Injection Annotations
264
265
Annotations for injecting parameters and values into service method parameters.
266
267
```java { .api }
268
/**
269
* Inject path parameters from URL patterns
270
*/
271
@Target({ElementType.PARAMETER})
272
@Retention(RetentionPolicy.RUNTIME)
273
public @interface PathParam {
274
/**
275
* Name of the path parameter to inject
276
* @return parameter name
277
*/
278
String value();
279
}
280
281
/**
282
* Specify message delivery targets
283
*/
284
@Target({ElementType.METHOD})
285
@Retention(RetentionPolicy.RUNTIME)
286
public @interface DeliverTo {
287
/**
288
* Delivery target specification
289
* @return target specification
290
*/
291
String value() default "";
292
}
293
```
294
295
**Usage Examples:**
296
297
```java
298
@ManagedService(path = "/chat/{room}/{user}")
299
public class ChatRoomService {
300
301
@Get
302
public void joinRoom(@PathParam("room") String roomId,
303
@PathParam("user") String userId,
304
AtmosphereResource resource) {
305
System.out.println("User " + userId + " joining room " + roomId);
306
resource.suspend();
307
}
308
309
@Message
310
@DeliverTo("/chat/{room}")
311
public String onMessage(@PathParam("room") String roomId,
312
String message) {
313
return "Room " + roomId + ": " + message;
314
}
315
}
316
```
317
318
### Component Registration Annotations
319
320
Annotations for registering custom Atmosphere components and services.
321
322
```java { .api }
323
/**
324
* Register custom Broadcaster implementations
325
*/
326
@Target({ElementType.TYPE})
327
@Retention(RetentionPolicy.RUNTIME)
328
public @interface BroadcasterService {
329
}
330
331
/**
332
* Register AtmosphereHandler implementations
333
*/
334
@Target({ElementType.TYPE})
335
@Retention(RetentionPolicy.RUNTIME)
336
public @interface AtmosphereHandlerService {
337
String path() default "/";
338
Class<? extends Broadcaster> broadcaster() default Broadcaster.class;
339
Class<? extends AtmosphereInterceptor>[] interceptors() default {};
340
}
341
342
/**
343
* Register AtmosphereInterceptor implementations
344
*/
345
@Target({ElementType.TYPE})
346
@Retention(RetentionPolicy.RUNTIME)
347
public @interface AtmosphereInterceptorService {
348
}
349
350
/**
351
* Register WebSocketHandler implementations
352
*/
353
@Target({ElementType.TYPE})
354
@Retention(RetentionPolicy.RUNTIME)
355
public @interface WebSocketHandlerService {
356
/**
357
* Path pattern for WebSocket handler
358
* @return path string
359
*/
360
String path() default "/";
361
362
/**
363
* Broadcaster to use
364
* @return Broadcaster class
365
*/
366
Class<? extends Broadcaster> broadcaster() default Broadcaster.class;
367
}
368
369
/**
370
* Register WebSocketProtocol implementations
371
*/
372
@Target({ElementType.TYPE})
373
@Retention(RetentionPolicy.RUNTIME)
374
public @interface WebSocketProtocolService {
375
}
376
377
/**
378
* Register BroadcasterCache implementations
379
*/
380
@Target({ElementType.TYPE})
381
@Retention(RetentionPolicy.RUNTIME)
382
public @interface BroadcasterCacheService {
383
}
384
385
/**
386
* Register BroadcasterFactory implementations
387
*/
388
@Target({ElementType.TYPE})
389
@Retention(RetentionPolicy.RUNTIME)
390
public @interface BroadcasterFactoryService {
391
}
392
```
393
394
**Usage Examples:**
395
396
```java
397
@BroadcasterService
398
public class CustomBroadcaster extends DefaultBroadcaster {
399
// Custom broadcaster implementation
400
}
401
402
@AtmosphereInterceptorService
403
public class LoggingInterceptor implements AtmosphereInterceptor {
404
// Custom interceptor implementation
405
}
406
407
@WebSocketHandlerService(path = "/websocket/custom")
408
public class CustomWebSocketHandler implements WebSocketHandler {
409
// Custom WebSocket handler
410
}
411
412
@BroadcasterCacheService
413
public class RedisBroadcasterCache implements BroadcasterCache {
414
// Redis-based cache implementation
415
}
416
```
417
418
### Scope and Lifecycle Annotations
419
420
Annotations for controlling component scope and lifecycle management.
421
422
```java { .api }
423
/**
424
* Mark service as singleton instance
425
*/
426
@Target({ElementType.TYPE})
427
@Retention(RetentionPolicy.RUNTIME)
428
public @interface Singleton {
429
}
430
```
431
432
**Usage Examples:**
433
434
```java
435
@ManagedService(path = "/global-counter")
436
@Singleton
437
public class GlobalCounterService {
438
private int counter = 0;
439
440
@Message
441
public int incrementCounter() {
442
return ++counter;
443
}
444
}
445
```
446
447
### Message Processing Interfaces
448
449
Interfaces for encoding and decoding messages in managed services.
450
451
```java { .api }
452
/**
453
* Decode incoming messages from clients
454
*/
455
public interface Decoder<T, U> {
456
/**
457
* Decode incoming message
458
* @param s input message to decode
459
* @return decoded object
460
*/
461
U decode(T s);
462
}
463
464
/**
465
* Encode outgoing messages to clients
466
*/
467
public interface Encoder<T, U> {
468
/**
469
* Encode outgoing message
470
* @param s object to encode
471
* @return encoded message
472
*/
473
U encode(T s);
474
}
475
```
476
477
**Usage Examples:**
478
479
```java
480
public class JsonDecoder implements Decoder<String, ChatMessage> {
481
@Override
482
public ChatMessage decode(String json) {
483
// Parse JSON string to ChatMessage object
484
return gson.fromJson(json, ChatMessage.class);
485
}
486
}
487
488
public class JsonEncoder implements Encoder<ChatMessage, String> {
489
@Override
490
public String encode(ChatMessage message) {
491
// Convert ChatMessage to JSON string
492
return gson.toJson(message);
493
}
494
}
495
496
@ManagedService(path = "/chat")
497
public class ChatService {
498
499
@Message(decoders = {JsonDecoder.class}, encoders = {JsonEncoder.class})
500
public ChatMessage onMessage(ChatMessage incoming) {
501
// Process typed message objects instead of raw strings
502
return new ChatMessage("Processed: " + incoming.getText());
503
}
504
}
505
```
506
507
### Complete Service Example
508
509
```java
510
@ManagedService(path = "/api/chat/{room}")
511
@Singleton
512
public class CompleteChatService {
513
private final Map<String, List<String>> roomHistory = new ConcurrentHashMap<>();
514
515
@Get
516
public void onConnect(@PathParam("room") String roomId,
517
AtmosphereResource resource) {
518
System.out.println("New connection to room: " + roomId);
519
520
// Send room history to new client
521
List<String> history = roomHistory.getOrDefault(roomId, new ArrayList<>());
522
for (String msg : history) {
523
resource.write(msg);
524
}
525
526
resource.suspend();
527
}
528
529
@Ready
530
public void onReady(@PathParam("room") String roomId,
531
AtmosphereResource resource) {
532
resource.getBroadcaster().broadcast("User joined room " + roomId);
533
}
534
535
@Message(decoders = {JsonDecoder.class}, encoders = {JsonEncoder.class})
536
@DeliverTo("/api/chat/{room}")
537
public ChatMessage onMessage(@PathParam("room") String roomId,
538
ChatMessage message) {
539
// Store message in room history
540
roomHistory.computeIfAbsent(roomId, k -> new ArrayList<>())
541
.add(message.getText());
542
543
// Return processed message for broadcast
544
return new ChatMessage("[" + roomId + "] " + message.getText());
545
}
546
547
@Disconnect
548
public void onDisconnect(@PathParam("room") String roomId,
549
AtmosphereResourceEvent event) {
550
System.out.println("User left room: " + roomId);
551
event.getResource().getBroadcaster()
552
.broadcast("User left room " + roomId);
553
}
554
555
@Heartbeat
556
public void onHeartbeat(AtmosphereResourceEvent event) {
557
// Handle heartbeat to keep connection alive
558
System.out.println("Heartbeat from: " + event.getResource().uuid());
559
}
560
}
561
```