spring-projects / spring-webflow

Spring Web Flow
https://spring.io/projects/spring-webflow
Apache License 2.0
329 stars 233 forks source link

FlowBuilderContextImpl does not use custom conversionService [SWF-1395] #564

Open spring-operator opened 14 years ago

spring-operator commented 14 years ago

Alberto Mozzone opened SWF-1395 and commented

Why can't I inject a custom "ConversionService" into "FlowBuilderContextImpl"? (more in comments)


Affects: 2.0.8

spring-operator commented 14 years ago

Alberto Mozzone commented

I'm customizing JaSig CAS. I need to add a custom converter in my flow, so I added a "binder" in one of the "view-state":

<binder>
  <binding property="username" />
  <binding property="password" />
  <binding property="userType" converter="userTypeConverter" />
</binder>

Then I modified "cas-servlet.xml":

<webflow:flow-builder-services id="builder" view-factory-creator="viewFactoryCreator" conversion-service="myCustomConversionService" />

In this way, my converters (added in my custom conversion service, which inherits "org.springframework.binding.convert.service.DefaultConversionService") are never called. Google pointed me to this thread: even if I use 2.0.8, I tried the workaround doing this:

  <webflow:flow-builder-services id="builder" view-factory-creator="viewFactoryCreator" conversion-service="myCustomConversionService" expression-parser="myCustomExpressionParser" />

  <bean id="myCustomExpressionParser" class="org.springframework.webflow.expression.WebFlowOgnlExpressionParser">
    <property name="conversionService" ref="myCustomConversionService" />
  </bean>

I discovered which "ExpressionParser" implementation to use by debuggging: initially I used "WebFlowELExpressionParser", but the default SWF uses is "WebFlowOgnlExpressionParser" (which does not require any argument in construction).

After this modification, the problem persists. Debugging the code I see that the constructor of "FlowBuilderContextImpl" does not get the conversion service from "FlowBuilderServices" but creates and uses a "GenericConversionService". Afterwards, I arrive in "LocalFlowBuilderContext.getConversionService()" which does this:

if (localFlowContext.containsLocalBean("conversionService")) {
     return (ConversionService) localFlowContext.getBean("conversionService", ConversionService.class);
} else {
     return parent.getConversionService();
}

Here, the code always goes in the second "return" and it always returns the "GenericConversionService".

At this point I've got two questions: 1) why does "parent.getConversionService()" always return the "GenericConversionService" and never return "MyCustomConversionService"? 2) why a conventional "conversionService" bean is searched? After all, I can inject my custom converter in the "webflow:flow-builder-services" element.

When I create a "conversionService" bean, Spring bombs with

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'conversionService' must be of type [org.springframework.core.convert.ConversionService], but was actually of type [mypack.MyCustomConversionService]

Google brought me to this question: I don't have any "mvc:annotation-driven" element, but I think I will do (and so I'll have to make them coexist).

Maybe I understood nothing of SWF, but these are problems I never had with SWF 1 (I had others ;)). If I'm wrong, please point me to the right direction. If I'm right, please provide a workaround or a solution (I could also contribute, if it's possible).

Thanks for your attention.

spring-operator commented 14 years ago

Alberto Mozzone commented

Whoops! It seems that text formatting isn't with us...

spring-operator commented 14 years ago

Rossen Stoyanchev commented

Have you tried upgrading to Spring Web Flow 2.1 or 2.2 where the FlowBuilderContextImpl re-uses the converters registered through the FlowBuilderServices (see changes in https://fisheye.springsource.org/browse/spring-webflow/branches/spring-webflow-2.2-maintenance/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderContextImpl.java?r1=2523&r2)?

spring-operator commented 14 years ago

Alberto Mozzone commented

Hi Rossen! What's the issue that made you change the code? If the new version resolves the problem I can try to tell our customer that I've got to upgrade CAS. Otherwise (or if I cannot upgrade), I'll stick with this workaround: do not use any ConversionService and get/set the "userType" manually in Actions.

I'll try in a few days.

FYI: CAS 3.4.3 actually uses SWF "2.1.1.RELEASE", while I started with 3.4.2.1.

Thanks for your suggestion.

spring-operator commented 14 years ago

Rossen Stoyanchev commented

The change was made as part of work done to integrate the Spring 3 type conversion into Spring Web Flow (see #440 for more details). Let me know if this resolves the issue. Note that named converters as shown in the original comment above (converter="userTypeConverter") are not supported in Spring's type conversion. They're still supported in Web Flow (through Web Flow's type conversion system) but are effectively deprecated. The idea is Spring's type conversion system, which makes use of generics should be able to figure out what converter is needed for a given a source and target type pair.