---
date: 2025-11-24T07:15:19Z
topic: "OGNL 3.4.8 Upgrade Investigation"
tags: [research, codebase, ognl, upgrade, breaking-changes, security]
status: complete
pr_number: 1405
---

# Research: OGNL 3.4.8 Upgrade Investigation

**Date**: 2025-11-24T07:15:19Z
**PR**: [#1405](https://github.com/apache/struts/pull/1405) - Bump ognl:ognl from 3.3.5 to 3.4.8

## Research Question

What is needed to upgrade Apache Struts from OGNL 3.3.5 to 3.4.8?

## Summary

**CRITICAL FINDING**: The upgrade from OGNL 3.3.5 to 3.4.8 cannot be accomplished by simply bumping the version number. OGNL 3.4.8 introduces **binary-incompatible API changes** that require code modifications across the entire Struts codebase.

The dependabot PR #1405 will **fail to compile** due to breaking changes in three core OGNL interfaces:
- `PropertyAccessor` - changed from `Map context` to `OgnlContext context`
- `TypeConverter` - changed from `Map context` to `OgnlContext context`
- `NullHandler` - changed from `Map context` to `OgnlContext context`

**Impact**: 18+ files in core module require updates, plus additional files in plugins (tiles, etc.)

**Historical Context**: Apache Struts attempted this upgrade in WW-5326 with a solution involving a custom `StrutsContext` wrapper, but this work has not been merged yet.

## Detailed Findings

### 1. Current State

**Branch**: `dependabot/maven/main/ognl-ognl-3.4.8`
**Current Version**: OGNL 3.3.5 (main branch)
**Target Version**: OGNL 3.4.8
**Version Property**: `pom.xml:123` (`<ognl.version>3.4.8</ognl.version>`)

**Compilation Status**: **FAILS** with 15+ compilation errors

### 2. OGNL Version History (3.3.5 → 3.4.8)

#### OGNL 3.4.1 (July 24, 2023)
- JDK17+ compatibility improved
- New helper method for OgnlContext creation
- **BREAKING**: OgnlContext initially removed Map interface implementation

#### OGNL 3.4.2 (August 23, 2023)
- **FIX**: Map interface restored to OgnlContext
- Performance optimization for null value returns

#### OGNL 3.4.3 (April 19, 2024)
- **Security**: Field access validation for property setters
- Enhanced access checks for setting field values

#### OGNL 3.4.4 (December 27, 2024)
- ASTLess class made public
- ObjectPropertyAccessor enhanced with `ignoreReadMethod` parameter

#### OGNL 3.4.5 (January 6, 2025)
- **BREAKING**: OgnlContext normalized to `Map<String, Object>` interface
- SecurityManager-related code marked deprecated
- Context root initialization improved when null

#### OGNL 3.4.6 (February 22, 2025)
- ClassResolver and TypeConverter preservation from previous OgnlContext

#### OGNL 3.4.7 (March 30, 2025)
- Methods flagged as deprecated for removal in 3.5.0

#### OGNL 3.4.8 (October 26, 2024)
- Deprecated methods explicitly marked for removal in 3.5
- Root context preservation during nested evaluations
- Migration to Sonatype Central Repository
- Artifact signing for releases

### 3. Breaking API Changes

#### PropertyAccessor Interface

**OGNL 3.3.5:**
```java
public interface PropertyAccessor {
    Object getProperty(Map context, Object target, Object name) throws OgnlException;
    void setProperty(Map context, Object target, Object name, Object value) throws OgnlException;
    String getSourceAccessor(OgnlContext context, Object target, Object index);
    String getSourceSetter(OgnlContext context, Object target, Object index);
}
```

**OGNL 3.4.8:**
```java
public interface PropertyAccessor {
    Object getProperty(OgnlContext context, Object target, Object name) throws OgnlException;
    void setProperty(OgnlContext context, Object target, Object name, Object value) throws OgnlException;
    String getSourceAccessor(OgnlContext context, Object target, Object index);
    String getSourceSetter(OgnlContext context, Object target, Object index);
}
```

**Change**: First parameter changed from `Map context` to `OgnlContext context` in `getProperty()` and `setProperty()`.

#### TypeConverter Interface

**OGNL 3.3.5:**
```java
public interface TypeConverter {
    Object convertValue(Map context, Object target, Member member,
                       String propertyName, Object value, Class toType);
}
```

**OGNL 3.4.8:**
```java
public interface TypeConverter {
    Object convertValue(OgnlContext context, Object target, Member member,
                       String propertyName, Object value, Class<?> toType);
}
```

**Changes**:
1. First parameter changed from `Map context` to `OgnlContext context`
2. Last parameter changed from `Class toType` to `Class<?> toType` (generic typing)

#### NullHandler Interface

**OGNL 3.3.5:**
```java
public interface NullHandler {
    Object nullMethodResult(Map context, Object target, String methodName, Object[] args);
    Object nullPropertyValue(Map context, Object target, Object property);
}
```

**OGNL 3.4.8:**
```java
public interface NullHandler {
    Object nullMethodResult(OgnlContext context, Object target, String methodName, Object[] args);
    Object nullPropertyValue(OgnlContext context, Object target, Object property);
}
```

**Change**: First parameter changed from `Map context` to `OgnlContext context` in both methods.

#### Ognl.createDefaultContext() Method

**OGNL 3.3.5 Signature:**
```java
public static Map createDefaultContext(
    Object root,
    ClassResolver classResolver,
    TypeConverter converter,
    MemberAccess memberAccess
)
```

**OGNL 3.4.2+ Signature:**
```java
public static OgnlContext createDefaultContext(
    Object root,
    MemberAccess memberAccess,      // MOVED to 2nd position
    ClassResolver classResolver,     // MOVED to 3rd position
    TypeConverter converter          // MOVED to 4th position
)
```

**Breaking Changes**:
1. Return type changed from `Map` to `OgnlContext`
2. Parameter order changed - `MemberAccess` moved from 4th to 2nd position

### 4. Impact on Apache Struts Codebase

#### Compilation Errors

```
[ERROR] /Users/lukaszlenart/Projects/Apache/struts/core/src/main/java/org/apache/struts2/ognl/accessor/XWorkCollectionPropertyAccessor.java:[47,5] method does not override or implement a method from a supertype
[ERROR] /Users/lukaszlenart/Projects/Apache/struts/core/src/main/java/org/apache/struts2/ognl/accessor/XWorkCollectionPropertyAccessor.java:[49,63] incompatible types: java.util.Map cannot be converted to ognl.OgnlContext
[ERROR] /Users/lukaszlenart/Projects/Apache/struts/core/src/main/java/org/apache/struts2/ognl/accessor/XWorkCollectionPropertyAccessor.java:[56,5] method does not override or implement a method from a supertype
...
[ERROR] /Users/lukaszlenart/Projects/Apache/struts/core/src/main/java/org/apache/struts2/ognl/OgnlTypeConverterWrapper.java:[29,8] org.apache.struts2.ognl.OgnlTypeConverterWrapper is not abstract and does not override abstract method convertValue(ognl.OgnlContext,java.lang.Object,java.lang.reflect.Member,java.lang.String,java.lang.Object,java.lang.Class<?>) in ognl.TypeConverter
...
[ERROR] /Users/lukaszlenart/Projects/Apache/struts/core/src/main/java/org/apache/struts2/ognl/OgnlNullHandlerWrapper.java:[25,8] org.apache.struts2.ognl.OgnlNullHandlerWrapper is not abstract and does not override abstract method nullPropertyValue(ognl.OgnlContext,java.lang.Object,java.lang.Object) in ognl.NullHandler
```

#### Files Requiring Changes

**PropertyAccessor Implementations (11 files)**:
- `core/src/main/java/org/apache/struts2/ognl/accessor/XWorkObjectPropertyAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/XWorkMapPropertyAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/XWorkListPropertyAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/XWorkIteratorPropertyAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/XWorkEnumerationAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/XWorkCollectionPropertyAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/RootAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/ParameterPropertyAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/ObjectProxyPropertyAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/ObjectAccessor.java`
- `core/src/main/java/org/apache/struts2/ognl/accessor/HttpParametersPropertyAccessor.java`

**TypeConverter Implementations (5 files)**:
- `core/src/main/java/org/apache/struts2/ognl/XWorkTypeConverterWrapper.java`
- `core/src/main/java/org/apache/struts2/ognl/OgnlTypeConverterWrapper.java`
- `core/src/main/java/org/apache/struts2/conversion/impl/DefaultTypeConverter.java`
- `core/src/main/java/org/apache/struts2/conversion/StrutsTypeConverterHolder.java`
- `core/src/main/java/org/apache/struts2/conversion/StrutsTypeConverterCreator.java`

**NullHandler Implementations (2 files)**:
- `core/src/main/java/org/apache/struts2/ognl/OgnlNullHandlerWrapper.java`
- `core/src/main/java/org/apache/struts2/conversion/impl/InstantiatingNullHandler.java`

**Files Using createDefaultContext (7 files)**:
- `core/src/test/java/org/apache/struts2/ognl/SetPropertiesTest.java`
- `core/src/test/java/org/apache/struts2/ognl/OgnlUtilTest.java`
- `core/src/test/java/org/apache/struts2/ognl/OgnlUtilStrutsTest.java`
- `core/src/main/java/org/apache/struts2/util/reflection/ReflectionContextFactory.java`
- `core/src/main/java/org/apache/struts2/ognl/OgnlValueStack.java`
- `core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java`
- `core/src/main/java/org/apache/struts2/ognl/OgnlReflectionContextFactory.java`

**Total**: 18+ files in core module, plus additional files in plugins (tiles, etc.)

### 5. Security Implications

**Positive Security Changes**:
- Field access validation (OGNL 3.4.3): Enhanced access checks for setting field values
- Property assignment security: Improved validation during property assignment
- No CVEs reported between 3.3.5 and 3.4.8

**Struts Security Layer** (still compatible):
- `SecurityMemberAccess` class with allowlist/exclusion list mechanisms
- `OgnlGuard` interface for expression validation
- `StrutsOgnlGuard` implementation with node type blocking
- Comprehensive security configurations

**Risk Assessment**: LOW security risk for the upgrade itself, but HIGH risk if implementation is incorrect.

### 6. Historical Context: WW-5326

According to Apache Struts mailing list archives, the team attempted this upgrade in **WW-5326** and developed a solution:

**Commits from WW-5326**:
1. "Upgrade to OGNL 3.4.6" - bumped version
2. "Introduces StrutsContext" - created custom wrapper
3. Updated all method signatures

**StrutsContext Approach**:
```java
package org.apache.struts2.ognl;

public class StrutsContext extends OgnlContext {

    private StrutsContext(
        MemberAccess memberAccess,
        ClassResolver classResolver,
        TypeConverter typeConverter,
        OgnlContext initialContext
    ) {
        // Constructor implementation
    }

    public static StrutsContext wrap(OgnlContext context) {
        // Factory method to wrap existing OgnlContext
    }
}
```

**Status**: This work has **NOT been merged** into the current main branch yet.

### 7. Migration Strategy

#### Required Changes

**Step 1: Create StrutsContext Wrapper**
- Create `org.apache.struts2.ognl.StrutsContext` extending `OgnlContext`
- Add factory methods for context creation
- Add convenience methods for Struts-specific functionality

**Step 2: Update PropertyAccessor Implementations**
- Change all `getProperty(Map context, ...)` to `getProperty(OgnlContext context, ...)`
- Change all `setProperty(Map context, ...)` to `setProperty(OgnlContext context, ...)`
- Cast `context` to `Map` internally where needed for backward compatibility

**Step 3: Update TypeConverter Implementations**
- Change `convertValue(Map context, ...)` to `convertValue(OgnlContext context, ...)`
- Update generic type from `Class` to `Class<?>`

**Step 4: Update NullHandler Implementations**
- Change `nullMethodResult(Map context, ...)` to `nullMethodResult(OgnlContext context, ...)`
- Change `nullPropertyValue(Map context, ...)` to `nullPropertyValue(OgnlContext context, ...)`

**Step 5: Update createDefaultContext Calls**
- Update parameter order: move `MemberAccess` to 2nd position
- Update return type handling from `Map` to `OgnlContext`
- Located in `OgnlUtil.java:724` and `OgnlReflectionContextFactory.java:34`

**Step 6: Update All Method Signatures**
- Search for all methods accepting `Map context` that interact with OGNL
- Update to `OgnlContext context` or `StrutsContext context`

**Step 7: Update Tests**
- Update all tests using `Map` context to use `OgnlContext`
- Verify OGNL-specific tests pass
- Run security tests

### 8. Testing Strategy

**Critical Test Suites**:
```bash
# OGNL-specific tests
mvn test -pl core -Dtest="*Ognl*Test" -DskipAssembly

# Security tests
mvn test -pl core -Dtest="SecurityMemberAccessTest" -DskipAssembly

# Full core module tests
mvn clean test -pl core -DskipAssembly

# Complete build
mvn clean install -DskipAssembly

# Integration tests
mvn clean package -pl apps/showcase
```

**Existing OGNL Test Coverage**:
- `OgnlUtilTest.java` (78KB - comprehensive)
- `OgnlValueStackTest.java` (50KB - comprehensive)
- `SecurityMemberAccessTest.java` (37KB - security-focused)
- `SetPropertiesTest.java` (14KB)
- `OgnlSetPossiblePropertyTest.java` (9KB)
- `StrutsOgnlGuardTest.java` (2.7KB)
- `ProviderAllowlistTest.java` (3KB)
- Accessor tests (XWorkMapPropertyAccessorTest, XWorkListPropertyAccessorTest)

### 9. Complexity Estimate

**Scope**:
- **Files to Modify**: 18+ in core module, unknown number in plugins
- **Lines of Code**: Potentially 200-500 lines across all files
- **Binary Compatibility**: Breaking changes requiring signature updates

**Effort Estimation**:
- **Development**: 2-3 days
- **Testing**: 2-3 days
- **Code Review**: 1 day
- **Total**: 5-7 days

**Risk Assessment**:
- **Technical Risk**: Medium-High (affects security-critical OGNL subsystem)
- **Regression Risk**: Medium (comprehensive test suite exists)
- **Security Risk**: Low (positive security improvements in OGNL 3.4.8)

### 10. Recommended Next Steps

#### Option 1: Full Implementation (Recommended for Long-Term)
1. Create JIRA ticket (e.g., WW-XXXX)
2. Implement StrutsContext wrapper based on WW-5326 approach
3. Update all 18+ affected files
4. Run comprehensive test suite
5. Create PR with detailed migration notes
6. Extensive code review and testing

**Pros**: Future-proof, positive security improvements, stays current with OGNL
**Cons**: Significant development effort, risk of regressions

#### Option 2: Stay on OGNL 3.3.5 (Recommended for Short-Term)
1. Close/reject dependabot PR #1405
2. Document reasons for staying on 3.3.5
3. Create tracking ticket for future upgrade
4. Remain on OGNL 3.3.5 until ready for breaking changes

**Pros**: No risk, stable, no development effort
**Cons**: Missing minor improvements and bug fixes

#### Option 3: Research Existing Work
1. Check if WW-5326 implementation exists in feature branches
2. Check if Struts 7.x or 8.x already has this upgrade
3. Potentially backport or cherry-pick the changes
4. Coordinate with Struts team on timing

**Pros**: Leverage existing work, community coordination
**Cons**: May not exist, may need adaptation

### 11. Configuration Changes

**No configuration changes required** - OGNL 3.4.8 maintains backward compatibility in configuration and usage patterns. Only code changes are needed.

**Deprecation Warnings**:
- SecurityManager-related methods deprecated (removal planned for OGNL 3.5.0)
- Current Struts code doesn't use deprecated SecurityManager APIs

## Code References

- `pom.xml:123` - OGNL version property
- `core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java:724` - createDefaultContext usage
- `core/src/main/java/org/apache/struts2/ognl/accessor/` - PropertyAccessor implementations
- `core/src/main/java/org/apache/struts2/ognl/OgnlTypeConverterWrapper.java:41` - TypeConverter implementation
- `core/src/main/java/org/apache/struts2/ognl/OgnlNullHandlerWrapper.java:33` - NullHandler implementation

## Architecture Insights

**OGNL Integration Pattern**:
- Struts wraps OGNL APIs with custom implementations (XWork* classes)
- Context management abstracted through factory pattern
- Security enforced through SecurityMemberAccess and OgnlGuard
- Type conversion handled through wrapper pattern

**Design Decision**: OGNL 3.4.5 normalized context parameter to `OgnlContext` for type safety and better API design. This breaks backward compatibility but provides:
- Stronger type checking at compile time
- Better IDE support and autocomplete
- Cleaner API with explicit context type
- Foundation for future OGNL 3.5.x improvements

## Related Research

- Historical: WW-5326 implementation approach
- Future: OGNL 3.5.0 will remove deprecated SecurityManager APIs
- Related: Jakarta EE migration efforts may intersect with OGNL upgrade timing

## Open Questions

1. **Does WW-5326 implementation exist in any feature branch?**
   - Need to search Struts repository for existing work

2. **Is Struts 7.x or 8.x planning this upgrade?**
   - Check roadmap and release plans

3. **Should we coordinate with Struts community on timing?**
   - Major breaking change may warrant coordination

4. **Are there any Tiles plugin PropertyAccessor implementations?**
   - Need to check plugins directory for additional affected files

5. **What is the migration path for third-party Struts plugins?**
   - Community plugins may break with this change

## Sources

- [OGNL GitHub Releases](https://github.com/orphan-oss/ognl/releases)
- [OGNL 3.4.8 PropertyAccessor Source](https://github.com/orphan-oss/ognl/blob/OGNL_3_4_8/src/main/java/ognl/PropertyAccessor.java)
- [OGNL 3.3.5 PropertyAccessor Source](https://github.com/orphan-oss/ognl/blob/OGNL_3_3_5/src/main/java/ognl/PropertyAccessor.java)
- [OGNL 3.4.8 TypeConverter Source](https://github.com/orphan-oss/ognl/blob/OGNL_3_4_8/src/main/java/ognl/TypeConverter.java)
- [OGNL 3.3.5 TypeConverter Source](https://github.com/orphan-oss/ognl/blob/OGNL_3_3_5/src/main/java/ognl/TypeConverter.java)
- [OGNL 3.4.8 NullHandler Source](https://github.com/orphan-oss/ognl/blob/OGNL_3_4_8/src/main/java/ognl/NullHandler.java)
- [OGNL 3.3.5 NullHandler Source](https://github.com/orphan-oss/ognl/blob/OGNL_3_3_5/src/main/java/ognl/NullHandler.java)
- [Apache Struts Mailing List: Upgrade to OGNL 3.5.x](https://www.mail-archive.com/dev@struts.apache.org/msg47679.html)
- [Stack Overflow: Error uplifting OGNL from 3.3.4 to 3.4.2](https://stackoverflow.com/questions/78135587/error-uplifting-ognl-from-3-3-4-to-3-4-2-with-struts26-3-0-2)
- [Stack Overflow: NoSuchMethodError for Ognl.createDefaultContext()](https://stackoverflow.com/questions/78581365/java-lang-nosuchmethoderror-for-ognl-createdefaultcontext-in-struts-6-4-0)
- [Struts GitHub PR #1405](https://github.com/apache/struts/pull/1405)
