This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
For detailed procedures, use the specialized skills in .claude/skills/.
Apache Struts is a mature MVC web application framework for Java (originally WebWork 2). Uses OGNL for value stack expressions and FreeMarker for UI tag templates.
Version: the -SNAPSHOT in the root pom.xml is a placeholder — the release version is chosen at release time from the semver impact of the accumulated changes. Released versions are git tags like STRUTS_7_2_1.
# Run tests (skip assembly for speed) mvn test -DskipAssembly # Single test in specific module mvn test -DskipAssembly -pl core -Dtest=MyClassTest#testMethodName # Jakarta EE 11 / Spring 7 profile mvn clean install -Pjakartaee11
Apache Struts has a history of security vulnerabilities (OGNL injection, temp file exploits). Apply these Struts-specific patterns:
ParameterNameAware to restrict accepted parameter names// Secure temporary file pattern protected File createTemporaryFile(String fileName, Path location) { String uid = UUID.randomUUID().toString().replace("-", "_"); return location.resolve("upload_" + uid + ".tmp").toFile(); }
For any security-related activity — vulnerability scans, security analysis, drafting security reports — SECURITY.md is the source of truth. Read it first and follow its pre-reporting checks, assessment checklist, and reporting requirements. Reports must be sent privately to security@struts.apache.org; do not open a public GitHub issue, Jira issue, pull request, or mailing list thread for a suspected vulnerability before private triage. AGENTS.md is a shorter LLM-facing wrapper around the same process. THREAT_MODEL.md is where the scope lives — trust boundaries, the security properties the framework does and does not provide, the recurring non-findings (§11a), and the triage dispositions (§13). Read it before judging whether a finding is real: on Struts most candidate findings are closed as application responsibility or non-default configuration rather than as framework bugs.
Tests are JUnit 4 — there is no JUnit 5 anywhere in this repo. parent/pom.xml declares junit:junit:4.13.2; there are zero org.junit.jupiter imports. Two styles coexist:
XWorkTestCase (which extends junit.framework.TestCase). Methods must be named testXxx(). A Jupiter @Test annotation added to one of these silently never runs — it does not fail, it is simply not collected.import org.junit.Test.Both styles are widespread and neither is being migrated away from; grep -rl for either marker gives the current split.
Before adding a test, open the target file and match the style already there. AssertJ assertions and Mockito mocks are both available and widely used. Introducing Jupiter is a build-infrastructure change that needs its own WW- ticket, never a side effect of a feature.
WW-XXXX Description — a Jira ticket ID is required for any code change. Pure documentation and build/CI changes (SECURITY.md, AGENTS.md, CLAUDE.md, .claude/, workflows) take no ticket and use conventional-commit form instead: docs: ..., build(ci): ..., chore: ...Fixes [WW-XXXX](https://issues.apache.org/jira/browse/WW-XXXX)security@struts.apache.org — see SECURITY.md.