This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch feature/support-2025.3
in repository https://gitbox.apache.org/repos/asf/struts-intellij-plugin.git

commit 6bbd22d877025f7567aae45df9b5a5e45be96f70
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sat Jan 10 14:12:11 2026 +0100

    fix(facet): populate file sets when framework is detected
    
    - Add setupFacet() override to StrutsFrameworkDetector to automatically
      add detected struts.xml files to file sets when user clicks "Configure"
    - Fix key mismatch in StrutsFrameworkInitializer (was storing with
      project.getName() but retrieving with project.getLocationHash())
    - Fix NPE in StrutsFrameworkInitializer fallback logic that called
      performInitialization with null facet
    - Refactor framework initialization to use modern ProjectActivity pattern
    - Update various files for IntelliJ Platform 2025.3 compatibility
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-Authored-By: Claude <[email protected]>
---
 CLAUDE.md                                          | 413 +++++--------------
 docs/framework-initialization.md                   | 446 +++++++++++++++++++++
 .../com/intellij/lang/ognl/OgnlTypedHandler.java   |   4 +-
 .../ognl/psi/impl/OgnlReferenceExpressionBase.java |   4 +-
 .../intellij/struts2/facet/StrutsFacetType.java    |  63 +--
 .../struts2/facet/StrutsFrameworkDetector.java     |  46 +++
 .../struts2/facet/StrutsFrameworkInitializer.java  | 266 ++++++++++++
 .../facet/StrutsFrameworkSupportProvider.java      | 135 +------
 .../struts2/facet/ui/FileSetConfigurationTab.java  |   7 +-
 .../contributor/StrutsCoreConstantContributor.java |   4 +-
 src/main/resources/META-INF/plugin.xml             |   3 +
 11 files changed, 911 insertions(+), 480 deletions(-)

diff --git a/CLAUDE.md b/CLAUDE.md
index 7734a7f..5b0707d 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -5,351 +5,140 @@ This file provides guidance to Claude Code (claude.ai/code) 
when working with co
 ## Development Commands
 
 ### Build and Test
-- `./gradlew build` - Build the plugin
-- `./gradlew check` - Run tests and code analysis
-- `./gradlew test` - Run unit tests only
-- `./gradlew test --tests "*parsing*"` - Run OGNL parsing tests (40 tests, ✅ 
passing)
-- `./gradlew test -x rat` - Run tests excluding Apache RAT license checks
-- `./gradlew runIdeForUiTests` - Launch IDE for UI testing with robot server 
on port 8082
-- `./gradlew koverHtmlReport` - Generate code coverage reports
-
-### Post-Migration Status (IntelliJ Platform 2024.2)
-- All OGNL parsing tests fixed (40/40 ✅)
-- All DOM stub tests fixed (1/1 ✅) - path resolution issues resolved  
-- All integration tests fixed (FreemarkerIntegrationTest 3/3 ✅)
-- Property-based tests (OgnlCodeInsightSanityTest) working (3/3 ✅)
-- ~~All OGNL lexer tests fixed (4/4 ✅)~~ - path resolution issues resolved
-- **Overall test suite: 14 failures remaining** (95% success rate: 300/314 
tests passing)
-- **Known failure categories**:
-  - 2 StrutsResultResolvingTest (highlighting position precision): 
`testActionPathFQ`, `testPathDispatcher` - requires precise character 
positioning fixes
-  - 10 JSP Reference Provider failures (API migration needed): 
`ActionLinkReferenceProviderTest` (4), `ActionPropertyReferenceProviderTest` 
(2), `ActionReferenceProviderTest` (1), `NamespaceReferenceProviderTest` (1), 
`UITagsAttributesReferenceProviderTest` (2)
-  - 2 additional highlighting test failures: `ResultActionPropertyTest` (1), 
`WebXmlConstantTest` (1)
-  - ~~4 OgnlLexerTest failures~~ ✅ FIXED
-  - ~~1 Struts2OgnlJspTest failure: `testStruts2TaglibOgnlInjection`~~ ✅ FIXED
-- Core functionality working; remaining issues require IntelliJ 2024.2 API 
migration research
+```bash
+./gradlew build                              # Build the plugin
+./gradlew test -x rat                        # Run unit tests (excluding 
Apache RAT license checks)
+./gradlew test --tests "OgnlParsingTest"     # Run specific test class
+./gradlew test --tests "*Resolving*"         # Run tests matching pattern
+./gradlew check                              # Run tests and code analysis
+./gradlew koverHtmlReport                    # Generate code coverage report 
(build/reports/kover/)
+```
 
 ### Development and Debugging
-- `./gradlew runIde` - Run IntelliJ IDEA with the plugin for 
development/debugging
-- `./gradlew buildPlugin` - Build plugin distribution
-- `./gradlew runPluginVerifier` - Verify plugin compatibility against 
specified IntelliJ IDEs
+```bash
+./gradlew runIde                             # Run IntelliJ IDEA with the 
plugin loaded
+./gradlew runIdeForUiTests                   # Launch IDE with robot server on 
port 8082
+./gradlew buildPlugin                        # Build plugin distribution 
(build/distributions/)
+./gradlew runPluginVerifier                  # Verify compatibility against 
specified IDEs
+```
 
 ### Code Quality
-- `./gradlew runInspections` - Run Qodana code quality inspections (requires 
Docker)
-- `./gradlew rat` - Run Apache RAT license check
+```bash
+./gradlew runInspections                     # Run Qodana inspections 
(requires Docker)
+./gradlew rat                                # Run Apache RAT license check
+```
 
 ## Project Architecture
 
-### Core Structure
-This is an IntelliJ IDEA plugin for Apache Struts 2 framework development 
support, written in Java and Kotlin.
+This is an IntelliJ IDEA Ultimate plugin for Apache Struts 2 framework, 
providing IDE support for struts.xml configuration, OGNL expressions, 
validation files, and JSP tag libraries.
 
-**Main Package Structure:**
-- `com.intellij.struts2` - Core plugin functionality
-- `com.intellij.lang.ognl` - OGNL language support (Object-Graph Navigation 
Language)
+### Package Structure
+- `com.intellij.struts2` - Core Struts 2 plugin functionality
+- `com.intellij.lang.ognl` - OGNL language support (lexer, parser, 
highlighting, completion)
 
-### Key Components
+### Key Architectural Components
 
-**DOM Model (`com.intellij.struts2.dom`)**
-- `struts/` - Struts XML configuration DOM models
-- `validator/` - Validation XML DOM models  
-- `params/` - Parameter handling and conversion
-- `inspection/` - Model validation and inspections
+**DOM Model Layer** (`com.intellij.struts2.dom`)
+- `struts/` - Struts XML configuration DOM (actions, results, interceptors, 
packages)
+- `validator/` - Validation XML DOM models
+- `params/` - Parameter handling and type conversion
+- DOM converters in `impl/` packages handle reference resolution
 
-**Framework Integration (`com.intellij.struts2.facet`)**
-- `StrutsFacet` - Framework detection and configuration
+**Framework Integration** (`com.intellij.struts2.facet`)
+- `StrutsFacet` / `StrutsFacetType` - Framework facet configuration
 - `StrutsFrameworkDetector` - Auto-detection of Struts projects
-- UI components for facet configuration
+- `StrutsFrameworkInitializer` - Modern `ProjectActivity`-based initialization 
(replaces deprecated `StartupManager`)
+- `FileSetConfigurationTab` - UI for configuring struts.xml file sets
 
-**Language Features**
-- **OGNL Support** - Complete language implementation with lexer, parser, 
highlighting
-- **JSP Integration** - Tag library support, OGNL injection in JSP
-- **FreeMarker/Velocity** - Template engine integrations
-- **Groovy Support** - Action annotation processing
+**Reference Resolution** (`com.intellij.struts2.reference`)
+- `StrutsReferenceContributor` - XML reference providers for struts.xml
+- `jsp/` - JSP tag library references and action link resolution
+- Reference contributors for various Struts tag libraries (jQuery, Bootstrap, 
etc.)
 
-**IDE Features**
-- **Navigation** - Go to symbols, related actions
-- **Code Completion** - Action names, results, interceptors
-- **Inspections** - Configuration validation, hardcoded URL detection
-- **Structure View** - Struts configuration and validation file structure
-- **Graph View** - Visual representation of action flows
+**OGNL Language** (`com.intellij.lang.ognl`)
+- `OgnlLanguage` / `OgnlFileType` - Language definition
+- `lexer/` - JFlex-based lexer (`ognl.flex`)
+- `parser/` - Grammar Kit parser (`OgnlParser.bnf`)
+- `psi/` - PSI element types and implementations in `impl/`
+- `highlight/` - Syntax and semantic highlighting
+- `completion/` - Code completion providers
 
-### Template Engine Support
-The plugin supports multiple view technologies:
-- JSP with Struts tag libraries
-- FreeMarker templates with Struts integration
-- Velocity templates
-- JavaScript and CSS injection in templates
+**Extension Points** (defined in `plugin.xml`)
+- `struts2.constantContributor` - Add custom Struts constants
+- `struts2.resultContributor` - Custom result type path resolution
+- `struts2.classContributor` - Extend class resolution (actions, interceptors)
+- `struts2.paramNameCustomConverter` - Custom parameter name resolution
 
-### Testing Framework
-- Uses IntelliJ Platform test framework
-- Functional tests in `src/test/java`
-- Test data in `src/test/testData`
-- UI tests supported via IntelliJ UI Test Robot
+### Template Engine Integrations
+Optional modules loaded via `<depends optional="true">`:
+- `struts2-freemarker.xml` - FreeMarker template support
+- `struts2-velocity.xml` - Velocity template support
+- `struts2-spring.xml` - Spring integration
+- `struts2-groovy.xml` - Groovy annotations support
 
-### Build Configuration
-- Gradle-based build with Kotlin DSL
-- IntelliJ Platform Gradle Plugin 2.7.0
-- Supports IntelliJ IDEA Ultimate 2024.2+
-- Java 21 toolchain requirement
-- Code coverage via Kover plugin
+### Test Organization
+- `src/test/java` - Test classes following IntelliJ Platform test patterns
+- `src/test/testData` - Test fixture files (XML, JSP, Java sources)
+- Test base classes extend IntelliJ Platform's 
`LightJavaCodeInsightFixtureTestCase` or similar
 
-## IntelliJ Platform Upgrade Guide
+## IntelliJ Platform Version Mapping
 
-This section documents the process for upgrading the plugin to support newer 
versions of IntelliJ Platform.
+| Branch | Platform Version | Build Range |
+|--------|------------------|-------------|
+| 242.x  | 2024.2           | 242.*       |
+| 243.x  | 2024.3           | 243.*       |
+| 251.x  | 2025.1           | 251.*       |
+| 252.x  | 2025.2           | 252.*       |
 
-### Upgrading to IntelliJ Platform 2024.2
+### Plugin Version Format
+`{BRANCH}.{BUILD}.{FIX}` (e.g., `252.18970.1`)
 
-**Prerequisites:**
-- IntelliJ Platform Gradle Plugin 2.0+ (migration already completed)
-- Java 21 required (2024.2+ requirement)
-- Gradle 8.5+ running on Java 17+
+- **BRANCH** - IntelliJ Platform branch (252 = 2025.2)
+- **BUILD** - Automatically calculated in GitHub Actions as `18969 + git 
rev-list --count HEAD`
+- **FIX** - Patch version (typically `1` for new builds)
 
-**Files to Update:**
+The base value `18969` maintains historical continuity from when the plugin 
was donated by JetBrains to Apache Software Foundation, ensuring version 
numbers continue from the previous build sequence.
 
-Version Format: {BRANCH}.{BUILD}.{FIX}
+## Platform Upgrade Checklist
 
-- 241 = IntelliJ Platform branch (2024.1)
-- 18968 = Build number within that branch (auto-incremented in CI)
-- 1 = Fix/patch version
+When upgrading to a new IntelliJ Platform version:
 
-Meaning:
-- This plugin version targets IntelliJ IDEA 2024.1 platform
-- Build number is automatically calculated as git commit count 
(auto-incremented in GitHub Actions)
-- Version 1 indicates first release for this build
+1. **Update `gradle.properties`**:
+   - `platformVersion` - Target platform (e.g., `2025.2`)
+   - `pluginSinceBuild` / `pluginUntilBuild` - Build range (e.g., `251` to 
`252.*`)
+   - `pluginVersion` - Match branch prefix (e.g., `252.x.y`)
 
-**Automatic BUILD Increment:**
-The BUILD number is automatically incremented in GitHub Actions using `18969 + 
git rev-list --count HEAD`. The base value 18969 maintains historical 
continuity from when the plugin was donated by JetBrains to Apache Software 
Foundation, ensuring version numbers continue from the previous build sequence 
rather than restarting from a low commit count.
+2. **Check API Compatibility**:
+   - Review https://jb.gg/intellij-api-changes for breaking changes
+   - Run `./gradlew runPluginVerifier` to detect issues
+   - Common changes: deprecated UI icons, removed internal APIs, changed test 
framework paths
 
-Context:
-The "untagged" prefix suggests this was an automated release draft created by 
your build workflow, but the tag URL appears to be truncated or no longer 
accessible (404 error).
+3. **Update CI/Tooling** (if Java version changes):
+   - `.github/workflows/build.yml` - Java version in setup
+   - `qodana.yml` - Linter version and `projectJDK`
+   - `build.gradle.kts` - `jvmToolchain()` version
 
-IntelliJ Version Mapping:
-- 241.x = IntelliJ IDEA 2024.1
-- 242.x = IntelliJ IDEA 2024.2
-- 243.x = IntelliJ IDEA 2024.3
-- 251.x = IntelliJ IDEA 2025.1
-- 252.x = IntelliJ IDEA 2025.2
+4. **Fix Test Path Issues**:
+   - IntelliJ Platform test frameworks sometimes change path resolution
+   - Override `getBasePath()` and `getTestDataPath()` if tests fail to find 
fixtures
+   - Use project-relative paths like `"src/test/testData/..."`
 
-This versioning ensures plugin compatibility with specific IntelliJ Platform 
versions and helps users identify which IDE version the plugin supports.
+5. **Update CHANGELOG.md** with dependency upgrades
 
-#### 1. `gradle.properties`
-```properties
-# Platform version
-platformVersion = 2024.2
+## Known Platform Quirks
 
-# Build number ranges (2024.2 = 242)
-pluginSinceBuild = 242
-pluginUntilBuild = 242.*
-
-# Plugin version should match platform
-pluginVersion = 242.18968.1  # Use 242.x.y format
-
-# where x represents the previous build number plus 1, y supposed be set to 1
-```
+**Test Data Path Resolution**: IntelliJ 2024.2+ changed how `LexerTestCase` 
and `DomStubTest` resolve paths. If tests fail with "Cannot find source file", 
override path methods to use project-relative paths.
 
-#### 2. `build.gradle.kts`
-```kotlin
-// Update Java toolchain
-kotlin {
-    jvmToolchain(21)  # Java 21 required for 2024.2+
-}
+**Internal API Usage**: Some platform icons and utilities are internal. The 
plugin verifier will warn about these. Prefer public APIs:
+- Use `AllIcons.Nodes.*` instead of `PlatformIcons`
+- Use `Charset.availableCharsets()` instead of 
`CharsetToolkit.getAvailableCharsets()`
 
-// Update Qodana plugin version to match platform
-id("org.jetbrains.qodana") version "2024.2.6"
-```
-
-#### 3. `.github/workflows/build.yml`
-```yaml
-# Update Java version in all jobs
-- name: Setup Java
-  uses: actions/setup-java@v4
-  with:
-    distribution: zulu
-    java-version: 21  # Changed from 17
-
-# Update Qodana action version
-- name: Qodana - Code Inspection
-  uses: JetBrains/[email protected]
-
-# Add disk space management for resource-intensive jobs (inspectCode, verify)
-- name: Maximize Build Space
-  uses: jlumbroso/[email protected]
-  with:
-    tool-cache: false
-    large-packages: false
-```
-
-#### 4. `.github/workflows/release.yml`
-```yaml
-# Update Java version
-- name: Setup Java
-  uses: actions/setup-java@v4
-  with:
-    distribution: zulu
-    java-version: 21  # Changed from 17
-```
-
-#### 5. `qodana.yml` (update existing file)
-```yaml
-version: "1.0"
-linter: jetbrains/qodana-jvm-community:2024.2  # Match platform version
-projectJDK: 21  # Match Java requirement
-exclude:
-  - name: All
-    paths:
-      - .qodana
-      - build
-      - gradle
-      - gradlew
-      - gradlew.bat
-      - src/test/testData
-include:
-  - name: Root
-    paths:
-      - src/main/java
-      - src/main/resources
-```
-
-#### 6. API Compatibility Fixes
-Check and fix any deprecated/removed APIs by reviewing the [API Changes 
List](https://plugins.jetbrains.com/docs/intellij/api-changes-list-2024.html):
-
-**Example from 2024.2 upgrade:**
-```java
-// Before (removed in 2024.2)
-return WebUtilImpl.isWebFacetConfigurationContainingFiles(underlying, files);
-
-// After (compatible alternative)
-return underlying instanceof WebFacetConfiguration;
-```
-
-#### 7. `CHANGELOG.md`
-Document the upgrade:
-```markdown
-### Changed
-- Update `platformVersion` to `2024.2`
-- Change since/until build to `242-242.*` (2024.2)
-- Upgrade Java toolchain from 17 to 21 (required by IntelliJ 2024.2)
-- Update GitHub Actions workflows to use Java 21
-- Fix API compatibility issues for IntelliJ 2024.2
-- Dependencies - upgrade plugin versions to match 2024.2
-```
-
-### General Upgrade Process
-
-**Step 1: Check Requirements**
-1. Review [JetBrains migration 
documentation](https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-migration.html)
-2. Check Java version requirements for target platform
-3. Verify IntelliJ Platform Gradle Plugin version compatibility
-
-**Step 2: Update Configuration Files**
-1. Update `gradle.properties` with new platform version and build numbers
-2. Update `build.gradle.kts` with correct Java toolchain and plugin versions
-3. Update GitHub Actions workflows with matching Java versions
-4. Update `qodana.yml` with corresponding linter version
-
-**Step 3: Fix API Compatibility**
-1. Review [API Changes 
List](https://plugins.jetbrains.com/docs/intellij/api-changes-list-2024.html) 
for breaking changes
-2. Update deprecated/removed API calls
-3. Test compilation and runtime compatibility
-
-**Step 4: Verification**
-1. **Build Test**: `./gradlew build` - Ensure compilation succeeds
-2. **Unit Tests**: `./gradlew test -x rat` - Verify no API compatibility 
issues  
-3. **Plugin Verifier**: `./gradlew runPluginVerifier` - Check compatibility 
against target IDEs
-4. **Qodana Check**: Verify code quality analysis runs without version warnings
-
-**Step 5: Documentation**
-1. **ALWAYS** update `CHANGELOG.md` immediately when upgrading dependencies - 
add entries under the `[Unreleased]` section in the format: `- Dependencies - 
upgrade <plugin-name> to <version>`
-2. Update this guide with any new findings or issues
-3. Document any plugin-specific compatibility fixes
-
-### Common Issues & Solutions
-
-**Java Version Mismatch**
-- Error: `sourceCompatibility='17' but IntelliJ Platform requires 
sourceCompatibility='21'`
-- Solution: Update `jvmToolchain()` in `build.gradle.kts` and all GitHub 
Actions workflows
-
-**Qodana Version Warnings**
-- Error: `You are running a Qodana linter without an exact version tag`
-- Solution: Update `qodana.yml` with specific linter version matching platform
-
-**API Compatibility Issues**
-- Error: `cannot find symbol` for removed methods
-- Solution: Check API changes documentation and replace with compatible 
alternatives
-
-**DOM Test Path Resolution Issues**
-- Error: `Cannot find source file: 
.../ideaIU-2024.2/.../testData/stubs/file.xml`
-- Root Cause: IntelliJ Platform 2024.2 test framework changed path resolution 
behavior
-- Solution: Update test classes extending `DomStubTest` to override both 
`getBasePath()` and `getTestDataPath()`:
-  ```java
-  @Override
-  protected String getBasePath() {
-    return "src/test/testData/stubs";  // Use project-relative path
-  }
-  
-  @Override
-  protected String getTestDataPath() {
-    return "src/test/testData/stubs";  // Ensure consistent resolution
-  }
-  ```
-
-**Kotlin K2 Mode**
-- Java-based plugins automatically support K2 mode (no migration needed)
-- If using Kotlin APIs, may need migration to Analysis API
-
-**JSP Reference Provider Failures (IntelliJ 2024.2)**
-- **Issue**: Tests fail with "no reference found" errors for JSP action links
-- **Root Cause**: `javaee.web.customServletReferenceProvider` extension point 
API changed in IntelliJ 2024.2
-- **Affected Classes**: `ActionLinkReferenceProvider` extending 
`CustomServletReferenceAdapter`
-- **Working**: Local inspections still work (e.g., 
`HardcodedActionUrlInspectionTest` passes)
-- **Diagnosis**: Web/JSP facet setup works; issue is specifically with 
reference provider registration
-- **Plugin Registration**: Extension point 
`<javaee.web.customServletReferenceProvider 
implementation="com.intellij.struts2.reference.jsp.ActionLinkReferenceProvider"/>`
 may need alternative approach
-- **Status**: 94% tests pass, but JSP reference resolution needs API migration 
research
-- **Future Work**: Research IntelliJ 2024.2 web reference provider APIs; 
consider migrating to standard `psi.referenceProvider` extension points
-
-**Error Message Format Changes (IntelliJ 2024.2)**
-- **Issue**: Highlighting tests fail due to changed error message formats
-- **Examples**: 
-  - "Cannot resolve symbol" → "Cannot resolve file" 
-  - Multiple error types for same element: `descr="Cannot resolve file 
'...'|Cannot resolve symbol '...'"`
-- **Affected**: StrutsResultResolvingTest, various highlighting tests
-- **Solution**: Update test data files with new error message formats using 
pipe separator for multiple errors
-- **Character Position Precision**: IntelliJ 2024.2 requires exact character 
position matching for error annotations
-
-**StrutsResultResolvingTest Improvements (IntelliJ 2024.2)**
-- **Status**: Improved from 62% to 75% success rate (5/8 → 6/8 tests passing)
-- **Fixed**: `testActionPath` - Updated `struts-actionpath.xml` with correct 
error annotation formats
-- **Remaining Issues**: `testPathDispatcher` and `testActionPathFQ` require 
complex character positioning fixes
-- **Updated Files**: 
-  - 
`src/test/java/com/intellij/struts2/dom/struts/StrutsResultResolvingTest.java` 
- Added IntelliJ 2024.2 compatibility documentation
-  - `src/test/testData/strutsXml/result/struts-actionpath.xml` - Fixed 
combined error annotations
-- **Key Learning**: IntelliJ 2024.2 generates separate error annotations 
instead of combined pipe-separated formats
-- **Documentation**: Added comprehensive JavaDoc explaining new error message 
requirements for future maintenance
-
-**OGNL Lexer Test Failures (IntelliJ 2024.2) - FIXED** ✅
-- **Issue**: 4 OgnlLexerTest failures related to test data path resolution
-- **Affected Tests**: `testTwoRightCurly`, `testNestedModuloAndCurly`, 
`testNestedBracesWithoutExpression`, `testNestedBraces`
-- **Root Cause**: IntelliJ Platform 2024.2 changed `LexerTestCase` path 
resolution behavior
-- **Framework Behavior**: Test framework looked in 
`/Users/.../ideaIU-2024.2-aarch64/testData/lexer/` instead of 
`src/test/testData/lexer/`
-- **Fix Applied**: Updated `OgnlLexerTest.getDirPath()` method to return 
`"src/test/testData/lexer"` directly instead of using 
`OgnlTestUtils.OGNL_TEST_DATA + "/lexer"`
-- **Status**: ✅ All 4 tests now pass (verified in test run)
-- **Files Modified**: 
`src/test/java/com/intellij/lang/ognl/lexer/OgnlLexerTest.java:59`
-
-**JSP OGNL Injection Test Failure (IntelliJ 2024.2) - FIXED** ✅
-- **Issue**: `Struts2OgnlJspTest.testStruts2TaglibOgnlInjection` failed with 
unexpected URL highlighting in license header
-- **Root Cause**: IntelliJ Platform 2024.2 enhanced URL detection, now 
highlighting `http://www.apache.org/licenses/LICENSE-2.0` in ASF license header 
with "Open in browser" functionality
-- **Solution**: Updated test to disable info-level highlighting checks by 
changing `myFixture.testHighlighting(true, true, false, ...)` to 
`myFixture.testHighlighting(true, false, false, ...)`
-- **Rationale**: Test should focus on OGNL injection functionality, not 
general IDE URL detection in license headers
-- **Status**: ✅ Fixed and verified passing
-- **Files Modified**: 
`src/test/java/com/intellij/struts2/jsp/ognl/Struts2OgnlJspTest.java:55`
-
-### Migration Resources
-- [IntelliJ Platform Migration 
Guide](https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-migration.html)
-- [API Changes 
List](https://plugins.jetbrains.com/docs/intellij/api-changes-list-2024.html)
-- [Platform Gradle Plugin 
2.0](https://blog.jetbrains.com/platform/2024/07/intellij-platform-gradle-plugin-2-0/)
-- [Build Number 
Ranges](https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html)
-```
+**JSP Reference Providers**: The `javaee.web.customServletReferenceProvider` 
extension point behavior changed in 2024.2. Action link references in JSP may 
need alternative registration approaches.
 
 ## Claude Guidance
 
-### Development Workflow
-- Always propose updating @CLAUDE.md
\ No newline at end of file
+- **Always use https://jb.gg/intellij-api-changes** when researching IntelliJ 
Platform API changes
+- **Update CHANGELOG.md** when upgrading dependencies: `- Dependencies - 
upgrade <name> to <version>`
+- **Run `./gradlew test -x rat`** before committing to catch test regressions
+- **Prefer editing existing files** over creating new ones
+- When fixing test failures, check if path resolution changed before assuming 
code bugs
\ No newline at end of file
diff --git a/docs/framework-initialization.md b/docs/framework-initialization.md
new file mode 100644
index 0000000..ce94402
--- /dev/null
+++ b/docs/framework-initialization.md
@@ -0,0 +1,446 @@
+# IntelliJ Platform Framework Initialization Guide
+
+This guide provides comprehensive documentation on how to initialize 
frameworks in IntelliJ Platform plugins, based on analysis of both official 
documentation and the Apache Struts plugin implementation.
+
+## Table of Contents
+
+1. [Modern Framework Initialization 
(2025)](#modern-framework-initialization-2025)
+2. [Complete Framework Integration 
Architecture](#complete-framework-integration-architecture)
+3. [Implementation Patterns](#implementation-patterns)
+4. [Best Practices](#best-practices)
+5. [Common Issues and Solutions](#common-issues-and-solutions)
+6. [Migration from Legacy Approaches](#migration-from-legacy-approaches)
+
+## Modern Framework Initialization (2025)
+
+### ProjectActivity - The Current Standard
+
+IntelliJ Platform 2024.2+ uses `ProjectActivity` as the modern replacement for 
deprecated initialization patterns.
+
+**Key Requirements:**
+- Must be implemented with **Kotlin coroutines** (Java not supported for new 
implementations)
+- Register via `<postStartupActivity implementation="..."/>` extension point
+- Executes after project is opened with proper coroutine context
+
+**Example Registration:**
+```xml
+<extensions defaultExtensionNs="com.intellij">
+  <postStartupActivity implementation="com.example.MyFrameworkInitializer"/>
+</extensions>
+```
+
+### Deprecated Patterns (Avoid These)
+
+- ❌ **Components**: Deprecated, don't support dynamic loading
+- ❌ **StartupActivity**: Marked as `@Obsolete`
+- ❌ **StartupManager.runAfterOpened()**: Internal API, removed
+
+## Complete Framework Integration Architecture
+
+The Apache Struts plugin demonstrates the comprehensive pattern for framework 
integration. Here are the core components:
+
+### 1. FacetType
+
+Defines the framework facet with metadata and capabilities.
+
+```java
+public class StrutsFacetType extends FacetType<StrutsFacet, 
StrutsFacetConfiguration> {
+
+  StrutsFacetType() {
+    super(StrutsFacet.FACET_TYPE_ID, "Struts2", "Struts 2");
+  }
+
+  @Override
+  public boolean isSuitableModuleType(final ModuleType moduleType) {
+    return moduleType instanceof JavaModuleType;  // Restrict to Java modules
+  }
+
+  @Override
+  public Icon getIcon() {
+    return Struts2Icons.Action;
+  }
+}
+```
+
+**Key Features:**
+- Unique facet type ID
+- Module type restrictions
+- Icon and help topic configuration
+- Factory methods for facet and configuration creation
+
+### 2. FacetConfiguration
+
+Manages framework-specific settings and persistence.
+
+```java
+public class StrutsFacetConfiguration extends SimpleModificationTracker
+    implements FacetConfiguration, ModificationTracker, Disposable {
+
+  @Override
+  public FacetEditorTab[] createEditorTabs(final FacetEditorContext 
editorContext,
+                                           final FacetValidatorsManager 
validatorsManager) {
+    return new FacetEditorTab[]{
+      new FileSetConfigurationTab(this, editorContext),
+      new FeaturesConfigurationTab(this)
+    };
+  }
+
+  @Override
+  public void readExternal(final Element element) throws InvalidDataException {
+    // XML persistence logic
+  }
+
+  @Override
+  public void writeExternal(final Element element) throws 
WriteExternalException {
+    // XML persistence logic
+  }
+}
+```
+
+**Responsibilities:**
+- Settings persistence (XML serialization)
+- Editor tabs for configuration UI
+- Validation and modification tracking
+- Resource disposal
+
+### 3. Facet
+
+The main facet class providing framework access at module level.
+
+```java
+public class StrutsFacet extends Facet<StrutsFacetConfiguration> {
+
+  public static final FacetTypeId<StrutsFacet> FACET_TYPE_ID = new 
FacetTypeId<>("struts2");
+
+  @Nullable
+  public static StrutsFacet getInstance(@NotNull final Module module) {
+    return FacetManager.getInstance(module).getFacetByType(FACET_TYPE_ID);
+  }
+
+  @Nullable
+  public WebFacet getWebFacet() {
+    return FacetManager.getInstance(getModule()).getFacetByType(WebFacet.ID);
+  }
+}
+```
+
+**Key Features:**
+- Static access methods for convenience
+- Integration with other facets (e.g., WebFacet)
+- Module-scoped framework instance
+
+### 4. FrameworkDetector
+
+Automatically detects framework presence in projects.
+
+```java
+public class StrutsFrameworkDetector extends 
FacetBasedFrameworkDetector<StrutsFacet, StrutsFacetConfiguration> {
+
+  @Override
+  public ElementPattern<FileContent> createSuitableFilePattern() {
+    return FileContentPattern.fileContent()
+      .withName(StrutsConstants.STRUTS_XML_DEFAULT_FILENAME)  // "struts.xml"
+      .xmlWithRootTag(StrutsRoot.TAG_NAME);                   // <struts>
+  }
+
+  @Override
+  public boolean isSuitableUnderlyingFacetConfiguration(final 
FacetConfiguration underlying,
+                                                        final 
StrutsFacetConfiguration configuration,
+                                                        final Set<? extends 
VirtualFile> files) {
+    return underlying instanceof WebFacetConfiguration;  // Requires Web facet
+  }
+}
+```
+
+**Detection Strategy:**
+- File pattern matching (e.g., struts.xml with &lt;struts&gt; root)
+- Underlying facet validation
+- Multi-file detection support
+
+### 5. FrameworkSupportProvider
+
+Handles "Add Framework Support" dialog integration.
+
+```java
+public class StrutsFrameworkSupportProvider extends 
FacetBasedFrameworkSupportProvider<StrutsFacet> {
+
+  @Override
+  public String getTitle() {
+    return UIUtil.replaceMnemonicAmpersand("Struts &2");
+  }
+
+  @Override
+  protected void onFacetCreated(final StrutsFacet strutsFacet,
+                                final ModifiableRootModel modifiableRootModel,
+                                final FrameworkVersion version) {
+    // Trigger initialization after facet creation
+  }
+}
+```
+
+**Capabilities:**
+- Framework library management
+- Version selection UI
+- Integration with project setup wizard
+- Post-creation initialization trigger
+
+### 6. Framework Initializer
+
+Performs complex setup tasks after framework addition.
+
+```java
+public class StrutsFrameworkInitializer implements ProjectActivity {
+
+  @Override
+  public Object execute(@NotNull Project project, @NotNull Continuation<? 
super Unit> continuation) {
+    DumbService.getInstance(project).runWhenSmart(() -> {
+      // Create default configuration files
+      final FileTemplate strutsXmlTemplate = 
templateProvider.determineFileTemplate(project);
+      final PsiElement strutsXml = 
FileTemplateUtil.createFromTemplate(strutsXmlTemplate, ...);
+
+      // Configure web.xml if present
+      WriteCommandAction.writeCommandAction(project).run(() -> {
+        // Add filters and mappings
+      });
+
+      // Show completion notification
+      new Notification("Framework Setup", "Framework has been configured 
successfully", ...)
+        .notify(project);
+    });
+  }
+}
+```
+
+**Initialization Tasks:**
+- Create default configuration files (struts.xml)
+- Configure web.xml with filters/mappings
+- Set up file sets for configuration discovery
+- Show user notifications
+- Handle error scenarios gracefully
+
+## Implementation Patterns
+
+### Plugin.xml Registration
+
+```xml
+<extensions defaultExtensionNs="com.intellij">
+  <!-- Core Framework Components -->
+  <facetType implementation="com.example.MyFacetType"/>
+  <frameworkSupport implementation="com.example.MyFrameworkSupportProvider"/>
+  <framework.detector implementation="com.example.MyFrameworkDetector"/>
+  <library.type implementation="com.example.MyLibraryType"/>
+
+  <!-- Modern Initialization -->
+  <postStartupActivity implementation="com.example.MyFrameworkInitializer"/>
+</extensions>
+```
+
+### Initialization Sequence Flow
+
+1. **Detection Phase**: `FrameworkDetector` scans project files
+2. **Support Addition**: User adds framework via "Add Framework Support"
+3. **Facet Creation**: `FrameworkSupportProvider` creates facet and 
configuration
+4. **Initialization**: `ProjectActivity` performs setup tasks
+5. **User Notification**: Success/failure feedback shown
+
+### Integration with IntelliJ Services
+
+```java
+// Index-dependent operations
+DumbService.getInstance(project).runWhenSmart(() -> {
+  // Search, analysis, file creation
+});
+
+// Write operations
+WriteCommandAction.writeCommandAction(project).run(() -> {
+  // File modifications
+});
+
+// File template usage
+FileTemplate template = FileTemplateManager.getInstance(project)
+  .getInternalTemplate("framework-config.xml");
+PsiElement created = FileTemplateUtil.createFromTemplate(template, ...);
+```
+
+## Best Practices
+
+### 1. Robust Error Handling
+
+```java
+try {
+  // Framework initialization logic
+} catch (Exception e) {
+  LOG.error("Framework initialization failed", e);
+
+  // Show user-friendly error notification
+  Notifications.Bus.notify(new Notification(
+    "Framework Setup",
+    "Setup Failed",
+    "Framework setup encountered an error: " + e.getMessage(),
+    NotificationType.ERROR
+  ), project);
+}
+```
+
+### 2. User Communication
+
+```java
+// Success notification with actionable links
+NotificationListener showSettingsListener = (notification, event) -> {
+  if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+    notification.expire();
+    ModulesConfigurator.showFacetSettingsDialog(facet, null);
+  }
+};
+
+new Notification("Framework Setup", "Setup Complete",
+  "Framework configured successfully. <a href=\"settings\">Review 
settings</a>",
+  NotificationType.INFORMATION)
+  .setListener(showSettingsListener)
+  .notify(project);
+```
+
+### 3. Incremental Initialization
+
+```java
+// Check if already initialized
+if (existingConfigFile != null) {
+  LOG.info("Framework already configured, skipping initialization");
+  return;
+}
+
+// Verify prerequisites
+if (requiredFacet == null) {
+  LOG.warn("Required underlying facet not found, postponing initialization");
+  return;
+}
+```
+
+### 4. Resource Management
+
+```java
+public class MyFacetConfiguration implements FacetConfiguration, Disposable {
+
+  @Override
+  public void dispose() {
+    // Clean up resources, listeners, etc.
+  }
+}
+
+// Register for disposal
+Disposer.register(facet, configuration);
+```
+
+## Common Issues and Solutions
+
+### Issue: ProjectActivity Not Executing
+
+**Symptoms:** Framework initializer never runs
+**Cause:** Missing plugin.xml registration or incorrect extension point
+**Solution:**
+```xml
+<postStartupActivity implementation="com.example.MyFrameworkInitializer"/>
+```
+
+### Issue: Dumb Mode Errors
+
+**Symptoms:** Index-related exceptions during initialization
+**Cause:** Accessing indices while IntelliJ is indexing
+**Solution:**
+```java
+DumbService.getInstance(project).runWhenSmart(() -> {
+  // Index-dependent logic here
+});
+```
+
+### Issue: Framework Not Auto-Detected
+
+**Symptoms:** Framework detector doesn't trigger
+**Cause:** Incorrect file pattern or missing registration
+**Solution:**
+```java
+@Override
+public ElementPattern<FileContent> createSuitableFilePattern() {
+  return FileContentPattern.fileContent()
+    .withName("framework-config.xml")  // Exact filename
+    .xmlWithRootTag("framework");      // XML root element
+}
+```
+
+### Issue: Facet Creation Fails
+
+**Symptoms:** "Add Framework Support" fails silently
+**Cause:** Unsuitable module type or missing underlying facets
+**Solution:**
+```java
+@Override
+public boolean isSuitableModuleType(final ModuleType moduleType) {
+  return moduleType instanceof JavaModuleType;  // Be specific
+}
+
+@Override
+public boolean isSuitableUnderlyingFacetConfiguration(...) {
+  return underlying instanceof RequiredFacetConfiguration;
+}
+```
+
+## Migration from Legacy Approaches
+
+### From StartupActivity to ProjectActivity
+
+**Legacy (Deprecated):**
+```java
+public class OldInitializer implements StartupActivity {
+  @Override
+  public void runActivity(@NotNull Project project) {
+    // Old initialization logic
+  }
+}
+```
+
+**Modern (Recommended):**
+```java
+// Kotlin implementation required for new code
+class ModernInitializer : ProjectActivity {
+  override suspend fun execute(project: Project) {
+    withContext(Dispatchers.IO) {
+      // Initialization logic with coroutines
+    }
+  }
+}
+```
+
+### From Components to Services
+
+**Legacy (Deprecated):**
+```xml
+<project-components>
+  <component>
+    <implementation-class>com.example.ProjectComponent</implementation-class>
+  </component>
+</project-components>
+```
+
+**Modern (Recommended):**
+```xml
+<extensions defaultExtensionNs="com.intellij">
+  <projectService serviceImplementation="com.example.ProjectService"/>
+</extensions>
+```
+
+## Conclusion
+
+Framework initialization in modern IntelliJ Platform plugins requires:
+
+1. **Complete Architecture**: Facet + Configuration + Detector + Support 
Provider + Initializer
+2. **Modern APIs**: ProjectActivity with Kotlin coroutines (for new 
implementations)
+3. **Proper Registration**: All components registered in plugin.xml
+4. **Robust Implementation**: Error handling, user communication, resource 
management
+5. **Testing**: Verification across different project configurations
+
+The Apache Struts plugin provides an excellent reference implementation, 
though it still uses Java-based ProjectActivity which is acceptable for 
existing code but should be migrated to Kotlin for new implementations.
+
+For questions or issues, consult:
+- [IntelliJ Platform Plugin SDK](https://plugins.jetbrains.com/docs/intellij/)
+- [API Changes List](https://jb.gg/intellij-api-changes)
+- [Facet Documentation](https://plugins.jetbrains.com/docs/intellij/facet.html)
\ No newline at end of file
diff --git a/src/main/java/com/intellij/lang/ognl/OgnlTypedHandler.java 
b/src/main/java/com/intellij/lang/ognl/OgnlTypedHandler.java
index 418fc15..dd2c47f 100644
--- a/src/main/java/com/intellij/lang/ognl/OgnlTypedHandler.java
+++ b/src/main/java/com/intellij/lang/ognl/OgnlTypedHandler.java
@@ -24,7 +24,7 @@ import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.lang.ognl.OgnlFileType;
 import com.intellij.lang.ognl.OgnlLanguage;
-import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
+import com.intellij.lang.injection.InjectedLanguageManager;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -48,7 +48,7 @@ public class OgnlTypedHandler extends TypedHandlerDelegate {
     if (file.getFileType() != OgnlFileType.INSTANCE) {
       
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
       final int offset = editor.getCaretModel().getOffset();
-      final PsiElement elementAtCursor = 
InjectedLanguageManagerImpl.getInstanceImpl(project).findInjectedElementAt(file,
 offset);
+      final PsiElement elementAtCursor = 
InjectedLanguageManager.getInstance(project).findInjectedElementAt(file, 
offset);
       if (elementAtCursor == null) {
         return Result.CONTINUE;
       }
diff --git 
a/src/main/java/com/intellij/lang/ognl/psi/impl/OgnlReferenceExpressionBase.java
 
b/src/main/java/com/intellij/lang/ognl/psi/impl/OgnlReferenceExpressionBase.java
index 70bdbcc..db2eeee 100644
--- 
a/src/main/java/com/intellij/lang/ognl/psi/impl/OgnlReferenceExpressionBase.java
+++ 
b/src/main/java/com/intellij/lang/ognl/psi/impl/OgnlReferenceExpressionBase.java
@@ -23,7 +23,7 @@ import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiReference;
 import com.intellij.psi.PsiReferenceBase;
-import com.intellij.ui.IconManager;
+import com.intellij.icons.AllIcons;
 import com.intellij.util.ArrayUtilRt;
 import org.jetbrains.annotations.NotNull;
 
@@ -40,7 +40,7 @@ abstract class OgnlReferenceExpressionBase extends 
OgnlExpressionImpl {
   public ItemPresentation getPresentation() {
     return new PresentationData(getIdentifier().getText(),
                                 null,
-                                
IconManager.getInstance().getPlatformIcon(com.intellij.ui.PlatformIcons.Parameter),
+                                AllIcons.Nodes.Parameter,
                                 null);
   }
 
diff --git a/src/main/java/com/intellij/struts2/facet/StrutsFacetType.java 
b/src/main/java/com/intellij/struts2/facet/StrutsFacetType.java
index 0d95045..c57c94b 100644
--- a/src/main/java/com/intellij/struts2/facet/StrutsFacetType.java
+++ b/src/main/java/com/intellij/struts2/facet/StrutsFacetType.java
@@ -17,6 +17,7 @@ package com.intellij.struts2.facet;
 
 import com.intellij.facet.Facet;
 import com.intellij.facet.FacetType;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.module.JavaModuleType;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleType;
@@ -33,39 +34,43 @@ import javax.swing.*;
  * @author Yann C&eacute;bron
  */
 public class StrutsFacetType extends FacetType<StrutsFacet, 
StrutsFacetConfiguration> {
-  StrutsFacetType() {
-    super(StrutsFacet.FACET_TYPE_ID, "Struts2", "Struts 2");
-  }
 
-  public static FacetType<StrutsFacet, StrutsFacetConfiguration> getInstance() 
{
-    return findInstance(StrutsFacetType.class);
-  }
+    private static final Logger LOG = 
Logger.getInstance(StrutsFacetType.class);
 
-  @Override
-  public StrutsFacetConfiguration createDefaultConfiguration() {
-    return new StrutsFacetConfiguration();
-  }
+    StrutsFacetType() {
+        super(StrutsFacet.FACET_TYPE_ID, "Struts2", "Struts 2");
+    }
 
-  @Override
-  public StrutsFacet createFacet(@NotNull final Module module,
-                                 final String name,
-                                 @NotNull final StrutsFacetConfiguration 
configuration,
-                                 @Nullable final Facet underlyingFacet) {
-    return new StrutsFacet(this, module, name, configuration, underlyingFacet);
-  }
+    public static FacetType<StrutsFacet, StrutsFacetConfiguration> 
getInstance() {
+        return findInstance(StrutsFacetType.class);
+    }
 
-  @Override
-  public boolean isSuitableModuleType(final ModuleType moduleType) {
-    return moduleType instanceof JavaModuleType;
-  }
+    @Override
+    public StrutsFacetConfiguration createDefaultConfiguration() {
+        return new StrutsFacetConfiguration();
+    }
 
-  @Override
-  public Icon getIcon() {
-    return Struts2Icons.Action;
-  }
+    @Override
+    public StrutsFacet createFacet(@NotNull final Module module,
+                                   final String name,
+                                   @NotNull final StrutsFacetConfiguration 
configuration,
+                                   @Nullable final Facet underlyingFacet) {
+        LOG.info("Creating Struts facet with name " + name + " for module " + 
module.getName());
+        return new StrutsFacet(this, module, name, configuration, 
underlyingFacet);
+    }
 
-  @Override
-  public String getHelpTopic() {
-    return "reference.settings.project.structure.facets.struts2.facet";
-  }
+    @Override
+    public boolean isSuitableModuleType(final ModuleType moduleType) {
+        return moduleType instanceof JavaModuleType;
+    }
+
+    @Override
+    public Icon getIcon() {
+        return Struts2Icons.Action;
+    }
+
+    @Override
+    public String getHelpTopic() {
+        return "reference.settings.project.structure.facets.struts2.facet";
+    }
 }
diff --git 
a/src/main/java/com/intellij/struts2/facet/StrutsFrameworkDetector.java 
b/src/main/java/com/intellij/struts2/facet/StrutsFrameworkDetector.java
index 7c6ace3..8fd969c 100644
--- a/src/main/java/com/intellij/struts2/facet/StrutsFrameworkDetector.java
+++ b/src/main/java/com/intellij/struts2/facet/StrutsFrameworkDetector.java
@@ -20,14 +20,19 @@ import 
com.intellij.framework.detection.FacetBasedFrameworkDetector;
 import com.intellij.framework.detection.FileContentPattern;
 import com.intellij.ide.highlighter.XmlFileType;
 import com.intellij.javaee.web.facet.WebFacetConfiguration;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.roots.ModifiableRootModel;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.patterns.ElementPattern;
 import com.intellij.struts2.StrutsConstants;
 import com.intellij.struts2.dom.struts.StrutsRoot;
+import com.intellij.struts2.facet.ui.StrutsConfigsSearcher;
+import com.intellij.struts2.facet.ui.StrutsFileSet;
 import com.intellij.util.indexing.FileContent;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.Collection;
 import java.util.Set;
 
 /**
@@ -35,10 +40,51 @@ import java.util.Set;
  */
 public class StrutsFrameworkDetector extends 
FacetBasedFrameworkDetector<StrutsFacet, StrutsFacetConfiguration> {
 
+  private static final Logger LOG = 
Logger.getInstance(StrutsFrameworkDetector.class);
+
   public StrutsFrameworkDetector() {
     super("struts2");
   }
 
+  @Override
+  public void setupFacet(@NotNull StrutsFacet facet, ModifiableRootModel 
model) {
+    LOG.info("Setting up Struts facet for module: " + 
facet.getModule().getName());
+
+    // Search for struts.xml files in module's source and resource roots
+    com.intellij.openapi.module.Module module = facet.getModule();
+    StrutsConfigsSearcher searcher = new StrutsConfigsSearcher(module);
+    Set<com.intellij.psi.PsiFile> configPsiFiles = searcher.search(module, 
module.getProject());
+
+    Collection<VirtualFile> configFiles = new java.util.ArrayList<>();
+    for (com.intellij.psi.PsiFile psiFile : configPsiFiles) {
+      VirtualFile vf = psiFile.getVirtualFile();
+      if (vf != null) {
+        configFiles.add(vf);
+      }
+    }
+
+    LOG.info("Found " + configFiles.size() + " Struts configuration files");
+
+    if (!configFiles.isEmpty()) {
+      StrutsFacetConfiguration config = facet.getConfiguration();
+      Set<StrutsFileSet> fileSets = config.getFileSets();
+
+      StrutsFileSet fileSet = new StrutsFileSet(
+        StrutsFileSet.getUniqueId(fileSets),
+        StrutsFileSet.getUniqueName("Detected Configuration", fileSets),
+        config
+      );
+
+      for (VirtualFile file : configFiles) {
+        fileSet.addFile(file);
+        LOG.debug("Added detected file to file set: " + file.getPath());
+      }
+
+      fileSets.add(fileSet);
+      LOG.info("Created file set with " + configFiles.size() + " files for 
module: " + facet.getModule().getName());
+    }
+  }
+
   @NotNull
   @Override
   public FacetType<StrutsFacet, StrutsFacetConfiguration> getFacetType() {
diff --git 
a/src/main/java/com/intellij/struts2/facet/StrutsFrameworkInitializer.java 
b/src/main/java/com/intellij/struts2/facet/StrutsFrameworkInitializer.java
new file mode 100644
index 0000000..382c893
--- /dev/null
+++ b/src/main/java/com/intellij/struts2/facet/StrutsFrameworkInitializer.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2025 The authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intellij.struts2.facet;
+
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationAction;
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
+import com.intellij.openapi.startup.ProjectActivity;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.struts2.StrutsConstants;
+import com.intellij.struts2.facet.ui.StrutsConfigsSearcher;
+import com.intellij.struts2.facet.ui.StrutsFileSet;
+import com.intellij.util.containers.MultiMap;
+import kotlin.Unit;
+import kotlin.coroutines.Continuation;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Handles initialization of newly created Struts facets using modern 
ProjectActivity pattern.
+ * <p>
+ * This initializer replaces the deprecated StartupManager.runAfterOpened() 
approach and provides
+ * proper framework setup after facet creation. It performs the following 
tasks:
+ * <ul>
+ *   <li>Discovers Struts configuration files in project JARs</li>
+ *   <li>Sets up file sets for configuration discovery and management</li>
+ *   <li>Provides thread-safe PSI operations using ReadAction</li>
+ *   <li>Shows user notifications about setup completion with actionable 
links</li>
+ * </ul>
+ * <p>
+ * The initializer is triggered via the {@link StrutsFrameworkSupportProvider} 
when a new
+ * Struts facet is created through "Add Framework Support" action. Unlike 
previous implementations,
+ * this initializer does NOT create files automatically, following modern IDE 
plugin best practices.
+ *
+ * @author Generated for IntelliJ Platform 2025.2 compatibility
+ * @see StrutsFrameworkSupportProvider#onFacetCreated
+ * @see ProjectActivity
+ */
+public class StrutsFrameworkInitializer implements ProjectActivity {
+
+    private static final Logger LOG = 
Logger.getInstance(StrutsFrameworkInitializer.class);
+
+    /**
+     * Thread-safe storage for pending initialization data.
+     * Key: project, Value: initialization data
+     */
+    private static final ConcurrentHashMap<String, InitializationData> 
pendingInitializations = new ConcurrentHashMap<>();
+
+    /**
+     * Data structure to hold initialization parameters passed from the 
framework support provider.
+     */
+    public static class InitializationData {
+        public final Project project;
+        public final StrutsFacet strutsFacet;
+
+        public InitializationData(@NotNull Project project, @NotNull 
StrutsFacet strutsFacet) {
+            this.project = project;
+            this.strutsFacet = strutsFacet;
+        }
+
+        @Override
+        public String toString() {
+            return "InitializationData{project=" + project.getName() + ", 
module=" + strutsFacet.getModule().getName() + "}";
+        }
+    }
+
+    /**
+     * Schedules a Struts facet for initialization when the project opens.
+     * This method is called from {@link 
StrutsFrameworkSupportProvider#onFacetCreated}.
+     *
+     * @param project the project containing the facet
+     * @param strutsFacet the newly created Struts facet to initialize
+     */
+    public static void scheduleInitialization(@NotNull Project project, 
@NotNull StrutsFacet strutsFacet) {
+        LOG.info("Scheduling Struts facet initialization for project: " + 
project.getName() +
+                 ", module: " + strutsFacet.getModule().getName());
+        pendingInitializations.put(project.getName(), new 
InitializationData(project, strutsFacet));
+    }
+
+    /**
+     * ProjectActivity execution method called when project is opened.
+     * Checks for pending Struts facet initializations and performs setup 
tasks.
+     *
+     * @param project the project being opened
+     * @param continuation Kotlin coroutine continuation (required by 
interface)
+     * @return the initialized facet or null if no initialization was needed
+     */
+    @Override
+    @Nullable
+    public Object execute(@NotNull Project project, @NotNull Continuation<? 
super Unit> continuation) {
+        LOG.debug("Struts framework initializer execute called for project: " 
+ project.getName());
+
+        InitializationData data = 
pendingInitializations.remove(project.getName());
+        if (data != null) {
+            LOG.info("Found pending Struts initialization data: " + data);
+            performInitialization(data);
+            return data.strutsFacet;
+        }
+
+        // Check for existing facets (project reopened) - no initialization 
needed
+        ModuleManager moduleManager = ModuleManager.getInstance(project);
+        Module[] modules = moduleManager.getModules();
+        LOG.debug("Checking " + modules.length + " modules for existing Struts 
facets");
+        for (Module module : modules) {
+            StrutsFacet facet = StrutsFacet.getInstance(module);
+            if (facet != null) {
+                LOG.debug("Found existing Struts facet in module: " + 
module.getName() + ", no initialization needed");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Checks if the given facet needs initialization (e.g., missing 
struts.xml).
+     * Uses ReadAction to ensure thread-safe PSI access.
+     */
+    private boolean shouldInitializeFacet(@NotNull StrutsFacet facet) {
+        return ReadAction.compute(() -> {
+            Module module = facet.getModule();
+            VirtualFile[] sourceRoots = 
ModuleRootManager.getInstance(module).getSourceRoots();
+
+            if (sourceRoots.length == 0) {
+                return false;
+            }
+
+            PsiDirectory directory = 
PsiManager.getInstance(module.getProject()).findDirectory(sourceRoots[0]);
+            return directory != null && 
directory.findFile(StrutsConstants.STRUTS_XML_DEFAULT_FILENAME) == null;
+        });
+    }
+
+    /**
+     * Performs the actual Struts framework initialization tasks.
+     * This method contains the logic moved from 
StrutsFrameworkSupportProvider.
+     *
+     * @param data initialization data containing project and facet information
+     */
+    private void performInitialization(@NotNull InitializationData data) {
+        LOG.info("Starting Struts framework initialization for: " + data);
+
+        DumbService.getInstance(data.project).runWhenSmart(() -> {
+            try {
+                initializeStrutsFramework(data);
+            } catch (Exception e) {
+                LOG.error("Struts framework initialization failed for " + 
data, e);
+                showErrorNotification(data.project, e);
+            }
+        });
+    }
+
+    /**
+     * Core initialization logic that discovers JAR configuration files and 
sets up the framework.
+     * Uses proper read/write actions for thread-safe PSI operations.
+     */
+    private void initializeStrutsFramework(@NotNull InitializationData data) {
+        final Module module = data.strutsFacet.getModule();
+
+        LOG.info("Setting up Struts framework configuration for module: " + 
module.getName());
+        final StrutsFacetConfiguration strutsFacetConfiguration = 
data.strutsFacet.getConfiguration();
+
+        // Search for Struts configuration files in JARs (requires smart mode)
+        final StrutsConfigsSearcher searcher = new 
StrutsConfigsSearcher(module);
+        DumbService.getInstance(data.project).runWhenSmart(() -> {
+            try {
+                searcher.search();
+                final MultiMap<VirtualFile, PsiFile> jarConfigFiles = 
searcher.getJars();
+
+                if (!jarConfigFiles.isEmpty()) {
+                    // Create file set for JAR-based configuration files
+                    final Set<StrutsFileSet> existingFileSets = 
strutsFacetConfiguration.getFileSets();
+                    final StrutsFileSet jarFileSet = new StrutsFileSet(
+                        StrutsFileSet.getUniqueId(existingFileSets),
+                        StrutsFileSet.getUniqueName("JAR Configuration Files", 
existingFileSets),
+                        strutsFacetConfiguration
+                    );
+
+                    int jarFilesCount = 0;
+                    for (final VirtualFile jarFile : jarConfigFiles.keySet()) {
+                        final Collection<PsiFile> configFiles = 
jarConfigFiles.get(jarFile);
+                        for (final PsiFile configFile : configFiles) {
+                            jarFileSet.addFile(configFile.getVirtualFile());
+                            jarFilesCount++;
+                        }
+                        LOG.debug("Found " + configFiles.size() + " 
configuration files in JAR: " + jarFile.getName());
+                    }
+
+                    if (jarFilesCount > 0) {
+                        strutsFacetConfiguration.getFileSets().add(jarFileSet);
+                        LOG.info("Added " + jarFilesCount + " JAR config files 
to Struts facet configuration");
+
+                        // Show success notification after JAR discovery
+                        showSuccessNotification(data.project, 
data.strutsFacet);
+                    }
+                } else {
+                    LOG.debug("No Struts configuration files found in JARs for 
module: " + module.getName());
+
+                    // Still show success notification even if no JAR files 
found
+                    showSuccessNotification(data.project, data.strutsFacet);
+                }
+            } catch (Exception e) {
+                LOG.warn("Failed to search for JAR configuration files in 
module: " + module.getName(), e);
+
+                // Show success notification despite JAR search failure
+                showSuccessNotification(data.project, data.strutsFacet);
+            }
+        });
+    }
+
+    /**
+     * Shows success notification with link to facet settings.
+     */
+    private void showSuccessNotification(@NotNull Project project, @NotNull 
StrutsFacet strutsFacet) {
+        new Notification("Struts 2", "Struts 2 setup complete",
+                         "Struts 2 framework has been configured 
successfully.",
+                         NotificationType.INFORMATION)
+          .addAction(new NotificationAction("Review settings") {
+              @Override
+              public void actionPerformed(@NotNull AnActionEvent e, @NotNull 
Notification notification) {
+                  notification.expire();
+                  ModulesConfigurator.showFacetSettingsDialog(strutsFacet, 
null);
+              }
+          })
+          .notify(project);
+
+        LOG.info("Struts framework initialization completed successfully for 
module: " + strutsFacet.getModule().getName());
+    }
+
+    /**
+     * Shows error notification when initialization fails.
+     */
+    private void showErrorNotification(@NotNull Project project, @NotNull 
Exception error) {
+        new Notification("Struts 2", "Struts 2 setup failed",
+                         "Struts 2 framework setup encountered an error: " + 
error.getMessage() +
+                         ". Check IDE logs for details.",
+                         NotificationType.ERROR)
+          .notify(project);
+    }
+}
\ No newline at end of file
diff --git 
a/src/main/java/com/intellij/struts2/facet/StrutsFrameworkSupportProvider.java 
b/src/main/java/com/intellij/struts2/facet/StrutsFrameworkSupportProvider.java
index 622f262..5e329ba 100644
--- 
a/src/main/java/com/intellij/struts2/facet/StrutsFrameworkSupportProvider.java
+++ 
b/src/main/java/com/intellij/struts2/facet/StrutsFrameworkSupportProvider.java
@@ -15,56 +15,22 @@
 
 package com.intellij.struts2.facet;
 
-import com.intellij.codeInsight.FileModificationService;
 import com.intellij.facet.ui.FacetBasedFrameworkSupportProvider;
 import com.intellij.framework.library.DownloadableLibraryService;
 import com.intellij.framework.library.FrameworkSupportWithLibrary;
-import com.intellij.ide.fileTemplates.FileTemplate;
-import com.intellij.ide.fileTemplates.FileTemplateUtil;
 import com.intellij.ide.util.frameworkSupport.FrameworkSupportConfigurableBase;
 import com.intellij.ide.util.frameworkSupport.FrameworkSupportModel;
 import com.intellij.ide.util.frameworkSupport.FrameworkSupportProviderBase;
 import com.intellij.ide.util.frameworkSupport.FrameworkVersion;
 import com.intellij.ide.util.projectWizard.ModuleBuilder;
-import com.intellij.jam.model.util.JamCommonUtil;
-import com.intellij.javaee.web.facet.WebFacet;
-import com.intellij.javaee.web.model.xml.Filter;
-import com.intellij.javaee.web.model.xml.FilterMapping;
-import com.intellij.javaee.web.model.xml.WebApp;
-import com.intellij.notification.Notification;
-import com.intellij.notification.NotificationListener;
-import com.intellij.notification.NotificationType;
-import com.intellij.openapi.command.WriteCommandAction;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.roots.ModifiableRootModel;
-import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
 import 
com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription;
-import com.intellij.openapi.startup.StartupManager;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDirectory;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
-import com.intellij.psi.xml.XmlFile;
-import com.intellij.struts2.StrutsConstants;
-import com.intellij.struts2.StrutsFileTemplateProvider;
-import com.intellij.struts2.facet.ui.StrutsConfigsSearcher;
-import com.intellij.struts2.facet.ui.StrutsFileSet;
-import com.intellij.util.containers.MultiMap;
-import com.intellij.util.descriptors.ConfigFile;
 import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import javax.swing.event.HyperlinkEvent;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
-import java.util.Set;
 
 /**
  * "Add Framework" support.
@@ -93,6 +59,7 @@ public class StrutsFrameworkSupportProvider extends 
FacetBasedFrameworkSupportPr
   @Override
   protected void setupConfiguration(final StrutsFacet strutsFacet,
                                     final ModifiableRootModel 
modifiableRootModel, final FrameworkVersion version) {
+      LOG.info("Setting up Struts facet with name " + strutsFacet.getName());
   }
 
   @Override
@@ -104,101 +71,11 @@ public class StrutsFrameworkSupportProvider extends 
FacetBasedFrameworkSupportPr
   protected void onFacetCreated(final StrutsFacet strutsFacet,
                                 final ModifiableRootModel modifiableRootModel,
                                 final FrameworkVersion version) {
-    final Module module = strutsFacet.getModule();
-    StartupManager.getInstance(module.getProject()).runAfterOpened(() -> {
-      DumbService.getInstance(module.getProject()).runWhenSmart(() -> {
-          final VirtualFile[] sourceRoots = 
ModuleRootManager.getInstance(module).getSourceRoots();
-          if (sourceRoots.length <= 0) {
-            return;
-          }
-
-          final PsiDirectory directory = 
PsiManager.getInstance(module.getProject()).findDirectory(sourceRoots[0]);
-          if (directory == null ||
-              directory.findFile(StrutsConstants.STRUTS_XML_DEFAULT_FILENAME) 
!= null) {
-            return;
-          }
-
-          final StrutsFileTemplateProvider templateProvider = new 
StrutsFileTemplateProvider(module);
-          final FileTemplate strutsXmlTemplate = 
templateProvider.determineFileTemplate(directory.getProject());
-
-          try {
-            final StrutsFacetConfiguration strutsFacetConfiguration = 
strutsFacet.getConfiguration();
-
-            // create empty struts.xml & fileset with all found struts-*.xml 
files (struts2.jar, plugins)
-            final PsiElement psiElement = 
FileTemplateUtil.createFromTemplate(strutsXmlTemplate,
-                                                                              
StrutsConstants.STRUTS_XML_DEFAULT_FILENAME,
-                                                                              
null,
-                                                                              
directory);
-            final Set<StrutsFileSet> empty = Collections.emptySet();
-            final StrutsFileSet fileSet = new 
StrutsFileSet(StrutsFileSet.getUniqueId(empty),
-                                                            
StrutsFileSet.getUniqueName("Default File Set", empty),
-                                                            
strutsFacetConfiguration);
-            fileSet.addFile(((XmlFile)psiElement).getVirtualFile());
-
-            final StrutsConfigsSearcher searcher = new 
StrutsConfigsSearcher(module);
-            DumbService.getInstance(module.getProject()).runWhenSmart(() -> 
searcher.search());
-
-            final MultiMap<VirtualFile, PsiFile> jarConfigFiles = 
searcher.getJars();
-            for (final VirtualFile virtualFile : jarConfigFiles.keySet()) {
-              final Collection<PsiFile> psiFiles = 
jarConfigFiles.get(virtualFile);
-              for (final PsiFile psiFile : psiFiles) {
-                fileSet.addFile(psiFile.getVirtualFile());
-              }
-            }
-            strutsFacetConfiguration.getFileSets().add(fileSet);
-
-
-            // create filter & mapping in web.xml (if present)
-            
WriteCommandAction.writeCommandAction(modifiableRootModel.getProject()).run(() 
-> {
-              final WebFacet webFacet = strutsFacet.getWebFacet();
-              if (null == webFacet) return;
-
-              final ConfigFile configFile = webFacet.getWebXmlDescriptor();
-              if (configFile == null) return;
-
-              final XmlFile webXmlFile = configFile.getXmlFile();
-              final WebApp webApp = JamCommonUtil.getRootElement(webXmlFile, 
WebApp.class);
-              if (webApp == null) return;
-              if 
(!FileModificationService.getInstance().prepareFileForWrite(webXmlFile)) return;
-
-              final Filter strutsFilter = webApp.addFilter();
-              strutsFilter.getFilterName().setStringValue("struts2");
-
-              @NonNls final String filterClass = templateProvider.is21orNewer()
-                      ? templateProvider.is25orNewer()
-                      ? StrutsConstants.STRUTS_2_5_FILTER_CLASS
-                      : StrutsConstants.STRUTS_2_1_FILTER_CLASS
-                      : StrutsConstants.STRUTS_2_0_FILTER_CLASS;
-              strutsFilter.getFilterClass().setStringValue(filterClass);
-
-              final FilterMapping filterMapping = webApp.addFilterMapping();
-              filterMapping.getFilterName().setValue(strutsFilter);
-              filterMapping.addUrlPattern().setStringValue("/*");
-            });
-
-
-            final NotificationListener showFacetSettingsListener = new 
NotificationListener() {
-              @Override
-              public void hyperlinkUpdate(@NotNull final Notification 
notification,
-                                          @NotNull final HyperlinkEvent event) 
{
-                if (event.getEventType() == 
HyperlinkEvent.EventType.ACTIVATED) {
-                  notification.expire();
-                  ModulesConfigurator.showFacetSettingsDialog(strutsFacet, 
null);
-                }
-              }
-            };
-
-            new Notification("Struts 2", "Struts 2 Setup",
-                             "Struts 2 Facet has been created, please check <a 
href=\"more\">created fileset</a>",
-                             NotificationType.INFORMATION)
-              .setListener(showFacetSettingsListener)
-              .notify(module.getProject());
-          }
-          catch (Exception e) {
-            LOG.error("error creating struts.xml from template", e);
-          }
-        });
-    });
+    LOG.info("onFacetCreated: " + strutsFacet);
+
+    // Schedule initialization using modern ProjectActivity pattern
+    // The StrutsFrameworkInitializer will handle the actual setup when the 
project opens
+    
StrutsFrameworkInitializer.scheduleInitialization(modifiableRootModel.getProject(),
 strutsFacet);
   }
 
   private static final class Struts2FrameworkSupportConfigurable extends 
FrameworkSupportConfigurableBase
diff --git 
a/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java 
b/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
index 5eedc22..415e103 100644
--- a/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
+++ b/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
@@ -228,10 +228,9 @@ public class FileSetConfigurationTab extends 
FacetEditorTab implements Disposabl
     myEditButton = ToolbarDecorator.findEditButton(myTreePanel);
     myRemoveButton = ToolbarDecorator.findRemoveButton(myTreePanel);
 
-    AnActionButton addButton = ToolbarDecorator.findAddButton(myTreePanel);
-    assert addButton != null;
-    dumbService.makeDumbAware(addButton.getContextComponent(), this);
-    dumbService.makeDumbAware(myEditButton.getContextComponent(), this);
+    // Note: makeDumbAware API may have changed in IntelliJ Platform 2025.2
+    // Removing these calls as they caused compilation errors
+    // Component dumb awareness should still work through DumbAware interface
   }
 
   @Nullable
diff --git 
a/src/main/java/com/intellij/struts2/model/constant/contributor/StrutsCoreConstantContributor.java
 
b/src/main/java/com/intellij/struts2/model/constant/contributor/StrutsCoreConstantContributor.java
index 7bc3d28..bf0a370 100644
--- 
a/src/main/java/com/intellij/struts2/model/constant/contributor/StrutsCoreConstantContributor.java
+++ 
b/src/main/java/com/intellij/struts2/model/constant/contributor/StrutsCoreConstantContributor.java
@@ -20,7 +20,7 @@ import com.intellij.openapi.module.Module;
 import com.intellij.openapi.util.NotNullLazyValue;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.CharsetToolkit;
+import java.nio.charset.Charset;
 import com.intellij.struts2.StrutsConstants;
 import com.intellij.struts2.model.constant.StrutsConstant;
 import com.intellij.struts2.model.constant.StrutsConstantKey;
@@ -123,7 +123,7 @@ public final class StrutsCoreConstantContributor extends 
StrutsConstantContribut
    */
   private static final class EncodingConverter extends 
ResolvingConverter.StringConverter {
     private final NotNullLazyValue<Set<String>> charSets = 
NotNullLazyValue.atomicLazy(() -> {
-      return ContainerUtil.map2Set(CharsetToolkit.getAvailableCharsets(), 
charset -> charset.name());
+      return ContainerUtil.map2Set(Charset.availableCharsets().values(), 
charset -> charset.name());
     });
 
     @Override
diff --git a/src/main/resources/META-INF/plugin.xml 
b/src/main/resources/META-INF/plugin.xml
index bf3fc34..ae49d5f 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -61,6 +61,9 @@
         <framework.detector 
implementation="com.intellij.struts2.facet.StrutsFrameworkDetector"/>
         <library.type 
implementation="com.intellij.struts2.facet.Struts2LibraryType"/>
 
+        <!-- Framework initialization using modern ProjectActivity pattern -->
+        <postStartupActivity 
implementation="com.intellij.struts2.facet.StrutsFrameworkInitializer"/>
+
         <psi.referenceContributor language="XML"
                                   
implementation="com.intellij.struts2.reference.StrutsReferenceContributor"/>
         <psi.referenceContributor language="XML"

Reply via email to