[ 
https://issues.apache.org/jira/browse/WW-4291?focusedWorklogId=1002871&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1002871
 ]

ASF GitHub Bot logged work on WW-4291:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 01/Feb/26 09:24
            Start Date: 01/Feb/26 09:24
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart opened a new pull request, #1562:
URL: https://github.com/apache/struts/pull/1562

   ## Summary
   
   This PR implements two-phase processing for conversion properties to enable 
Spring bean name resolution in `struts-conversion.properties` files.
   
   **Problem:** Users could not reference Spring bean names in conversion 
properties. When specifying a bean name (e.g., "myConverter") instead of a 
fully qualified class name, a `ClassNotFoundException` was thrown.
   
   **Root Cause:** Type converters were processed during the bootstrap phase 
before `SpringObjectFactory` was available. 
`SpringObjectFactory.getClassInstance()` already supports bean names via 
`containsBean()` check, but it wasn't being used during early initialization.
   
   **Solution:** Split conversion property processing into two phases:
   - **Early phase (EarlyInitializable):** Process 
`struts-default-conversion.properties` only - contains class names
   - **Late phase (Initializable):** Process user properties 
(`struts-conversion.properties`, `xwork-conversion.properties`) when 
`SpringObjectFactory` is available
   
   ## Changes
   
   - Add `UserConversionPropertiesProvider` interface defining the late 
initialization contract
   - Add `UserConversionPropertiesProcessor` implementing `Initializable` for 
late-phase processing
   - Modify `StrutsConversionPropertiesProcessor` to implement 
`UserConversionPropertiesProvider` and split `init()` into early/late phases
   - Register new beans in `DefaultConfiguration` and `struts-beans.xml`
   - Add alias in `StrutsBeanSelectionProvider` for proper dependency injection
   - Explicitly trigger late initialization in 
`DefaultConfiguration.reloadContainer()`
   - Improve JavaDocs for `BeanSelectionProvider` and 
`AbstractBeanSelectionProvider`
   
   ## Usage After This Change
   
   Users can now specify Spring bean names in `struts-conversion.properties`:
   
   ```properties
   # Using Spring bean name
   java.time.LocalDate=localDateConverter
   
   # Using class name (still works - backward compatible)
   java.util.UUID=com.example.UUIDConverter
   ```
   
   ## Test Plan
   
   - [x] Unit tests for `StrutsConversionPropertiesProcessor` two-phase 
processing
   - [x] Integration tests for Spring bean name resolution via 
`SpringObjectFactory`
   - [ ] Run full test suite: `mvn test -DskipAssembly`
   - [ ] Manual verification with sample Spring application
   
   Fixes [WW-4291](https://issues.apache.org/jira/browse/WW-4291)
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)




Issue Time Tracking
-------------------

            Worklog Id:     (was: 1002871)
    Remaining Estimate: 0h
            Time Spent: 10m

> Can't use Spring bean name for type convertor
> ---------------------------------------------
>
>                 Key: WW-4291
>                 URL: https://issues.apache.org/jira/browse/WW-4291
>             Project: Struts 2
>          Issue Type: Improvement
>          Components: Plugin - Spring
>    Affects Versions: 6.1.1
>            Reporter: Jasper Rosenberg
>            Assignee: Lukasz Lenart
>            Priority: Minor
>             Fix For: 6.9.0, 7.2.0
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> If in your xwork.conversion.properties file you try to use a Spring bean name 
> instead of a class name, it blows up.
> This is because DefaultConfiguration.createBootstrapContainer() ends up using 
> DefaultTypeConverterCreator which has the generic ObjectFactory at that point 
> because it happens before the struts.properties file is ever loaded (where in 
> my case the SpringObjectFactory is defined.)
> {noformat}
> 10:20:06,910 ERROR [DefaultConversionPropertiesProcessor] Conversion 
> registration error
> java.lang.ClassNotFoundException: entityObjectTypeConvertor
>         at 
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1680)
>         at 
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
>         at 
> com.opensymphony.xwork2.util.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:152)
>         at 
> com.opensymphony.xwork2.ObjectFactory.getClassInstance(ObjectFactory.java:108)
>         at 
> com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:161)
>         at 
> com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:151)
>         at 
> com.opensymphony.xwork2.conversion.impl.DefaultTypeConverterCreator.createTypeConverter(DefaultTypeConverterCreator.java:23)
>         at 
> com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor.loadConversionProperties(DefaultConversionPropertiesProcessor.java:64)
>         at 
> com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor.process(DefaultConversionPropertiesProcessor.java:40)
>         at 
> com.opensymphony.xwork2.conversion.impl.XWorkConverter.setConversionPropertiesProcessor(XWorkConverter.java:179)
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>         at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>         at java.lang.reflect.Method.invoke(Method.java:606)
>         at 
> com.opensymphony.xwork2.inject.ContainerImpl$MethodInjector.inject(ContainerImpl.java:299)
>         at 
> com.opensymphony.xwork2.inject.ContainerImpl$ConstructorInjector.construct(ContainerImpl.java:438)
>         at 
> com.opensymphony.xwork2.inject.ContainerBuilder$5.create(ContainerBuilder.java:207)
> ...
>         at 
> com.opensymphony.xwork2.inject.ContainerBuilder$7.call(ContainerBuilder.java:484)
>         at 
> com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:584)
>         at 
> com.opensymphony.xwork2.inject.ContainerBuilder.create(ContainerBuilder.java:484)
>         at 
> com.opensymphony.xwork2.config.impl.DefaultConfiguration.createBootstrapContainer(DefaultConfiguration.java:324)
>         at 
> com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:221)
>         at 
> com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)
>         at 
> org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:446)
>         at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:490)
>         at 
> org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:74)
>         at 
> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(StrutsPrepareAndExecuteFilter.java:57)
>         at 
> org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:325)
>         at 
> org.springframework.web.filter.DelegatingFilterProxy.initFilterBean(DelegatingFilterProxy.java:235)
>         at 
> org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:194)
>         at 
> org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:295)
>         at 
> org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:422)
>         at 
> org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:115)
>         at 
> org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4072)
>         at 
> org.apache.catalina.core.StandardContext.start(StandardContext.java:4726)
>         at 
> org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
>         at 
> org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)
>         at 
> org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
>         at 
> org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:943)
>         at 
> org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:778)
>         at 
> org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:504)
>         at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1317)
>         at 
> org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:324)
>         at 
> org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
>         at 
> org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1065)
>         at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
>         at 
> org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
>         at 
> org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
>         at 
> org.apache.catalina.core.StandardService.start(StandardService.java:525)
>         at 
> org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
>         at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>         at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>         at java.lang.reflect.Method.invoke(Method.java:606)
>         at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
>         at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
> 10:20:07,074 INFO  [XmlConfigurationProvider] Parsing configuration file 
> [struts-default.xml]
> 10:20:07,159 INFO  [XmlConfigurationProvider] Parsing configuration file 
> [struts-plugin.xml]
> 10:20:07,663 INFO  [XmlConfigurationProvider] Parsing configuration file 
> [struts.xml]
> 10:20:07,674 INFO  [BeanSelectionProvider] Choosing bean (struts) for 
> (com.opensymphony.xwork2.FileManagerFactory)
> {noformat}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to