* WW-5537 fix(core): resolve classloader/memory leaks during Tomcat hot deployment
Introduce InternalDestroyable interface with container-based discovery to
clean up static caches, daemon threads, and shared references that pin the
webapp classloader after undeploy. This prevents OutOfMemoryError (Metaspace)
on repeated hot deployments.
Changes:
- Add InternalDestroyable/ContextAwareDestroyable interfaces for cleanup hooks
- Clear OGNL, Component, ScopeInterceptor, DefaultFileManager static caches
- Stop FinalizableReferenceQueue daemon thread and null its classloader
- Clear FreeMarker template/introspection caches from ServletContext
- Replace ContainerHolder ThreadLocal with volatile to prevent thread-pool leaks
- Clear static dispatcherListeners list on Dispatcher cleanup
- Add JSONCacheDestroyable for json plugin cache cleanup
- Register all destroyables via struts-beans.xml / struts-plugin.xml
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 chore(showcase): add log4j-web for proper Log4j2 lifecycle in Servlet container
Without log4j-web, Log4j2 SoftReferences delay classloader GC after undeploy.
The log4j-web module provides Log4jServletContextListener which ensures proper
Log4j2 shutdown during ServletContext destruction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 fix(core): use ThreadLocal with generation counter in ContainerHolder
Replace the volatile shared reference with a ThreadLocal backed by a volatile
generation counter. Per-request clear() only affects the current thread (safe
for concurrent requests and tests). On undeploy, invalidateAll() advances the
generation counter so idle pool threads detect staleness on next access and
self-clear, preventing classloader leaks without breaking test isolation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add configurable limits to the JSON plugin to prevent denial-of-service
attacks via malicious JSON payloads. Limits are enforced directly in the
existing JSONReader class without breaking backward compatibility (no
interface extraction or class renames).
New configurable constants (struts-plugin.xml defaults):
- struts.json.maxElements (10000) - per-container element count
- struts.json.maxDepth (64) - maximum nesting depth
- struts.json.maxLength (2097152) - maximum input length in chars
- struts.json.maxStringLength (262144) - maximum string value length
- struts.json.maxKeyLength (512) - maximum object key length
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Add serialization support for LocalDate, LocalDateTime, LocalTime,
ZonedDateTime, OffsetDateTime, and Instant in DefaultJSONWriter
- Add deserialization support for the same types in JSONPopulator
- Support @JSON(format=...) custom formats for all temporal types
- Add Calendar deserialization support (was serialize-only)
- Add comprehensive tests including custom formats, null handling,
malformed input, and round-trip serialization/deserialization
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Upgrades test dependencies
* Drops unused lib
* Uses AssertJ instead of FestAssert
* Upgrades Surefire Maven Plugin to 2.22.1
* Downgrades to AssertJ 2.x to support JDK7
* decouple tests from java version
Refactor a java 9 conditional test to work always with any java version
See also WW-4845
* fix NullPointerException in NotURLClassLoader tests
Also includes a few improvements
See also WW-4845
* do not specify threadCount & forkMode which breaks tests in java 9
See also WW-4845
* pass all current tests with java 11
See also WW-4981
* fix an odd path problem in java 9
See also WW-4845
* gitignore test-output
See also WW-4981
* ask travis an oracle jdk 11 build
See also WW-4981
* ask travis to report coverage only in latest working jdk, jdk8
See also WW-4845