You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Bart Kummel <ba...@kummelweb.nl> on 2009/03/21 12:41:00 UTC

Custom converter: attributes not set?

Hi,

I'm trying to write a custom converter that converts the casing of text.
Therefor I want a "type" attribute that let's me choose if I want to convert
to lower case, UPPER CASE or Title Case. This is what I've done so far:

*Created converter class*
I've created a class, CaseConverter.java:
package my.company.conversion;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;

public class CaseConverter implements Converter {
    private String type = "lower";

    public Object getAsObject(FacesContext context, UIComponent component,
String string) {
        String result = "";
        if ("upper".equals(getType())){
            return string.toUpperCase();
        } else if ("title".equals(getType())) {
            return toTitleCase(string);
        } else {
            return string.toLowerCase();
        }
        return result;
    }

    private String toTitleCase(String string){
        // left out for brevity
    }

    public synchronized String getAsString(FacesContext context, UIComponent
component, Object object) {
        return object.toString();
    }

    public void setType(String type) {
        if (type != null) {
            this.type = type.toLowerCase();
        }
    }

    public String getType() {
        return type;
    }
}

*Registered converter in faces-config.xml*
As follows:
  <converter>
    <description>Case converter for text values</description>
    <converter-id>convertCase</converter-id>
    <converter-class>my.company.conversion.CaseConverter</converter-class>
  </converter>

*Added to Facelets taglib*
I already had a my.taglib.xml file for some composition components, so I
added my converter there:
  <tag>
    <tag-name>convertCase</tag-name>
    <converter>
      <converter-id>convertCase</converter-id>
    </converter>
  </tag>

*Used the converter in a page*
I added the converter to a page, like this:
          <my:field id="jobTitle" bean="#{pageFlowScope.selectedEmployee}" >
            <my:convertCase type="title"/>
          </my:field>
The <my:field> component is a Facelets Composition Component, defined as
follows:
<ui:composition>
  <c:if test="#{empty autoComplete}">
    <c:set var="autoComplete" value="on" />
  </c:if>

  <c:if test="#{empty simple}">
    <c:set var="simple" value="false" />
  </c:if>

  <!-- This is a work around for bug TRINIDAD-1390. -->
  <c:if test="#{empty maximumLength}">
    <c:if test="#{columns gt 1}">
      <c:set var="maximumLength" value="2147483647" />
    </c:if>
  </c:if>

  <!-- This is a work around for bug TRINIDAD-1417. -->
  <c:if test="#{not empty partialTriggers}">
    <c:set var="partialTriggers"
value="#{my:getStringArray(partialTriggers)}" />
  </c:if>

  <tr:inputText value="#{bean[id]}" id="#{id}" required="#{required}"
readOnly="#{readOnly}"
                label="#{msg[id]}:" secret="#{secret}"
maximumLength="#{maximumLength}" columns="#{columns}"
                rows="#{rows}" wrap="#{wrap}" autoComplete="#{autoComplete}"
simple="#{simple}"
                partialTriggers="#{partialTriggers}" >
    <ui:insert/>
  </tr:inputText>
</ui:composition>

*Versions used:*
Apache MyFaces 1.2.4
Apache MyFaces Trinidad 1.2.10
Facelets 1.1.14

*Problem description:
*Everything works fine, except that the method setType() is only called
before a call to getAsString(). I figured out that:

   - Everytime the converter is needed, a new instance of the class is
   constructed.
   - Before every call to getAsString() the setType() is called with the
   value set in the tag attribute ("title" in this case).
   - Before a call to getAsObject() the setType() method is *not *called.
   This causes the strings to always be converted to lower case, which is de
   default.

Is this normal behaviour? What should I do to get it right? I hope someine
can help...

Best regards,
Bart Kummel

Re: Custom converter: attributes not set?

Posted by Matthias Wessendorf <ma...@apache.org>.
you have to implement stateholder interface:
http://myfaces.apache.org/core12/myfaces-api/apidocs/javax/faces/component/StateHolder.html

like here, for instance:
http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/api/src/main/java/javax/faces/convert/DateTimeConverter.java?view=markup
http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/api/src/main/java/javax/faces/convert/NumberConverter.java?view=markup

-Matthias

On Sat, Mar 21, 2009 at 12:41 PM, Bart Kummel <ba...@kummelweb.nl> wrote:
> Hi,
>
> I'm trying to write a custom converter that converts the casing of text.
> Therefor I want a "type" attribute that let's me choose if I want to convert
> to lower case, UPPER CASE or Title Case. This is what I've done so far:
>
> Created converter class
> I've created a class, CaseConverter.java:
> package my.company.conversion;
>
> import javax.faces.component.UIComponent;
> import javax.faces.context.FacesContext;
> import javax.faces.convert.Converter;
>
> public class CaseConverter implements Converter {
>     private String type = "lower";
>
>     public Object getAsObject(FacesContext context, UIComponent component,
> String string) {
>         String result = "";
>         if ("upper".equals(getType())){
>             return string.toUpperCase();
>         } else if ("title".equals(getType())) {
>             return toTitleCase(string);
>         } else {
>             return string.toLowerCase();
>         }
>         return result;
>     }
>
>     private String toTitleCase(String string){
>         // left out for brevity
>     }
>
>     public synchronized String getAsString(FacesContext context, UIComponent
> component, Object object) {
>         return object.toString();
>     }
>
>     public void setType(String type) {
>         if (type != null) {
>             this.type = type.toLowerCase();
>         }
>     }
>
>     public String getType() {
>         return type;
>     }
> }
>
> Registered converter in faces-config.xml
> As follows:
>   <converter>
>     <description>Case converter for text values</description>
>     <converter-id>convertCase</converter-id>
>     <converter-class>my.company.conversion.CaseConverter</converter-class>
>   </converter>
>
> Added to Facelets taglib
> I already had a my.taglib.xml file for some composition components, so I
> added my converter there:
>   <tag>
>     <tag-name>convertCase</tag-name>
>     <converter>
>       <converter-id>convertCase</converter-id>
>     </converter>
>   </tag>
>
> Used the converter in a page
> I added the converter to a page, like this:
>           <my:field id="jobTitle" bean="#{pageFlowScope.selectedEmployee}" >
>             <my:convertCase type="title"/>
>           </my:field>
> The <my:field> component is a Facelets Composition Component, defined as
> follows:
> <ui:composition>
>   <c:if test="#{empty autoComplete}">
>     <c:set var="autoComplete" value="on" />
>   </c:if>
>
>   <c:if test="#{empty simple}">
>     <c:set var="simple" value="false" />
>   </c:if>
>
>   <!-- This is a work around for bug TRINIDAD-1390. -->
>   <c:if test="#{empty maximumLength}">
>     <c:if test="#{columns gt 1}">
>       <c:set var="maximumLength" value="2147483647" />
>     </c:if>
>   </c:if>
>
>   <!-- This is a work around for bug TRINIDAD-1417. -->
>   <c:if test="#{not empty partialTriggers}">
>     <c:set var="partialTriggers"
> value="#{my:getStringArray(partialTriggers)}" />
>   </c:if>
>
>   <tr:inputText value="#{bean[id]}" id="#{id}" required="#{required}"
> readOnly="#{readOnly}"
>                 label="#{msg[id]}:" secret="#{secret}"
> maximumLength="#{maximumLength}" columns="#{columns}"
>                 rows="#{rows}" wrap="#{wrap}" autoComplete="#{autoComplete}"
> simple="#{simple}"
>                 partialTriggers="#{partialTriggers}" >
>     <ui:insert/>
>   </tr:inputText>
> </ui:composition>
>
> Versions used:
> Apache MyFaces 1.2.4
> Apache MyFaces Trinidad 1.2.10
> Facelets 1.1.14
>
> Problem description:
> Everything works fine, except that the method setType() is only called
> before a call to getAsString(). I figured out that:
>
> Everytime the converter is needed, a new instance of the class is
> constructed.
> Before every call to getAsString() the setType() is called with the value
> set in the tag attribute ("title" in this case).
> Before a call to getAsObject() the setType() method is not called. This
> causes the strings to always be converted to lower case, which is de
> default.
>
> Is this normal behaviour? What should I do to get it right? I hope someine
> can help...
>
> Best regards,
> Bart Kummel
>



-- 
Matthias Wessendorf

blog: http://matthiaswessendorf.wordpress.com/
sessions: http://www.slideshare.net/mwessendorf
twitter: http://twitter.com/mwessendorf