or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotation-handling.mdcore-messaging.mdindex.mdmessage-conversion.mdmessaging-templates.mdrsocket-integration.mdstomp-websocket.md

annotation-handling.mddocs/

0

# Annotation-Based Handling

1

2

Declarative message handling using annotations for mapping messages to handler methods, extracting payloads and headers, and defining response destinations.

3

4

## Capabilities

5

6

### Core Annotations

7

8

Primary annotations for mapping messages to handler methods and extracting message components.

9

10

```java { .api }

11

/**

12

* Annotation for mapping a Message onto a message-handling method by matching

13

* the declared patterns to a destination extracted from the message.

14

*/

15

@Target({ElementType.TYPE, ElementType.METHOD})

16

@Retention(RetentionPolicy.RUNTIME)

17

@Documented

18

public @interface MessageMapping {

19

/**

20

* Destination patterns to map to. Supports Ant-style path patterns with placeholders.

21

*/

22

String[] value() default {};

23

}

24

25

/**

26

* Annotation that binds a method parameter to the payload of a message.

27

*/

28

@Target(ElementType.PARAMETER)

29

@Retention(RetentionPolicy.RUNTIME)

30

@Documented

31

public @interface Payload {

32

/**

33

* A SpEL expression to be evaluated against the payload object as the root context.

34

*/

35

String value() default "";

36

37

/**

38

* Whether payload content is required.

39

*/

40

boolean required() default true;

41

}

42

43

/**

44

* Annotation which indicates that a method parameter should be bound to a message header.

45

*/

46

@Target(ElementType.PARAMETER)

47

@Retention(RetentionPolicy.RUNTIME)

48

@Documented

49

public @interface Header {

50

/**

51

* The name of the request header to bind to.

52

*/

53

String value() default "";

54

55

/**

56

* The name of the request header to bind to.

57

*/

58

String name() default "";

59

60

/**

61

* Whether the header is required.

62

*/

63

boolean required() default true;

64

65

/**

66

* The default value as a fallback.

67

*/

68

String defaultValue() default ValueConstants.DEFAULT_NONE;

69

}

70

71

/**

72

* Annotation which indicates that a method parameter should be bound to the headers of a message.

73

*/

74

@Target(ElementType.PARAMETER)

75

@Retention(RetentionPolicy.RUNTIME)

76

@Documented

77

public @interface Headers {

78

// No attributes - binds all headers as a Map

79

}

80

```

81

82

### Destination and Response Annotations

83

84

Annotations for handling destination variables and specifying response destinations.

85

86

```java { .api }

87

/**

88

* Annotation to indicate that a method parameter is bound to a URI template variable.

89

*/

90

@Target(ElementType.PARAMETER)

91

@Retention(RetentionPolicy.RUNTIME)

92

@Documented

93

public @interface DestinationVariable {

94

/**

95

* The name of the destination template variable to bind to.

96

*/

97

String value() default "";

98

99

/**

100

* Whether the destination variable is required.

101

*/

102

boolean required() default true;

103

}

104

105

/**

106

* Annotation for sending a message as a response to the current message.

107

*/

108

@Target({ElementType.TYPE, ElementType.METHOD})

109

@Retention(RetentionPolicy.RUNTIME)

110

@Documented

111

public @interface SendTo {

112

/**

113

* Destination where the return value should be sent.

114

*/

115

String[] value() default {};

116

}

117

118

/**

119

* Annotation for sending a message to the specified user-specific destination.

120

*/

121

@Target({ElementType.TYPE, ElementType.METHOD})

122

@Retention(RetentionPolicy.RUNTIME)

123

@Documented

124

public @interface SendToUser {

125

/**

126

* User destinations where the return value should be sent.

127

*/

128

String[] value() default {};

129

130

/**

131

* Whether to broadcast to all sessions of the user.

132

*/

133

boolean broadcast() default true;

134

}

135

```

136

137

### Exception Handling Annotations

138

139

Annotations for handling exceptions in message processing.

140

141

```java { .api }

142

/**

143

* Annotation for handling exceptions thrown from message-handling methods within a specific handler class.

144

*/

145

@Target(ElementType.METHOD)

146

@Retention(RetentionPolicy.RUNTIME)

147

@Documented

148

public @interface MessageExceptionHandler {

149

/**

150

* Exceptions handled by the annotated method.

151

*/

152

Class<? extends Throwable>[] value() default {};

153

}

154

```

155

156

### SIMP-Specific Annotations

157

158

Annotations specific to SIMP (Simple Messaging Protocol) for WebSocket messaging.

159

160

```java { .api }

161

/**

162

* Annotation for mapping subscription requests onto specific handler methods based on the destination.

163

*/

164

@Target(ElementType.METHOD)

165

@Retention(RetentionPolicy.RUNTIME)

166

@Documented

167

public @interface SubscribeMapping {

168

/**

169

* Destination patterns for subscription requests.

170

*/

171

String[] value() default {};

172

}

173

```

174

175

### RSocket-Specific Annotations

176

177

Annotations specific to RSocket protocol handling.

178

179

```java { .api }

180

/**

181

* Annotation for mapping RSocket connection requests onto handler methods.

182

*/

183

@Target(ElementType.METHOD)

184

@Retention(RetentionPolicy.RUNTIME)

185

@Documented

186

public @interface ConnectMapping {

187

/**

188

* Patterns for matching connection setup frame routes.

189

*/

190

String[] value() default {};

191

}

192

```

193

194

### Constants

195

196

Constants used in annotation default values.

197

198

```java { .api }

199

/**

200

* Common value constants shared between bind annotations.

201

*/

202

public final class ValueConstants {

203

204

/**

205

* Constant defining a value for "default none" - used as a marker for a default

206

* value that hasn't been provided and should be resolved in another way.

207

*/

208

public static final String DEFAULT_NONE = "\n\t\t\n\t\t\n\uE000\uE001\uE002\n\t\t\t\t\n";

209

210

private ValueConstants() {

211

// Private constructor

212

}

213

}

214

```

215

216

**Usage Examples:**

217

218

```java

219

import org.springframework.messaging.handler.annotation.*;

220

import org.springframework.messaging.simp.annotation.*;

221

import org.springframework.stereotype.Controller;

222

223

@Controller

224

public class ChatController {

225

226

// Basic message mapping

227

@MessageMapping("/chat.sendMessage")

228

@SendTo("/topic/public")

229

public ChatMessage sendMessage(@Payload ChatMessage chatMessage) {

230

return chatMessage;

231

}

232

233

// Extract specific headers

234

@MessageMapping("/chat.addUser")

235

@SendTo("/topic/public")

236

public ChatMessage addUser(@Payload ChatMessage chatMessage,

237

@Header("simpSessionId") String sessionId,

238

@Header(value = "priority", defaultValue = "normal") String priority) {

239

chatMessage.setSender(sessionId);

240

return chatMessage;

241

}

242

243

// Use destination variables (path parameters)

244

@MessageMapping("/chat.room.{roomId}")

245

@SendTo("/topic/room.{roomId}")

246

public ChatMessage sendToRoom(@DestinationVariable String roomId,

247

@Payload ChatMessage message) {

248

message.setRoom(roomId);

249

return message;

250

}

251

252

// Access all headers

253

@MessageMapping("/chat.debug")

254

public void debugMessage(@Payload String message,

255

@Headers Map<String, Object> headers) {

256

System.out.println("Message: " + message);

257

System.out.println("Headers: " + headers);

258

}

259

260

// User-specific messaging

261

@MessageMapping("/chat.private")

262

@SendToUser("/queue/reply")

263

public String handlePrivateMessage(@Payload String message,

264

Principal principal) {

265

return "Hello " + principal.getName() + ", you sent: " + message;

266

}

267

268

// Subscription mapping for WebSocket

269

@SubscribeMapping("/topic/activity")

270

public ActivityMessage getActivity() {

271

return new ActivityMessage("Current activity status");

272

}

273

274

// Exception handling

275

@MessageExceptionHandler(IllegalArgumentException.class)

276

@SendToUser("/queue/errors")

277

public String handleException(IllegalArgumentException ex) {

278

return "Error: " + ex.getMessage();

279

}

280

281

// Multiple exception types

282

@MessageExceptionHandler({IllegalArgumentException.class, IllegalStateException.class})

283

public void handleMultipleExceptions(Exception ex) {

284

// Handle multiple exception types

285

}

286

287

// RSocket connection mapping

288

@ConnectMapping("setup")

289

public void handleConnection(@Header Map<String, Object> metadata) {

290

// Handle RSocket connection setup

291

}

292

}

293

294

// Example with class-level mapping

295

@Controller

296

@MessageMapping("/app")

297

public class AppController {

298

299

// Inherits "/app" prefix, so actual mapping is "/app/hello"

300

@MessageMapping("/hello")

301

@SendTo("/topic/greetings")

302

public Greeting greeting(@Payload HelloMessage message) {

303

return new Greeting("Hello, " + message.getName() + "!");

304

}

305

}

306

```