Skip to content

Latest commit

 

History

History
515 lines (392 loc) · 15.3 KB

File metadata and controls

515 lines (392 loc) · 15.3 KB

Dependency and Framework Upgrades

This document describes major dependency upgrades and fixes implemented in TreeBASE to support Java 17 and modern frameworks.

Table of Contents

  1. Spring Framework 5.3.39 Upgrade
  2. Security Dependency Upgrades
  3. SLF4J and Logging Framework Compatibility
  4. Jersey 2.x Upgrade
  5. JUnit 4 Migration

Spring Framework 5.3.39 Upgrade

Problem

The project was using Spring Framework 5.3.26 with hardcoded versions spread across multiple pom.xml files. This made version management difficult and led to inconsistent transitive dependency versions.

Solution

Upgraded Spring Framework from 5.3.26 to 5.3.39 (the latest 5.x LTS release) and centralized version management using Maven properties.

Changes in parent pom.xml:

<!-- Centralized version management -->
<properties>
  <!-- Spring Framework 5.3.39 - latest 5.x LTS release with security fixes -->
  <spring.version>5.3.39</spring.version>
  <!-- Spring Security 5.8.15 - compatible with Spring 5.3.x -->
  <spring.security.version>5.8.15</spring.security.version>
  <!-- Log4j 2.24.3 - latest stable with security fixes -->
  <log4j.version>2.24.3</log4j.version>
  <!-- SLF4J 1.7.36 - required for Spring 5.x spring-jcl compatibility -->
  <slf4j.version>1.7.36</slf4j.version>
</properties>

<!-- Now using ${spring.version} for all Spring dependencies -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>${spring.version}</version>
</dependency>

Benefits

  • ✅ Latest Spring 5.x LTS with security patches
  • ✅ Centralized version management - change one property to update all modules
  • ✅ Consistent versions across all child modules
  • ✅ Spring Security 5.8.15 compatible with Spring 5.3.39

Known Vulnerabilities in Spring 5.3.39 (No Patch Available)

Spring Framework 5.3.39 has the following vulnerabilities that cannot be fixed without migrating to Spring 6.x:

CVE Description Affected Patched Version
CVE-2024-38816 Path Traversal vulnerability in spring-webmvc 5.3.0-5.3.39 None in 5.x (6.1.14+)
CVE-2024-38819 Path Traversal vulnerability in spring-webmvc 5.3.0-5.3.39 None in 5.x (6.1.14+)
CVE-2025-22228 Annotation detection improper authorization 5.3.0-5.3.44 None in 5.x (6.2.11+)

Why these cannot be fixed in 5.x:

  • Spring 5.x reached end-of-life December 2024
  • VMware/Broadcom will not release security patches for Spring 5.x
  • Patches are only available in Spring 6.1.14+ and 6.2.11+
  • Spring 6.x requires Jakarta EE 9+ migration (javax.* → jakarta.*)

Risk Mitigation: These vulnerabilities primarily affect:

  1. Path Traversal: Applications using functional web endpoints (RouterFunction) or that serve static resources. TreeBASE uses traditional annotation-based controllers which have lower exposure.
  2. Annotation Detection: Affects Spring Security annotation processing. TreeBASE uses XML-based security configuration which has lower exposure.

Recommended Action: Plan migration to Spring 6.x as documented in "Future Upgrade Paths" section below.


Security Dependency Upgrades

Problem

Several dependencies had known security vulnerabilities (CVEs):

  1. commons-fileupload 1.3.3 - DoS vulnerability (CVE-2023-24998)
  2. commons-io 2.7 - Needed update to match commons-fileupload requirements
  3. xalan 2.7.0 - Integer truncation vulnerability (CVE-2022-34169)

Solution

Upgraded vulnerable dependencies to patched versions:

<!-- commons-fileupload 1.6.0 (was 1.3.3) - fixes CVE-2023-24998, CVE-2024-25710 -->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.6.0</version>
</dependency>

<!-- commons-io 2.15.1 (was 2.7) - matches commons-fileupload 1.5 -->
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.15.1</version>
</dependency>

<!-- xalan 2.7.3 (was 2.7.0) - fixes CVE-2022-34169 -->
<dependency>
  <groupId>xalan</groupId>
  <artifactId>xalan</artifactId>
  <version>2.7.3</version>
</dependency>

Also added exclusion in treebase-core for xom dependency which was pulling in xalan 2.6.0:

<dependency>
  <groupId>jaxen</groupId>
  <artifactId>jaxen</artifactId>
  <version>1.1-beta-8</version>
  <exclusions>
    <exclusion>
      <groupId>xom</groupId>
      <artifactId>xom</artifactId>
    </exclusion>
  </exclusions>
</dependency>

Benefits

  • ✅ Addresses dependabot security alerts
  • ✅ DoS vulnerability in file upload fixed
  • ✅ Integer truncation vulnerability in XSLT processing fixed
  • ✅ Consistent xalan version across all modules (2.7.3)

SLF4J and Logging Framework Compatibility

Problem

Spring 5.3.26 includes spring-jcl module which provides commons-logging API compatibility by bridging to SLF4J 1.7.x API. The project initially used SLF4J 2.0.16, which has breaking API changes from 1.7.x.

Error observed:

java.lang.NoSuchMethodError: 'void org.slf4j.spi.LocationAwareLogger.log(...)'
at org.apache.commons.logging.impl.SLF4JLocationAwareLog.error(...)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(...)

Solution

Downgraded SLF4J from 2.0.16 to 1.7.36 for Spring 5.x compatibility.

Changes in pom.xml:

<!-- BEFORE -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.16</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j2-impl</artifactId>
    <version>2.24.3</version>
</dependency>

<!-- AFTER -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.36</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.24.3</version>
</dependency>

Benefits

  • ✅ Compatible with Spring 5.x's logging bridge
  • ✅ No method signature mismatches
  • ✅ Clean application startup

Future Considerations

  • SLF4J 1.7.x is in maintenance mode
  • Consider upgrading to Spring 6.x (requires Jakarta EE migration) to use SLF4J 2.x
  • See roadmap in deployment fix analysis below

Jersey 2.x Upgrade

Problem

Jersey 1.x versions bundle their own repackaged ASM 3.x as jersey.repackaged.org.objectweb.asm.*, which:

  1. Cannot be overridden by external ASM dependencies
  2. Cannot read Java 17 bytecode (ASM 3.x predates Java 17 by 12 years)
  3. Causes fatal IllegalArgumentException during JAX-RS resource scanning

Error observed:

java.lang.IllegalArgumentException
at jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:170)
at com.sun.jersey.spi.scanning.AnnotationScannerListener.onProcess(...)

Solution

Upgraded from Jersey 1.19.4 to Jersey 2.41, which uses external ASM 9.x compatible with Java 17.

Changes in treebase-web/pom.xml:

<!-- BEFORE: Jersey 1.x -->
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-server</artifactId>
    <version>1.19.4</version>
</dependency>

<!-- AFTER: Jersey 2.x -->
<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-server</artifactId>
    <version>2.41</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.41</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>2.41</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>2.41</version>
</dependency>

Changes in web.xml:

<!-- BEFORE -->
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    ...
</init-param>

<!-- AFTER -->
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
    ...
</init-param>

Code changes:

Updated import statements in Java files:

// BEFORE
import com.sun.jersey.multipart.*;

// AFTER
import org.glassfish.jersey.media.multipart.*;

API Compatibility

What stayed the same:

  • JAX-RS annotations (@Path, @GET, @POST, @Produces, etc.)
  • REST endpoint logic
  • HTTP semantics
  • Request/response handling

What changed:

  • Package names: com.sun.jersey.*org.glassfish.jersey.*
  • Configuration property names
  • Servlet class name
  • Dependency injection framework (now uses HK2)

Benefits

Aspect Jersey 1.x Jersey 2.x
ASM Repackaged 3.x (2009) External 9.x (2021+)
Java 17 ❌ Fails ✅ Works
Maintenance EOL 2018 Active
Can Override ASM ❌ No ✅ Yes

Migration Effort

  • Files changed: 3 (pom.xml, web.xml, DryadImporter.java)
  • Lines changed: ~50 total
  • Breaking changes: Minimal (package names only)
  • Risk level: Low (JAX-RS API unchanged)

JUnit 4 Migration

Problem

Tests were using JUnit 3 style with deprecated Spring test base classes like AbstractTransactionalDataSourceSpringContextTests, which don't support modern Spring versions.

Solution

Migrated to JUnit 4 with Spring 3.2.18.RELEASE test support using annotations.

Changes in pom.xml:

<!-- Spring Framework - Modular Dependencies -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>3.2.18.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>3.2.18.RELEASE</version>
</dependency>
<!-- Additional spring-* modules -->

<!-- JUnit 4 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
</dependency>

<!-- Maven Surefire for test execution -->
<dependency>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
</dependency>

Test base class modernization:

// BEFORE: JUnit 3 style
public abstract class AbstractDAOTest 
    extends AbstractTransactionalDataSourceSpringContextTests {
    // ...
}

// AFTER: JUnit 4 style
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = CoreServiceLauncher.getSpringConfigurations())
@TransactionConfiguration(defaultRollback = true)
@Transactional
public abstract class AbstractDAOTest {
    
    @Autowired
    protected JdbcTemplate jdbcTemplate;
    
    @Autowired
    protected PlatformTransactionManager transactionManager;
    
    @Autowired
    protected ApplicationContext applicationContext;
}

Test method updates:

// BEFORE: JUnit 3 style
public void testSomething() {
    // test code
}

// AFTER: JUnit 4 style
@Test
public void testSomething() {
    // test code
}

Benefits

  • ✅ Modern Spring test annotations
  • ✅ Automatic transaction rollback by default
  • ✅ Dependency injection via @Autowired
  • ✅ No deprecated APIs
  • ✅ Better IDE support

Compatibility

  • Java: 1.7+
  • Spring: 3.2.18.RELEASE (modular dependencies)
  • JUnit: 4.13.2
  • Hibernate: 3.x compatible

Deployment Pipeline Analysis

Historical Context

The deployment pipeline previously had complex workarounds involving:

  1. Starting Tomcat
  2. Stopping Tomcat
  3. Manually removing conflicting JARs with shell scripts
  4. Restarting Tomcat

This approach masked underlying dependency management issues rather than fixing them.

Root Causes Fixed

All three issues above stemmed from dependency version incompatibilities:

  1. SLF4J 2.0.16 incompatible with Spring 5.x → Fixed by downgrading to 1.7.36
  2. Jersey 1.x's internal ASM 3.x can't read Java 17 bytecode → Fixed by upgrading to Jersey 2.41
  3. Conflicting transitive dependencies → Fixed by proper Maven exclusions

Current State

Deployment workflow is now clean and simple:

- Build WARs with Maven
- Deploy to Tomcat
- Start Tomcat
- Verify application health

All dependency management is handled in Maven POMs, not at deployment time.

Future Upgrade Paths

Short-term (Stable - Current State):

  • Spring 5.3.39 (latest 5.x LTS)
  • Spring Security 5.8.15
  • Jersey 2.x
  • SLF4J 1.7.36
  • Low risk, proven compatibility
  • ⚠️ Spring 5.x has unpatched vulnerabilities (see above)

Medium-term (REQUIRED for full security):

  • Spring 6.2.11+ - Required to fix CVE-2024-38816, CVE-2024-38819, CVE-2025-22228
  • Jakarta EE 9+ namespace migration (javax.* → jakarta.*)
  • Tomcat 10+ (supports Jakarta EE 9)
  • Servlet API 5.0+
  • Jersey 3.x (Jakarta EE)
  • SLF4J 2.x

Migration Requirements for Spring 6.x:

  1. Namespace changes - All javax.* imports → jakarta.*

    • javax.servlet → jakarta.servlet
    • javax.persistence → jakarta.persistence
    • javax.validation → jakarta.validation
  2. JSP changes - Update JSTL and taglib URIs

  3. Configuration updates - Spring XML configuration adjustments

  4. Tomcat upgrade - Tomcat 9 → Tomcat 10

  5. Dependencies - Many libraries need Jakarta EE compatible versions

Estimated Efforts

  • Spring 5.3.39 upgrade: Complete ✅
  • Security dependency upgrades: Complete ✅ (commons-fileupload, xalan)
  • Version centralization: Complete ✅
  • ⚠️ Spring 6.2.11+ migration: 60-80 hours (namespace changes, Tomcat upgrade, testing)
  • Jersey 3.x upgrade: 8-16 hours (with Spring 6.x)
  • Full modernization: 100-140 hours (combined effort)

Security Status Summary

Vulnerability Status Fix Available
CVE-2023-24998 (commons-fileupload) ✅ FIXED commons-fileupload 1.6.0
CVE-2024-25710 (commons-fileupload) ✅ FIXED commons-fileupload 1.6.0
CVE-2022-34169 (xalan) ✅ FIXED xalan 2.7.3
CVE-2024-38816 (spring-webmvc) ⚠️ UNFIXED Requires Spring 6.1.14+
CVE-2024-38819 (spring-webmvc) ⚠️ UNFIXED Requires Spring 6.1.14+
CVE-2025-22228 (spring-core) ⚠️ UNFIXED Requires Spring 6.2.11+

References