or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mderror-handling.mdevaluation-contexts.mdexpression-evaluation.mdindex.mdmethod-constructor-resolution.mdproperty-index-access.mdspel-configuration.mdtype-system-support.md

expression-evaluation.mddocs/

0

# Expression Evaluation

1

2

This document covers SpEL's expression evaluation capabilities, including the core interfaces, standard implementations, and evaluation patterns.

3

4

## Core Expression Evaluation

5

6

### SpelExpressionParser Class

7

8

```java

9

public class SpelExpressionParser extends TemplateAwareExpressionParser {

10

public SpelExpressionParser();

11

public SpelExpressionParser(SpelParserConfiguration configuration);

12

13

public SpelExpression parseRaw(String expressionString) throws ParseException;

14

// Inherited from ExpressionParser:

15

public Expression parseExpression(String expressionString) throws ParseException;

16

public Expression parseExpression(String expressionString, ParserContext context)

17

throws ParseException;

18

}

19

```

20

{ .api }

21

22

The SpelExpressionParser is thread-safe and should be reused across multiple parsing operations for better performance.

23

24

### SpelExpression Class

25

26

```java

27

public class SpelExpression implements Expression {

28

// Configuration

29

public void setEvaluationContext(EvaluationContext evaluationContext);

30

public EvaluationContext getEvaluationContext();

31

32

// Compilation

33

public boolean compileExpression();

34

public void revertToInterpreted();

35

36

// AST Access

37

public SpelNode getAST();

38

public String toStringAST();

39

40

// Expression Interface Methods

41

public String getExpressionString();

42

43

public Object getValue() throws EvaluationException;

44

public <T> T getValue(Class<T> desiredResultType) throws EvaluationException;

45

public Object getValue(Object rootObject) throws EvaluationException;

46

public Object getValue(EvaluationContext context) throws EvaluationException;

47

public Object getValue(EvaluationContext context, Object rootObject) throws EvaluationException;

48

public <T> T getValue(EvaluationContext context, Object rootObject, Class<T> expectedResultType)

49

throws EvaluationException;

50

51

public Class<?> getValueType() throws EvaluationException;

52

public Class<?> getValueType(Object rootObject) throws EvaluationException;

53

public Class<?> getValueType(EvaluationContext context) throws EvaluationException;

54

public Class<?> getValueType(EvaluationContext context, Object rootObject)

55

throws EvaluationException;

56

57

public TypeDescriptor getValueTypeDescriptor() throws EvaluationException;

58

public TypeDescriptor getValueTypeDescriptor(Object rootObject) throws EvaluationException;

59

public TypeDescriptor getValueTypeDescriptor(EvaluationContext context) throws EvaluationException;

60

public TypeDescriptor getValueTypeDescriptor(EvaluationContext context, Object rootObject)

61

throws EvaluationException;

62

63

public boolean isWritable(Object rootObject) throws EvaluationException;

64

public boolean isWritable(EvaluationContext context) throws EvaluationException;

65

public boolean isWritable(EvaluationContext context, Object rootObject) throws EvaluationException;

66

67

public void setValue(Object rootObject, Object value) throws EvaluationException;

68

public void setValue(EvaluationContext context, Object value) throws EvaluationException;

69

public void setValue(EvaluationContext context, Object rootObject, Object value)

70

throws EvaluationException;

71

}

72

```

73

{ .api }

74

75

## Parser Context Support

76

77

### ParserContext Interface

78

79

```java

80

public interface ParserContext {

81

boolean isTemplate();

82

String getExpressionPrefix();

83

String getExpressionSuffix();

84

85

// Constants

86

ParserContext TEMPLATE_EXPRESSION = new TemplateParserContext();

87

}

88

```

89

{ .api }

90

91

### TemplateParserContext Class

92

93

```java

94

public class TemplateParserContext implements ParserContext {

95

public TemplateParserContext();

96

public TemplateParserContext(String expressionPrefix, String expressionSuffix);

97

98

public boolean isTemplate();

99

public String getExpressionPrefix();

100

public String getExpressionSuffix();

101

}

102

```

103

{ .api }

104

105

## Expression Types

106

107

### LiteralExpression Class

108

109

```java

110

public class LiteralExpression implements Expression {

111

public LiteralExpression(String literalValue);

112

113

public String getExpressionString();

114

public Object getValue() throws EvaluationException;

115

public <T> T getValue(Class<T> expectedResultType) throws EvaluationException;

116

public Object getValue(Object rootObject) throws EvaluationException;

117

public Object getValue(EvaluationContext context) throws EvaluationException;

118

public Object getValue(EvaluationContext context, Object rootObject) throws EvaluationException;

119

public <T> T getValue(EvaluationContext context, Object rootObject, Class<T> expectedResultType)

120

throws EvaluationException;

121

122

public Class<?> getValueType();

123

public Class<?> getValueType(Object rootObject);

124

public Class<?> getValueType(EvaluationContext context);

125

public Class<?> getValueType(EvaluationContext context, Object rootObject);

126

127

public TypeDescriptor getValueTypeDescriptor();

128

public TypeDescriptor getValueTypeDescriptor(Object rootObject);

129

public TypeDescriptor getValueTypeDescriptor(EvaluationContext context);

130

public TypeDescriptor getValueTypeDescriptor(EvaluationContext context, Object rootObject);

131

132

public boolean isWritable(Object rootObject);

133

public boolean isWritable(EvaluationContext context);

134

public boolean isWritable(EvaluationContext context, Object rootObject);

135

136

public void setValue(Object rootObject, Object value);

137

public void setValue(EvaluationContext context, Object value);

138

public void setValue(EvaluationContext context, Object rootObject, Object value);

139

}

140

```

141

{ .api }

142

143

### CompositeStringExpression Class

144

145

```java

146

public class CompositeStringExpression implements Expression {

147

public CompositeStringExpression(String expressionString, Expression[] expressions);

148

149

// Implements all Expression interface methods

150

// Evaluates each sub-expression and concatenates results as strings

151

}

152

```

153

{ .api }

154

155

## Expression Language Features

156

157

### Basic Syntax Examples

158

159

```java

160

ExpressionParser parser = new SpelExpressionParser();

161

162

// Literals

163

Expression exp = parser.parseExpression("'Hello World'");

164

String result = exp.getValue(String.class); // "Hello World"

165

166

exp = parser.parseExpression("42");

167

Integer number = exp.getValue(Integer.class); // 42

168

169

exp = parser.parseExpression("true");

170

Boolean bool = exp.getValue(Boolean.class); // true

171

172

// Mathematical operations

173

exp = parser.parseExpression("2 + 3 * 4");

174

Integer math = exp.getValue(Integer.class); // 14

175

176

exp = parser.parseExpression("10 / 3.0");

177

Double division = exp.getValue(Double.class); // 3.3333333333333335

178

179

// String operations

180

exp = parser.parseExpression("'Hello' + ' ' + 'World'");

181

String concat = exp.getValue(String.class); // "Hello World"

182

183

// Logical operations

184

exp = parser.parseExpression("true and false");

185

Boolean logical = exp.getValue(Boolean.class); // false

186

187

exp = parser.parseExpression("2 > 1 ? 'yes' : 'no'");

188

String conditional = exp.getValue(String.class); // "yes"

189

```

190

{ .api }

191

192

### Property Access

193

194

```java

195

public class Person {

196

private String name;

197

private int age;

198

private Address address;

199

// getters and setters...

200

}

201

202

public class Address {

203

private String city;

204

private String country;

205

// getters and setters...

206

}

207

208

Person person = new Person();

209

person.setName("John");

210

person.setAge(30);

211

212

ExpressionParser parser = new SpelExpressionParser();

213

214

// Direct property access

215

Expression exp = parser.parseExpression("name");

216

String name = exp.getValue(person, String.class); // "John"

217

218

// Method invocation

219

exp = parser.parseExpression("name.toUpperCase()");

220

String upperName = exp.getValue(person, String.class); // "JOHN"

221

222

// Nested property access

223

exp = parser.parseExpression("address?.city");

224

String city = exp.getValue(person, String.class); // null (safe navigation)

225

226

// Property assignment (requires StandardEvaluationContext)

227

StandardEvaluationContext context = new StandardEvaluationContext(person);

228

exp = parser.parseExpression("name");

229

exp.setValue(context, "Jane");

230

```

231

{ .api }

232

233

### Collection and Array Access

234

235

```java

236

List<String> names = Arrays.asList("John", "Jane", "Bob");

237

Map<String, Integer> ages = Map.of("John", 30, "Jane", 25, "Bob", 35);

238

int[] numbers = {1, 2, 3, 4, 5};

239

240

ExpressionParser parser = new SpelExpressionParser();

241

StandardEvaluationContext context = new StandardEvaluationContext();

242

context.setVariable("names", names);

243

context.setVariable("ages", ages);

244

context.setVariable("numbers", numbers);

245

246

// List access

247

Expression exp = parser.parseExpression("#names[0]");

248

String firstName = exp.getValue(context, String.class); // "John"

249

250

// Map access

251

exp = parser.parseExpression("#ages['John']");

252

Integer age = exp.getValue(context, Integer.class); // 30

253

254

// Array access

255

exp = parser.parseExpression("#numbers[2]");

256

Integer number = exp.getValue(context, Integer.class); // 3

257

258

// Collection methods

259

exp = parser.parseExpression("#names.size()");

260

Integer size = exp.getValue(context, Integer.class); // 3

261

262

// Collection filtering and projection

263

exp = parser.parseExpression("#names.?[length() > 3]"); // Filter

264

List<String> filtered = (List<String>) exp.getValue(context); // ["John", "Jane"]

265

266

exp = parser.parseExpression("#names.![toUpperCase()]"); // Projection

267

List<String> projected = (List<String>) exp.getValue(context); // ["JOHN", "JANE", "BOB"]

268

```

269

{ .api }

270

271

### Variables and Functions

272

273

```java

274

StandardEvaluationContext context = new StandardEvaluationContext();

275

276

// Setting variables

277

context.setVariable("greeting", "Hello");

278

context.setVariable("name", "World");

279

280

// Using variables

281

ExpressionParser parser = new SpelExpressionParser();

282

Expression exp = parser.parseExpression("#greeting + ' ' + #name");

283

String message = exp.getValue(context, String.class); // "Hello World"

284

285

// Registering functions

286

context.registerFunction("reverse",

287

String.class.getDeclaredMethod("valueOf", Object.class));

288

289

exp = parser.parseExpression("#reverse('hello')");

290

String reversed = exp.getValue(context, String.class);

291

292

// Built-in variables (when available)

293

exp = parser.parseExpression("#this"); // Current object

294

exp = parser.parseExpression("#root"); // Root object

295

```

296

{ .api }

297

298

### Type References

299

300

```java

301

ExpressionParser parser = new SpelExpressionParser();

302

StandardEvaluationContext context = new StandardEvaluationContext();

303

304

// Type references

305

Expression exp = parser.parseExpression("T(java.lang.Math).PI");

306

Double pi = exp.getValue(context, Double.class); // 3.141592653589793

307

308

exp = parser.parseExpression("T(java.lang.Math).max(2, 3)");

309

Integer max = exp.getValue(context, Integer.class); // 3

310

311

// Constructor invocation

312

exp = parser.parseExpression("new java.util.Date()");

313

Date date = exp.getValue(context, Date.class);

314

315

exp = parser.parseExpression("new String('hello').toUpperCase()");

316

String upper = exp.getValue(context, String.class); // "HELLO"

317

```

318

{ .api }

319

320

## Advanced Evaluation Patterns

321

322

### Template Expressions

323

324

```java

325

ExpressionParser parser = new SpelExpressionParser();

326

Map<String, Object> vars = new HashMap<>();

327

vars.put("name", "John");

328

vars.put("age", 30);

329

330

StandardEvaluationContext context = new StandardEvaluationContext();

331

context.setVariables(vars);

332

333

// Template with multiple expressions

334

String template = "Hello #{#name}, you are #{#age} years old and next year you'll be #{#age + 1}!";

335

Expression exp = parser.parseExpression(template, ParserContext.TEMPLATE_EXPRESSION);

336

String result = exp.getValue(context, String.class);

337

// "Hello John, you are 30 years old and next year you'll be 31!"

338

```

339

{ .api }

340

341

### Safe Navigation

342

343

```java

344

public class Customer {

345

private Address address;

346

// getters and setters...

347

}

348

349

Customer customer = new Customer(); // address is null

350

351

ExpressionParser parser = new SpelExpressionParser();

352

353

// Safe navigation operator (?.): prevents NullPointerException

354

Expression exp = parser.parseExpression("address?.city");

355

String city = exp.getValue(customer, String.class); // null (no exception)

356

357

// Without safe navigation (would throw NullPointerException)

358

// exp = parser.parseExpression("address.city"); // Throws exception

359

```

360

{ .api }

361

362

### Elvis Operator

363

364

```java

365

ExpressionParser parser = new SpelExpressionParser();

366

StandardEvaluationContext context = new StandardEvaluationContext();

367

context.setVariable("name", null);

368

369

// Elvis operator (?:): provides default value for null

370

Expression exp = parser.parseExpression("#name ?: 'Unknown'");

371

String name = exp.getValue(context, String.class); // "Unknown"

372

373

context.setVariable("name", "John");

374

name = exp.getValue(context, String.class); // "John"

375

```

376

{ .api }

377

378

### Regular Expressions

379

380

```java

381

ExpressionParser parser = new SpelExpressionParser();

382

StandardEvaluationContext context = new StandardEvaluationContext();

383

context.setVariable("text", "Hello World");

384

385

// Pattern matching

386

Expression exp = parser.parseExpression("#text matches '[A-Z].*'");

387

Boolean matches = exp.getValue(context, Boolean.class); // true

388

389

// Case-insensitive matching

390

exp = parser.parseExpression("#text matches '(?i)hello.*'");

391

matches = exp.getValue(context, Boolean.class); // true

392

```

393

{ .api }

394

395

## Performance Optimization

396

397

### Expression Compilation

398

399

```java

400

// Enable compilation for better performance

401

SpelParserConfiguration config = new SpelParserConfiguration(

402

SpelCompilerMode.IMMEDIATE,

403

Thread.currentThread().getContextClassLoader()

404

);

405

SpelExpressionParser parser = new SpelExpressionParser(config);

406

407

SpelExpression expression = parser.parseRaw("name.toUpperCase() + age.toString()");

408

409

// First evaluation interprets the expression

410

String result1 = expression.getValue(person, String.class);

411

412

// Subsequent evaluations use compiled bytecode (much faster)

413

String result2 = expression.getValue(person, String.class);

414

415

// Check if expression is compiled

416

boolean isCompiled = expression.compileExpression(); // true if successfully compiled

417

418

// Revert to interpreted mode if needed

419

expression.revertToInterpreted();

420

```

421

{ .api }

422

423

### Expression Caching

424

425

```java

426

// Cache frequently used expressions

427

public class ExpressionCache {

428

private final Map<String, Expression> cache = new ConcurrentHashMap<>();

429

private final ExpressionParser parser = new SpelExpressionParser();

430

431

public Expression getExpression(String expressionString) {

432

return cache.computeIfAbsent(expressionString, parser::parseExpression);

433

}

434

}

435

436

// Usage

437

ExpressionCache cache = new ExpressionCache();

438

Expression exp = cache.getExpression("name.toUpperCase()");

439

String result = exp.getValue(person, String.class);

440

```

441

{ .api }

442

443

## Best Practices

444

445

1. **Reuse Parsers**: SpelExpressionParser is thread-safe and expensive to create

446

2. **Cache Expressions**: Cache compiled expressions for repeated use

447

3. **Use Compilation**: Enable compilation for frequently-evaluated expressions

448

4. **Choose Appropriate Context**: Use SimpleEvaluationContext for better security and performance in data-binding scenarios

449

5. **Handle Exceptions**: Always handle ParseException and EvaluationException appropriately

450

6. **Safe Navigation**: Use safe navigation operator (?.) to avoid NullPointerException

451

7. **Type Safety**: Specify expected result types when calling getValue()

452

453

## Thread Safety Notes

454

455

- **SpelExpressionParser**: Thread-safe, can be shared across threads

456

- **SpelExpression**: Thread-safe for evaluation, but configuration methods should not be called concurrently

457

- **EvaluationContext**: Generally not thread-safe, create separate instances per thread or evaluation

458

- **Compilation**: Compiled expressions are thread-safe for evaluation