* WW-5537 Add InternalDestroyable and ContextAwareDestroyable interfaces
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 ContainerHolder: ThreadLocal with AtomicLong generation counter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 FinalizableReferenceQueue: volatile instance, join, classloader null
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 ScopeInterceptor.clearLocks: add synchronized block
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 CompoundRootAccessor, DefaultFileManager: implement InternalDestroyable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Add InternalDestroyable adapter classes for static cache cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Register InternalDestroyable beans in struts-beans.xml
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 JSON plugin: add JSONCacheDestroyable for BeanInfo cache cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Dispatcher.cleanup: refactor into focused methods with InternalDestroyable discovery
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Rewrite DispatcherCleanupTest for InternalDestroyable discovery
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Add log4j-web for proper Log4j2 lifecycle in Servlet container
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Dispatcher.destroyObjectFactory: add early return on null, use pattern matching
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Fix @since annotations: 7.1.0 -> 7.2.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Add Container.destroy() to clear internal caches on undeploy
Container now exposes a destroy() method that clears factories, injectors,
constructors, and ThreadLocals. This releases Class<?> keys and JDK
DelegatingClassLoader instances that pin the webapp classloader.
DefaultConfiguration.destroy() calls container.destroy() and
reloadContainer() delegates to destroy() to avoid duplication.
Also fixes JSONCacheDestroyable referencing non-existent DefaultJSONWriter
(renamed to StrutsJSONWriter).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Fix Container.destroy(): don't clear factories, don't call from reloadContainer
factories must remain intact because existing code holds direct
references to the Container after destroyConfiguration() and expects
it to still resolve dependencies (e.g. during configuration reload).
reloadContainer() reverted to clearing packageContexts/loadedFileNames
directly — calling destroy() there nulled the container reference and
cleared state needed during the bootstrap transition.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Restore destroy() call in reloadContainer()
The test failures were caused by factories.clear() in
Container.destroy(), not by calling destroy() from reloadContainer().
Now that factories.clear() is removed, destroy() is safe to call
here — it clears packageContexts, loadedFileNames, and the container's
reflection caches in one place.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* WW-5537 Fix Sonar issues: thread-safe FinalizableReferenceQueue, empty method comments
- Replace volatile field with AtomicReference in FinalizableReferenceQueue
for proper thread safety using getAndSet()
- Add comments to empty destroy() implementations in test mocks
- Replace deprecated new URL() with URI.toURL() in DispatcherCleanupTest
- Add comments to empty listener methods in DispatcherCleanupTest
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 payloads (deeply nested objects, huge arrays, long
strings).
Changes:
- Extract JSONReader interface from class, create StrutsJSONReader impl
with maxElements, maxDepth, maxStringLength, maxKeyLength enforcement
- Rename DefaultJSONWriter to StrutsJSONWriter (Struts* naming convention)
- Add JSONBeanSelectionProvider for bean aliasing via constants
- Update JSONUtil with @Inject for reader/writer, add instance
deserializeInput() with maxLength check, deprecate static deserialize()
- Wire limits into JSONInterceptor with @Inject from constants
- Register beans and defaults in struts-plugin.xml
Default limits: 10K elements, 64 depth, 2MB length, 256KB strings, 512 keys.
All configurable via struts.xml constants or per-action interceptor params.
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
- Fix Instant custom-format serialization requiring UTC zone
- Add Calendar serialization/deserialization via temporal bridge
- Add comprehensive tests for all temporal types including custom
formats, malformed input, and null handling
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(proxy): WW-5514 add StrutsProxyService for proxy detection and resolution
Introduces a configurable ProxyService interface and StrutsProxyService
implementation for detecting and resolving Spring AOP/Hibernate proxies.
Key changes:
- Add ProxyService interface with isProxy, ultimateTargetClass, and
resolveTargetMember methods
- Add StrutsProxyService implementation using configurable caches
- Add ProxyCacheFactory and StrutsProxyCacheFactory for cache management
- Integrate ProxyService into ChainingInterceptor, ParametersInterceptor,
and SecurityMemberAccess
- Add integration test with Spring AOP proxied action chaining
- Add configuration constants for proxy cache type and size
The StrutsProxyService correctly handles:
- Spring CGLIB proxies (class-based)
- Spring JDK dynamic proxies (interface-based)
- Hibernate entity proxies
- Member resolution for allowlist checking
Fixes WW-5514
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* test(proxy): WW-5514 add ProxyService integration tests for Spring proxies
Add integration tests to SpringProxyUtilTest that verify the new
ProxyService works correctly with real Spring AOP proxies, alongside
the existing deprecated ProxyUtil tests.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(proxy): WW-5514 address PR review feedback for proxy caches
Remove targetClassCache from StrutsProxyService to avoid memory leak
(object-keyed cache reintroduced from PR #1578). Change default proxy
cache type to wtlfu to align with all other caches. Switch deprecated
ProxyUtil static caches to BASIC to remove hard Caffeine dependency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* [maven-release-plugin] prepare release STRUTS_7_1_1
* [maven-release-plugin] rollback the release of STRUTS_7_1_1
* [maven-release-plugin] prepare release STRUTS_7_1_1
* [maven-release-plugin] prepare for next development iteration