[jsr-314-open-mirror] [jsr-314-open] [2.1 Spec Review] UIData state saving
by Andy Schwartz
Gang -
I am reviewing the 2.1 Java API changes today. Decided to start with
UIData state saving. Comments on the doc for
UIData.setPreserveRowComponentState():
> When the markInitialState() method is called, save the state of the
> direct children
Is it just the direct children? Don't we need to save the state for
non-direct descendents as well? Should we mention that non-iterated
facets of UIData are excluded from this?
> of this instance by traversing them as if this component was a normal
> UIComponent instance, not a UIData, and calling
> saveState(javax.faces.context.FacesContext) on each, collecting the
> state as the traversal proceeds. State collected in this manner will
> be referred to as "rolled up" state. Store the resultant rolled up
> state in a data structure with a scope equivalent to that of an
> instance variable. This is necessary so that state can be restored
> without a dependency on any particular row value. For discussion, this
> rolled up state is called the "initial rolled up state".
Minor issue, but for some reason the term "rolled up state" doesn't seem
to be clicking for me. I think of this as the "full initial state" -
ie. we are doing a full state save to capture the initial state of these
components so that we can get back to this later.
>
> When setRowIndex(int) is called, the following additional actions must
> be taken before the usual call to setRowIndex(int).
Instead of "before the usual call to setRowIndex()", maybe "before any
other work is performed"? It isn't clear what "the usual call" means.
>
> Traverse the children as done with markInitialState(), saving the
> state of each child. Because the
> saveState(javax.faces.context.FacesContext) calls during this pass
> happen after the call to markInitialState(), the state saved is the so
> called "delta" state of each component.
What happens is partial state saving is disabled? Do we still implement
this behavior and just save/restore the full state, or do we bail on the
preserveRowComponentState behavior?
BTW, we don't need to perform this traversal if the current row index
(the row index at the point in time when setRowIndex() is called) is -1.
> Because this traversal happens during a per-row operation (in this
> case, setRowIndex(int)) the rolled up state
Okay, so I guess "rolled up" state != "full initial state" - more like
the per-row saved state.
> must be saved in a row-aware data structure. One implementation choice
> would be to save the state from this pass in a Map keyed by the return
> from UIComponent.getContainerClientId(javax.faces.context.FacesContext).
Though this might not work well if we need to save state for subtrees as
opposed to only direct children - ie. might be better to use the full
client id. Perhaps we should leave this implementation suggestion out?
> It is permissible for the rolled up state to be null or empty.
>
> If the current row index is not -1, traverse the children as in the
> previous step,
Do we need to perform two separate traversals? Woudn't it be more
efficient to consolidate these into a single traversal?
> but, instead of calling saveState(javax.faces.context.FacesContext),
> call UIComponent.saveTransientState(javax.faces.context.FacesContext).
> Save the rolled up state in a separate row-aware data structure from
> the one used in the preciding
preceding (sp)
> step.
>
> Call DataModel.setRowIndex(int) on the model, as normal. Store the row
> data as request scope attributes, as normal.
>
> If the rolled up state saved during the call to markInitialState() is
> not null or empty,
Since this is the "initial rolled up state" - ie. the full state,
wouldn't this be non-null?
I am mostly asking just because I want to make sure I understand how
this all fits together. The reference to null/empty state makes me
think that this might be partial state, but I believe we are dealing
with full state here.
> perform the reverse of the two save operations, as described next.
> This is necessary to indicate that transient state from the previous
> row must be discarded, in order to not pollute the state of the
> current row.
>
> If the per-row state saved in step a. above is null, traverse the
> children and restore the child state using the initial rolled up state.
Does the "per-row state saved in step a. above" refer to the stave saved
for the row that we are leaving? Or for the state that we saved the
last time that visited the current row?
That is, if we are on row 1 and setRowIndex(2) is called, does the
"per-row state saved in step a" mean the state produced for row 1 before
we adjusted the index, or the state that we previously saved away the
last time we visited row 2?
This is important to specify clearly.
>
> If the per-row state saved in step a. above is not null, traverse the
> children and restore the child state using the state saved during step
> a., using the initial rolled up state only as a backup in the case
> that per-row state is not available.
Okay, so I guess that "per-row state saved in step a. above" refers to
the previously saved state for the current row. However, since this is
delta state, before we apply this isn't it necessary to first restore
the components to their initial state by restoring the full initial
saved state? If we don't restore the components to their initial state
before applying the delta state, won't we run the risk that state from
the previous row might bleed over into the current row? (In the case
where the state from the previous from was null, this won't be an issue.)
Also, at some point is it necessary to tell the StateHelper that it
needs to clear out any previously saved deltas so that it can start
tracking deltas for the currently active row? Or does that happen
implicitly at some point, eg. when we restore the row state?
>
> If the current row index is -1, traverse the children and pass null to
> UIComponent.restoreTransientState(javax.faces.context.FacesContext,
> java.lang.Object).
Hopefully we can consolidate the restore-related traversals as well.
>
> If the current row index is not -1, take the following actions.
>
> If the per-row state saved in step b. above is null, traverse the
> children and restore the transient state by passing null to each
> child's
> UIComponent.restoreTransientState(javax.faces.context.FacesContext,
> java.lang.Object) method
>
> If the per-row state saved in step b. above is not null, traverse the
> children and restore the transient state from the state saved in step
> b. above, calling
> UIComponent.restoreTransientState(javax.faces.context.FacesContext,
> java.lang.Object) on each child, and passing the appropriate state.
Sounds like we are doing the same thing whether or not the transient
state is null, so perhaps we can simplify the wording.
Few other questions:
1. Leonardo raised an issue regarding the timing of when
markInitialState() is called - ie. that markInitialState() needs to be
called on the parent before the children - otherwise UIData won't be
able to capture the full initial state of its children. How did we
solve this problem? Are there spec changes relating to this? Did we
find a way to do this that doesn't require introducing yet another full
tree traversal?
2. Regarding the name of the new property...
is/setPreserveRowComponentState() is a bit of a mouthful. Could we
maybe shorten this to is/setRowStatePreserved()?
3. Are there cases where it might be useful to enable per-row transient
state saving without also enabling non-transient state saving (which
seems more expensive)? I wonder whether it should be possible to enable
these independently, in which case we may want to consider using an enum
property instead of a boolean. Also wondering whether transient row
state saving should just be on by default or possibly always on.
Andy
14 years, 1 month
[jsr-314-open-mirror] [jsr-314-open] composite:attribute "targets" property does not match with ViewDeclarationLanguage.retargetMethodExpressions
by Leonardo Uribe
Hi
Some days ago, it was mentioned on myfaces dev list that "targets"
attribute does not seem to work as expected. After review the available
documentation and doing some test, my conclusion was the spec is good,
but this part needs a little bit more documentation (and fix some
bugs), because there are use cases that are causing problems to users.
Some of these problems has been already mentioned (spec issue 755) but
my intention here is do a full and detailed analysis.
The property "targets" is used for these tags:
composite:actionSource
composite:editableValueHolder
composite:valueHolder
composite:clientBehavior
composite:attribute
For the first four cases, this property is used by :
ViewDeclarationLanguage.retargetAttachedObjects(FacesContext context,
UIComponent topLevelComponent,
List<AttachedObjectHandler> handlers)
In JSF 2.0 rev A it was made explicit the need to handle nested
composite component with this lines:
"... The implementation must support retargeting attached objects from
the top level compsite component to targets that are composite and
non-composite components ...."
This is ok ;-).
The problem is the description about how composite:attribute "targets"
property works does not match with the algorithm for:
ViewDeclarationLanguage.retargetMethodExpressions(FacesContext context,
UIComponent topLevelComponent)
Here is the documentation about composite:attribute "targets":
"... If this element has a method-signature attribute,
the value of the targets attribute must be interpreted as a space
(not tab) separated list of client ids (relative to the top level
component) of components within the <composite:implementation> section.
Space is used as the delimiter for compatibility with the IDREFS and
NMTOKENS data types from the XML Schema.
Each entry in the list must be interpreted as the id of an inner
component to which the MethodExpression from the composite component
tag in the using page must be applied.
If this element has a method-signature attribute, but no targets
attribute, the value of the name attribute is used as the single entry
in the list.
If the value of the name attribute is not one of the special values
listed in the description of the name attribute, targets (or its
derived value) need not correspond to the id of an inner component ...".
At this point everything seems to be ok. But look this documentation
(I'll put the important points):
".....
# Get the value of the targets attribute. If the value is a ValueExpression
evaluate it. If there is no targets attribute, let the name of the
metadata element be the evaluated value of the targets attribute.
# Interpret targets as a space (not tab) separated list of ids. For each
entry
in the list:
......
# If name is equal to the string "action" without the quotes, call
ActionSource2.setActionExpression(javax.el.MethodExpression) on
target,
passing attributeMethodExpression.
# If name is equal to the string "actionListener" without the quotes,
call
ActionSource.addActionListener(javax.faces.event.ActionListener) on
target,
passing attributeMethodExpression wrapped in a
MethodExpressionActionListener.
# If name is equal to the string "validator" without the quotes, call
EditableValueHolder.addValidator(javax.faces.validator.Validator) on
target,
passing attributeMethodExpression wrapped in a
MethodExpressionValidator.
# If name is equal to the string "valueChangeListener" without the
quotes, call
EditableValueHolder.addValueChangeListener(javax.faces.event.ValueChangeListener)
on target, passing attributeMethodExpression wrapped in a
MethodExpressionValueChangeListener.
# Otherwise, assume that the MethodExpression should be placed in the
components attribute set. The runtme must create the MethodExpression
instance based on the value of the "method-signature" attribute.
....."
My first interpretation of this javadoc was that "targets" only has sense
for "action",
"actionListener", "validator" and "valueChangeListener". But note if that's
true,
someone could expect something like the description on
retargetAttachedObjects, right?
The current behavior (Mojarra 2.0.3 and Myfaces 2.0.2) is the same, if we
have two
nested composite components, that will throw a ClassCastException. There is
a issue already
open for this one:
https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=755
There are two possible alternatives here:
1. Implement the algorithm proposed for retargetMethodExpressions and
ignore
composite:attribute "targets" property says.
2. Implement the expected behavior of composite:attribute "targets"
property and make
some changes to retargetMethodExpressions algorithm.
The intention is take option 2 and include it for JSF 2.0, because in theory
should be
handled as an implementation detail of the algorithm (anyway it could be
good to update
the documentation with the same advice used for retargetAttachedObjects).
For "action", "actionListener", "validator" and "valueChangeListener" it is
clear that
the action to take is something like this:
- If target is a composite component and that one "retarget" to other
components and
additionally does not implements [ActionSource2/EditableValueHolder],
call:
targetComponent.getAttributes().put(attributeName,
attributeNameValueExpression);
and call retargetMethodExpressions recursively. Take care of apply the
method twice
and if the property pointed by "attributeName" was already set, revert
its effects.
The tricky part is how to handle generic method expression properties. The
javadoc says:
"....
# Otherwise, assume that the MethodExpression should be placed in the
components attribute set. The runtme must create the MethodExpression
instance based on the value of the "method-signature" attribute.
....."
But I have identified three valid cases:
1. testSimpleAttributeMethodExpressionEmpty.xhtml (Using an EL #{cc}
reference)
<testComposite:simpleAttributeMethodExpressionEmpty id="cc1"
customMethod="#{methodExpressionBean.doSomethingFunny}">
</testComposite:simpleAttributeMethodExpressionEmpty>
simpleAttributeMethodExpressionEmpty.xhtml
<composite:interface>
<composite:attribute
name="customMethod"
method-signature="String doSomething(String)"/>
</composite:interface>
<composite:implementation>
<tc:testComponent id="testComponent"
customMethod="#{cc.attrs.customMethod}"/>
</composite:implementation>
2. testSimpleAttributeMethodExpressionTarget.xhtml (Using "targets" to call
a property setter directly)
<testComposite:simpleAttributeMethodExpressionTarget id="cc1"
customMethod="#{methodExpressionBean.doSomethingFunny}">
</testComposite:simpleAttributeMethodExpressionTarget>
simpleAttributeMethodExpressionTarget.xhtml
<composite:interface>
<composite:attribute
name="customMethod"
method-signature="String doSomething(String)"
targets="testComponent"/>
</composite:interface>
<composite:implementation>
<tc:testComponent id="testComponent"/>
</composite:implementation>
3. testCompositeAttributeMethodExpressionTarget.xhtml (Using "targets",
but the target component is a composite one)
<testComposite:compositeAttributeMethodExpressionTarget id="cc1"
customMethod="#{methodExpressionBean.doSomethingFunny}">
</testComposite:compositeAttributeMethodExpressionTarget>
compositeAttributeMethodExpressionTarget.xhtml
<composite:interface>
<composite:attribute
name="customMethod"
method-signature="String doSomething(String)"
targets="simpleAttributeMethodExpressionTarget"/>
</composite:interface>
<composite:implementation>
<testComposite:simpleAttributeMethodExpressionTarget
id="simpleAttributeMethodExpressionTarget"/>
</composite:implementation>
simpleAttributeMethodExpressionTarget.xhtml (could be like in 1 or 2)
The case (1) actually works but the case (2) and (3) does not work on both
MyFaces 2.0.2 and Mojarra 2.0.3 .
I have created an issue on MyFaces here:
https://issues.apache.org/jira/browse/MYFACES-2946
a attached a working patch too if you want to take a look at it:
https://issues.apache.org/jira/secure/attachment/12457512/MYFACES-2946-1....
Suggestions are welcome
regards,
Leonardo Uribe
14 years, 1 month
[jsr-314-open-mirror] [jsr-314-open] [490-XmlViews] Chapter 11: The JSF XML View Syntax
by Andy Schwartz
Ed, All -
I have finally started reviewing the pdf, including the new chapter 11:
"The JSF XML View Syntax". Unfortunately, while reviewing this chapter
I felt very lost.
The chapter opens with:
> As of version 2.1 of this specification, JavaServer Faces
> implementations must support (although JSF-based applications need not
> utilize) using plain XML as a View Declaration Language (VDL).
I didn't realize that we were introducing a new VDL. I thought that our
efforts have been focused on allowing the existing Facelets VDL to be
more XML-friendly by providing control over XML processing behavior.
> The main difference between using XML as a VDL and using Facelets is
> that the XML syntax does not support HTML template text. In other
> words, every element in a facelets XML page must be a JSF UI
> component. There is no facility for automatically generating transient
> UIComponent instances from template text. If you want this facility,
> use Facelets as your VDL.
The differences that we have been discussing between legacy
xhtml-centric Facelets and the new xml-centric approach are related to
processing of XML-centric constructs such as CDATA blocks, XML
declarations, processing instructions, etc... I didn't realize that we
would also be changing how HTML template text/tags were handled. If
this means that you cannot use HTML elements in the new XML views, my
guess is that nobody will be interested in adopting this approach.
> First note the outer-most <faces-view> element. In Facelets, the
> outer-most element is normally the <html> element. In Facelets, the
> <html> element is where the taglibs used in the page are declared. In
> the Faces XML VDL, the <faces-view> element is the outer-most element
> and here is where the taglibs used are declared.
One small but important feature that folks seemed to like about Facelets
is that it made the <f:view> optional. If we now require a new
top-level element, my guess is that many people will find this to be a
step backwards.
I find section 11.2, "Java Programming Language Specification for Faces
XML Views" to be overly detailed and difficult to read, eg:
> Each element in the XML view falls into one of the following
> categories, each of which corresponds to an instance of a Java object
> that implements javax.faces.view.facelets.FaceletHandler, or a
> subinterface or subclass thereof, and an instance of
> javax.faces.view.facelets.TagConfig, or a subinterface or subclass
> thereof, which is passed to the constructor of the object implementing
> FaceletHandler.The mapping between the categories of elements in the
> XML view and the appropriate subinterface or subclass of
> FaceletHandler is specified below. Each FaceletHandler instance must
> be traversed and its apply() method called in the same depth-first
> order as in the other lifecycle phase methods in jsf. Each
> FaceletHandler instance must use the getNextHandler() method of the
> TagConfig instance passed to its constuctor to perform the traversal
> starting from the root FaceletHandler.
I am surprised that we need to go into this level of detail. Perhaps
the problem is that I am not a JSF implementor and as such I don't
appreciate why this sort of detail is necessary. I also worry that this
is information that must be available elsewhere (eg. for the Facelets
VDL), in which case we don't have a single source of truth.
Could the MyFaces guys comment on whether this level of detail in
section 11.2 is helpful to you as JSF implementors?
The big picture problem that I have with the information in chapter 11
is that I do not understand how this relates to xhtml/xml/facelets
processing mode that we have been discussing in detail over the last few
weeks. I did not realize that a new VDL was necessary. I thought that
our focus was on configuring how Facelets processes documents that are
mapped to the Facelets VDL.
I would prefer that we focus on the approach that is currently outlined
in Apendix A, section 1.2.1.1 ("The facelets-processing element") and
avoid introducing a new VDL as described in chapter 11.
BTW, if we are introducing a new VDL, one thing that is missing is any
mention of how to map views to this VDL - ie. there is no equivalent of
the javax.faces.FACELETS_VIEW_MAPPINGS. Though based on the concerns
that Leonardo raised on our other active thread, rather than introduce
additional context parameters for this sort of thing, we should look
into a generic faces-config-based VDL registration mechanism.
Andy
14 years, 1 month
[jsr-314-open-mirror] [jsr-314-open] Enhance conversion model is required because UIInput.submittedValue returns Object, but Converter suggest only String is allowed
by Leonardo Uribe
Hi
This issue has been posted on spec issue tracker:
https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=888
The current conversion model is not good enough on some cases when it
is required the submitted value be something different than String, or on
more complex components that requires to send information from multiple html
"input" components.
This issue has been discussed earlier on myfaces list, as you can
see on the comments at the end of this mail:
To understand what's missing, I'll resume how the current conversion model
works.
This could be redundant, but the intention is expose the reasons about why
it is
wanted to extend the current model in a understandable way.
Every component that is used as a input has at least one "value binding" to
a bean.
In UIInput, the user just set "value" property with an EL expression to
indicate that the value sent should be assigned to that expression.
Now suppose a form with this component that is submitted. The input
component
should first create the "submittedValue" from the information available on
request parameter map. This is done on UIComponent or Renderer decode()
method.
Then, this value is converted to the type required by the "value binding",
through
Converter interface and later, if conversion fails by some reason, the
information
stored on "submittedValue" will be used to render the component later.
Therefore, "submittedValue" must satisfy three conditions:
1. It should contain all info sent by the component through request
parameter map,
otherwise the renderer will not be able to render the component
correctly.
2. It should be on a way that can be converted to the type indicated by
"value binding",
that means the submittedValue type should be a public class, so the
renderer can
instantiate it and conversion model can process it.
3. The component should be responsible to define the type used by
submitted value,
according to its needs.
Now, let's take a look at the current Converter interface:
public interface Converter
{
/**
* used to map the submittedValue to the "value binding".
*/
Object getAsObject(FacesContext context,
UIComponent component,
String value) throws ConverterException;
/**
* used to convert the "value binding" into a String to be used
* on the renderer.
*/
String getAsString(FacesContext context,
UIComponent component,
Object value) throws ConverterException;
}
Note that JSF provide some converters for the most common types, so the user
can
specify which converter use or let JSF decide which one fits best, using
the converters registered with "forClass" mapping. Yes, that's ok, but only
for
components with only one "<input>". In that case, assume String as submitted
value type looks better and keep things simple.
Things start to get confusing when you see the signature of
UIInput.getSubmittedValue():
public Object getSubmittedValue()
Does the conversion model did not make the assumption that String is the
only type to
be used by submittedValue?
But this assumption fails when a more complex component is required. The
typical
example is a component that handles date/time values. In that case, the
date/time value
can be decomposed into its elements (year, month, day, hour, minutes ....).
In this case, a component developer could want to send all that info into
multiple
"<input>" parameters through request parameter map. So, to use the model
proposed,
all that information should be used to encode a String, just to later decode
it on
the converter used to construct the "value binding" required, but later it
will be
decoded/encoded by the renderer again to render the component.
The proposal to put into consideration is do the following modifications on
jsf:
- Add a class called BusinessConverter (maybe you can find other name but
for now let
it as is) :
public interface BusinessConverter
{
public Object getBusinessValue(FacesContext context,
UIComponent component,
Object submittedValue);
public Object getAsSubmittedValue(FacesContext context,
UIComponent component,
Object value);
}
Really is similar to Converter interface but does not force submittedValue
to be String,
instead it lets it open.
- Add the following methods to Application class :
public abstract void addBusinessConverter(Class<?> submittedClass,
Class<?> targetClass,
String converterClass);
public abstract void addBusinessConverter(String businessConverterId,
String
businessConverterClass);
public abstract Converter createBusinessConverter(Class<?>
submittedClass,
Class<?> targetClass);
public abstract Converter createBusinessConverter(String
businessConverterId);
public abstract Iterator<String> getBusinessConverterIds();
public abstract Iterator<Class<?>> getBusinessConverterTypes(Class<?>
submittedClass);
Again, it is similar to converter methods on Application class, but in this
case it takes
into consideration the submittedClass. Therefore, a component that define as
submittedClass
java.util.Date, could retrieve the converters that can handle this
conversion. From some
point of view, the current Converter interface is a particular case when
submittedClass is
java.lang.String.
- Add the following methods to UIOutput class :
public BusinessConverter getBusinessConverter();
public void setBusinessConverter(BusinessConverter converter);
/**
* Return the value type the submitted value will take on
* decode() method. In my opinion, allow just one submittedValueType is
* enough.
*/
public Class<?> getSubmittedValueClass();
The idea is provide a way to configure business converter, just like
Converter.
Note this implies change some stuff on UIInput too.
- Add an annotation @FacesBusinessConverter.
- Add a component f:businessConverter in the same way as f:converter.
I would like to put into consideration this idea. My personal opinion is
this should be
included at the spec level for two reasons:
- It is clear there is a contradiction between UIInput.getSubmittedValue()
and
Converter interface.
- It could be good to have a common repository for business converters, and
use JSF
annotations to register it.
I have some code I'm working but it is better to know if you think it is
worth or
not before continue. If it is necessary I can help with the implementation.
Suggestions are welcome
best regards,
Leonardo Uribe
Note: As an historical comment, currently, Trinidad has a workaround for
handle
handle "oracle types", from the binding layer, using an interfaces called
TypedConverter as you can see below:
package org.apache.myfaces.trinidadinternal.convert;
public interface TypeConverter
{
/**
* converts the given Object into an instance of the
* targetType.
* @return an instance of the targetType.
*/
Object convert(Object source, Class<?> targetType);
}
The idea behind this interface is provide a way that trinidad can
"understand"
specific types and include them when are resolved, but note this class is
not
part of trinidad api. The reason is this is just an internal workaround.
COMMENTS FROM OTHER PEOPLE SUPPORTING THIS ISSUE:
Martin Koci
MK>> maybe this is a stupid question but:
MK>>
MK>> >From UIInput javadoc:
MK>>
MK>> ... decoded value of this component, usually but >>>not necessarily a
MK>> String<<<, must be stored - but not yet converted - using
MK>> setSubmittedValue() ....
MK>>
MK>> from UIInput.getConvertedValue:
MK>>
MK>> ... and the submitted value is a >>>String<<<, locate a Converter as
MK>> follows
MK>>
MK>> Question: why is Converter tied only to String? Whole specification
MK>> speaks about submitted value as of "raw representation of value from
MK>> client" but not necessarily String. And 3.3 Conversion Model: "This
MK>> section describes the facilities provided by JavaServer Faces to
support
MK>> type conversion between server-side Java objects and their (typically
MK>> String-based) representation in presentation markup."
MK>> But Converter.getAsObject expects only String as this "raw
MK>> representation" and "typically String-based" formulation from spec now
MK>> means "always String-based".
MK>> It seems to me that Converter introduces unnecessary dependency on
MK>> String-based representation - even ResponseWriter.write* accepts
MK>> java.lang.Object as value ....
MK>>
MK>> What I try to do is JSF-based server view with custom NOT-string based
MK>> protocol where "raw representations from client" can be java object
like
MK>> Integer or more complex. Creating of:
MK>>
MK>> interface Converter2 {
MK>> Object getAsObject(FacesContext,UIComponent,Object)
MK>> Object getAsRepresentation(FacesContext,UIComponent,Object)
MK>> }
MK>>
MK>> solves my problem but I must reprogram significant part of JSF api.
Martin Marinschek
MM>> MK>> So on JSF level conversion String <-> Object is unable to solve
this
MM>> MK>> problem - I simply need Object <-> Object conversion which is not
MM>> MK>> supported yet.
MM>>
MM>> Yes, this is true - this is obviously a spec problem.
MM>>
MM>> If the submitted value is an object, it should also be allowed to
MM>> convert it. A converter is more than just a string to object (and
MM>> back) converter, it is an artefact which transforms information from
MM>> its representation for output (and this output could be anything, and
MM>> certainly doesn't have to be string based) to its representation which
MM>> the business model (or also an artefact within JSF, like a validator)
MM>> understands.
MM>>
MM>> So I agree. This hasn't come up so far cause nobody uses non string
MM>> based output models for JSF.
MM>>
MM>> Note that my notion of a business converter (discussed on this mailing
MM>> list a while ago) for converting between a business model
MM>> representation and a representation in a JSF artefact like the
MM>> renderer (e.g. you use joda.Date in the business model, but the JSF
MM>> date picker renderer only understands the normal java date) is also
MM>> hinting in the direction that such an additional converter API would
MM>> be necessary. I discussed this with the EG (and also Ed privately),
MM>> and there wasn't much interest for adding this.
14 years, 1 month