CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework--spring-expression

Spring Expression Language (SpEL) provides a powerful expression language for querying and manipulating object graphs at runtime.

Pending
Overview
Eval results
Files

spel-configuration.mddocs/

SpEL Configuration

This document covers SpEL's configuration capabilities, including parser configuration, compiler settings, and performance tuning options.

Parser Configuration

SpelParserConfiguration Class

public class SpelParserConfiguration {
    // Constants
    public static final int DEFAULT_MAX_EXPRESSION_LENGTH = 10000;
    public static final String SPRING_EXPRESSION_COMPILER_MODE_PROPERTY_NAME = 
        "spring.expression.compiler.mode";
    
    // Constructors
    public SpelParserConfiguration();
    public SpelParserConfiguration(SpelCompilerMode compilerMode, ClassLoader compilerClassLoader);
    public SpelParserConfiguration(boolean autoGrowNullReferences, boolean autoGrowCollections);
    public SpelParserConfiguration(boolean autoGrowNullReferences, boolean autoGrowCollections, 
                                 int maximumAutoGrowSize);
    public SpelParserConfiguration(SpelCompilerMode compilerMode, ClassLoader compilerClassLoader,
                                 boolean autoGrowNullReferences, boolean autoGrowCollections,
                                 int maximumAutoGrowSize, int maximumExpressionLength);
    
    // Accessors
    public SpelCompilerMode getCompilerMode();
    public ClassLoader getCompilerClassLoader();
    public boolean isAutoGrowNullReferences();
    public boolean isAutoGrowCollections();
    public int getMaximumAutoGrowSize();
    public int getMaximumExpressionLength();
}

{ .api }

Basic Configuration Examples

// Default configuration
SpelParserConfiguration defaultConfig = new SpelParserConfiguration();

// Configuration with compilation enabled
SpelParserConfiguration compiledConfig = new SpelParserConfiguration(
    SpelCompilerMode.IMMEDIATE,
    Thread.currentThread().getContextClassLoader()
);

// Configuration with auto-grow features
SpelParserConfiguration autoGrowConfig = new SpelParserConfiguration(
    true,  // autoGrowNullReferences
    true,  // autoGrowCollections
    100    // maximumAutoGrowSize
);

// Complete configuration
SpelParserConfiguration fullConfig = new SpelParserConfiguration(
    SpelCompilerMode.MIXED,                          // compilerMode
    Thread.currentThread().getContextClassLoader(), // compilerClassLoader
    true,                                           // autoGrowNullReferences
    true,                                           // autoGrowCollections
    1000,                                          // maximumAutoGrowSize
    50000                                          // maximumExpressionLength
);

// Use configuration with parser
SpelExpressionParser parser = new SpelExpressionParser(fullConfig);

{ .api }

Compiler Configuration

SpelCompilerMode Enum

public enum SpelCompilerMode {
    OFF,        // No compilation, interpreted mode only (default)
    IMMEDIATE,  // Compile immediately after first interpretation
    MIXED       // Switch between interpreted and compiled modes as needed
}

{ .api }

Compilation Modes Explained

OFF Mode (Default)

SpelParserConfiguration config = new SpelParserConfiguration(
    SpelCompilerMode.OFF, 
    null
);
SpelExpressionParser parser = new SpelExpressionParser(config);

// All expressions will be interpreted, no compilation
Expression exp = parser.parseExpression("name.toUpperCase() + ' ' + age");
// Always uses interpretation, slower but more flexible

{ .api }

IMMEDIATE Mode

SpelParserConfiguration config = new SpelParserConfiguration(
    SpelCompilerMode.IMMEDIATE, 
    Thread.currentThread().getContextClassLoader()
);
SpelExpressionParser parser = new SpelExpressionParser(config);

SpelExpression exp = parser.parseRaw("name.toUpperCase() + ' ' + age");

// First evaluation triggers compilation
String result1 = exp.getValue(person, String.class); // Interpreted + compiled
// Subsequent evaluations use compiled code
String result2 = exp.getValue(person, String.class); // Compiled (much faster)

{ .api }

MIXED Mode

SpelParserConfiguration config = new SpelParserConfiguration(
    SpelCompilerMode.MIXED, 
    Thread.currentThread().getContextClassLoader()
);
SpelExpressionParser parser = new SpelExpressionParser(config);

// Expressions can switch between interpreted and compiled modes
// based on success/failure of compilation and execution patterns
SpelExpression exp = parser.parseRaw("complexExpression()");

{ .api }

System Property Configuration

// Set compiler mode via system property
System.setProperty("spring.expression.compiler.mode", "IMMEDIATE");

// Parser will use system property if no explicit configuration provided
SpelExpressionParser parser = new SpelExpressionParser();
// Equivalent to:
// SpelExpressionParser parser = new SpelExpressionParser(
//     new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, classLoader)
// );

{ .api }

Manual Compilation Control

SpelExpressionParser parser = new SpelExpressionParser();
SpelExpression expression = parser.parseRaw("name.length() > 5 ? name.toUpperCase() : name");

// Check if expression can be compiled
boolean compilable = expression.compileExpression();

if (compilable) {
    // Expression was successfully compiled
    String result = expression.getValue(person, String.class); // Uses compiled code
} else {
    // Compilation failed, will use interpreted mode
    String result = expression.getValue(person, String.class); // Uses interpretation
}

// Revert to interpreted mode
expression.revertToInterpreted();
String result = expression.getValue(person, String.class); // Back to interpretation

{ .api }

Auto-Growth Configuration

Null Reference Auto-Growth

public class Container {
    private NestedObject nested;
    // getter and setter
}

public class NestedObject {
    private String value;
    // getter and setter
}

// Enable null reference auto-growth
SpelParserConfiguration config = new SpelParserConfiguration(
    true,  // autoGrowNullReferences
    false  // autoGrowCollections
);
SpelExpressionParser parser = new SpelExpressionParser(config);

Container container = new Container(); // nested is null
StandardEvaluationContext context = new StandardEvaluationContext(container);

// Without auto-growth, this would throw NullPointerException
// With auto-growth, it creates the nested object automatically
Expression exp = parser.parseExpression("nested.value");
exp.setValue(context, "Hello World");

// nested object was created automatically
NestedObject created = container.getNested(); // not null
String value = created.getValue(); // "Hello World"

{ .api }

Collection Auto-Growth

public class ListContainer {
    private List<String> items = new ArrayList<>();
    // getter and setter
}

// Enable collection auto-growth
SpelParserConfiguration config = new SpelParserConfiguration(
    false, // autoGrowNullReferences
    true,  // autoGrowCollections
    10     // maximumAutoGrowSize
);
SpelExpressionParser parser = new SpelExpressionParser(config);

ListContainer container = new ListContainer(); // empty list
StandardEvaluationContext context = new StandardEvaluationContext(container);

// Set value at index 5 in empty list
Expression exp = parser.parseExpression("items[5]");
exp.setValue(context, "Hello");

// List automatically grows to accommodate index 5
List<String> items = container.getItems();
// items.size() == 6, items.get(5) == "Hello", others are null

{ .api }

Combined Auto-Growth

public class ComplexContainer {
    private List<NestedObject> objects;
    // getter and setter
}

// Enable both auto-growth features
SpelParserConfiguration config = new SpelParserConfiguration(
    true,  // autoGrowNullReferences
    true,  // autoGrowCollections
    50     // maximumAutoGrowSize
);
SpelExpressionParser parser = new SpelExpressionParser(config);

ComplexContainer container = new ComplexContainer(); // objects is null
StandardEvaluationContext context = new StandardEvaluationContext(container);

// This will:
// 1. Create the objects list (null reference auto-growth)
// 2. Grow the list to accommodate index 3 (collection auto-growth)
// 3. Create NestedObject at index 3 (null reference auto-growth)
Expression exp = parser.parseExpression("objects[3].value");
exp.setValue(context, "Deep Value");

NestedObject obj = container.getObjects().get(3);
String value = obj.getValue(); // "Deep Value"

{ .api }

Expression Length Limits

Maximum Expression Length

// Set custom maximum expression length
SpelParserConfiguration config = new SpelParserConfiguration(
    SpelCompilerMode.OFF,
    null,
    false, // autoGrowNullReferences
    false, // autoGrowCollections
    0,     // maximumAutoGrowSize
    5000   // maximumExpressionLength (default is 10,000)
);

SpelExpressionParser parser = new SpelExpressionParser(config);

// Expressions longer than 5000 characters will be rejected
String longExpression = "very".repeat(2000) + "long expression";
try {
    Expression exp = parser.parseExpression(longExpression);
} catch (ParseException e) {
    // Expression too long
}

{ .api }

Advanced Configuration Patterns

Environment-Based Configuration

public class SpelConfigurationFactory {
    
    public static SpelParserConfiguration createProductionConfig() {
        return new SpelParserConfiguration(
            SpelCompilerMode.IMMEDIATE, // Aggressive compilation for performance
            Thread.currentThread().getContextClassLoader(),
            false, // Disable auto-growth for predictable behavior
            false,
            0,
            10000  // Standard expression length limit
        );
    }
    
    public static SpelParserConfiguration createDevelopmentConfig() {
        return new SpelParserConfiguration(
            SpelCompilerMode.OFF, // No compilation for easier debugging
            null,
            true,  // Enable auto-growth for convenience
            true,
            100,
            50000  // Larger expression limit for experimentation
        );
    }
    
    public static SpelParserConfiguration createTestConfig() {
        return new SpelParserConfiguration(
            SpelCompilerMode.MIXED, // Mixed mode for testing both paths
            Thread.currentThread().getContextClassLoader(),
            true,  // Auto-growth for test data setup
            true,
            10,
            10000
        );
    }
}

// Usage
String environment = System.getProperty("environment", "development");
SpelParserConfiguration config = switch (environment) {
    case "production" -> SpelConfigurationFactory.createProductionConfig();
    case "test" -> SpelConfigurationFactory.createTestConfig();
    default -> SpelConfigurationFactory.createDevelopmentConfig();
};

SpelExpressionParser parser = new SpelExpressionParser(config);

{ .api }

Configuration with Custom ClassLoader

// Custom class loader for isolation
ClassLoader customClassLoader = new URLClassLoader(
    new URL[]{new URL("file:///path/to/custom/classes/")},
    Thread.currentThread().getContextClassLoader()
);

SpelParserConfiguration config = new SpelParserConfiguration(
    SpelCompilerMode.IMMEDIATE,
    customClassLoader // Use custom class loader for compilation
);

SpelExpressionParser parser = new SpelExpressionParser(config);

// Compiled expressions will use the custom class loader
Expression exp = parser.parseExpression("T(com.custom.MyClass).staticMethod()");

{ .api }

Configuration Best Practices

Performance-Oriented Configuration

// High-performance configuration for production systems
SpelParserConfiguration performanceConfig = new SpelParserConfiguration(
    SpelCompilerMode.IMMEDIATE,                      // Immediate compilation
    Thread.currentThread().getContextClassLoader(), // Appropriate class loader
    false,                                          // Disable auto-growth (predictable)
    false,                                          // Disable auto-growth
    0,                                              // No auto-growth
    10000                                           // Standard limit
);

// Use with cached expressions
Map<String, Expression> expressionCache = new ConcurrentHashMap<>();
SpelExpressionParser parser = new SpelExpressionParser(performanceConfig);

public Expression getCachedExpression(String expressionString) {
    return expressionCache.computeIfAbsent(expressionString, parser::parseExpression);
}

{ .api }

Security-Conscious Configuration

// Security-focused configuration
SpelParserConfiguration secureConfig = new SpelParserConfiguration(
    SpelCompilerMode.OFF, // No compilation to avoid runtime class generation
    null,
    false, // No auto-growth to prevent unexpected object creation
    false,
    0,
    1000   // Strict expression length limit
);

// Combine with SimpleEvaluationContext for additional security
SpelExpressionParser parser = new SpelExpressionParser(secureConfig);
SimpleEvaluationContext context = SimpleEvaluationContext
    .forReadOnlyDataBinding()
    .build();

{ .api }

Development-Friendly Configuration

// Development configuration with helpful features
SpelParserConfiguration devConfig = new SpelParserConfiguration(
    SpelCompilerMode.MIXED, // Test both compilation modes
    Thread.currentThread().getContextClassLoader(),
    true,  // Auto-growth for easier prototyping
    true,
    1000,  // Generous auto-growth limit
    100000 // Large expression limit for experimentation
);

SpelExpressionParser parser = new SpelExpressionParser(devConfig);

// Useful for development: detailed error reporting
public Object safeEvaluate(String expressionString, Object root) {
    try {
        Expression exp = parser.parseExpression(expressionString);
        return exp.getValue(root);
    } catch (ParseException e) {
        System.err.println("Parse error in expression: " + expressionString);
        System.err.println("Error: " + e.toDetailedString());
        return null;
    } catch (EvaluationException e) {
        System.err.println("Evaluation error in expression: " + expressionString);
        System.err.println("Error: " + e.toDetailedString());
        return null;
    }
}

{ .api }

Configuration Validation

Runtime Configuration Checks

public class ConfigurationValidator {
    
    public static void validateConfiguration(SpelParserConfiguration config) {
        SpelCompilerMode mode = config.getCompilerMode();
        ClassLoader classLoader = config.getCompilerClassLoader();
        
        if ((mode == SpelCompilerMode.IMMEDIATE || mode == SpelCompilerMode.MIXED) 
            && classLoader == null) {
            throw new IllegalArgumentException(
                "ClassLoader must be provided for compilation modes");
        }
        
        if (config.getMaximumAutoGrowSize() < 0) {
            throw new IllegalArgumentException(
                "Maximum auto-grow size must be non-negative");
        }
        
        if (config.getMaximumExpressionLength() <= 0) {
            throw new IllegalArgumentException(
                "Maximum expression length must be positive");
        }
    }
    
    public static SpelExpressionParser createValidatedParser(SpelParserConfiguration config) {
        validateConfiguration(config);
        return new SpelExpressionParser(config);
    }
}

{ .api }

Migration and Compatibility

Upgrading Configuration

// Legacy configuration (pre-6.0)
SpelParserConfiguration legacyConfig = new SpelParserConfiguration(
    true,  // autoGrowNullReferences
    true   // autoGrowCollections
);

// Modern equivalent with explicit settings
SpelParserConfiguration modernConfig = new SpelParserConfiguration(
    SpelCompilerMode.OFF,                           // Explicit compiler mode
    Thread.currentThread().getContextClassLoader(), // Explicit class loader
    true,                                          // autoGrowNullReferences
    true,                                          // autoGrowCollections
    Integer.MAX_VALUE,                             // maximumAutoGrowSize
    SpelParserConfiguration.DEFAULT_MAX_EXPRESSION_LENGTH
);

{ .api }

Configuration Compatibility Checking

public class CompatibilityChecker {
    
    public static boolean isCompilationSupported() {
        try {
            SpelParserConfiguration config = new SpelParserConfiguration(
                SpelCompilerMode.IMMEDIATE,
                Thread.currentThread().getContextClassLoader()
            );
            SpelExpressionParser parser = new SpelExpressionParser(config);
            SpelExpression exp = parser.parseRaw("'test'");
            return exp.compileExpression();
        } catch (Exception e) {
            return false;
        }
    }
    
    public static SpelParserConfiguration createCompatibleConfig() {
        if (isCompilationSupported()) {
            return new SpelParserConfiguration(
                SpelCompilerMode.IMMEDIATE,
                Thread.currentThread().getContextClassLoader()
            );
        } else {
            return new SpelParserConfiguration();
        }
    }
}

{ .api }

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework--spring-expression

docs

advanced-features.md

error-handling.md

evaluation-contexts.md

expression-evaluation.md

index.md

method-constructor-resolution.md

property-index-access.md

spel-configuration.md

type-system-support.md

tile.json