Mon contexte technique est le suivant : JSF 1.2 (myfaces) + Tomahawk12 + Facelets 1.0 je n'ai bien entendu pas le droit d'utiliser la sandbox de myfaces.
L'utilisation d'un custom converter via le tag <f:converter id="myConverterId"/> ne permet pas d'envoyer un paramètre au converter.
Mon cas : Créer un converter permettant de tronquer une chaine de caractères à une longueur définie directement dans ma page.
Seulement 3 étapes et 10 minutes sont nécessaires :
_ Créer la classe du converter
_ Créer un custom tag via Facelet mapé sur ce converter
_ Créer sa page
1 - Créer la classe
Cet article n'étant pas un totu sur les converters, je vais me concentrer sur ce qui nous intéresse : le paramétrage.
Créez votre converter "as usual" et offrez lui en plus les 2 choses suivantes :
_ le/les paramètre(s) : propriété privée avec accesseurs publics
private Integer maxSize = -1;
_ une propriété statique nommée CONVERTER_ID
public static final String CONVERTER_ID = "maxLengthConverter";
C'est tout, votre classe ressemble à ça :
public class MaxLengthConverter implements Converter{
public static final String CONVERTER_ID = "maxLengthConverter";
static final Logger logger =
LoggerFactory.getLogger(MaxLengthConverter.class.getName());
protected boolean _transcient;
private Integer maxSize = -1;
/*
* (non-Javadoc)
* @see
* javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext
* , javax.faces.component.UIComponent, java.lang.String)
*/
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2)
throws ConverterException
{
String val = (String) arg2;
if (maxSize>0 && val.length() > maxSize)
{
val = val.substring(0, maxSize) + "...";
}
return val;
}
/*
* (non-Javadoc)
* @see
* javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext
* , javax.faces.component.UIComponent, java.lang.Object)
*/
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2)
throws ConverterException
{
if (arg2 instanceof String)
{
String val = (String) arg2;
if (maxSize>0 && val.length() > maxSize)
{
val = val.substring(0, maxSize) + "...";
}
return val;
}
else
{
logger.error("La valeur passée au converter n'est pas une String.");
ConverterException expt =
new ConverterException(
new ClassCastException(
"MaxLengthConverter n'accepte que des String en paramètre."));
throw expt;
}
}
/**
* Accesseur de maxSize
*
* @return maxSize
*/
public final Integer getMaxSize()
{
return maxSize;
}
/**
* Setter de maxSize
*
* @param maxSize maxSize à définir
*/
public final void setMaxSize(Integer maxSize)
{
this.maxSize = maxSize;
}
}
2- Déclarer le converter à JSF
Dans le FacesConfig, déclarez votre converter comme suit :
<converter-id>maxLengthConverter</converter-id>
<converter-class>dwdwdw.examples.converters.MaxLengthConverter</converter-class>
<property>
<description>-1 = no max length
>0 = maximum length of the output string.</description>
<property-name>maxSize</property-name>
<property-class>java.lang.Integer</property-class>
<default-value>-1</default-value>
<suggested-value>-1</suggested-value>
</property>
</converter>
Ici, il ne faut pas oublier de déclarer la propriété qui rendra notre converter paramétrable depuis la page JSF.
3 - Créer le custom tag
Grâce à Facelet, il n'y a rien de plus simple, créez simplement un fichier dont le nom se termine par ".taglib.xml" dans /META-INF et définissez votre tag. Facelet ne requiert pas de classe de tag.
Votre fichier ressemblera à celui-ci :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://fr.gouv.impots.vulcain/</namespace>
<tag>
<tag-name>trimMaxSize</tag-name>
<converter>
<converter-id>maxLengthConverter</converter-id>
</converter>
</tag>
</facelet-taglib>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://fr.gouv.impots.vulcain/</namespace>
<tag>
<tag-name>trimMaxSize</tag-name>
<converter>
<converter-id>maxLengthConverter</converter-id>
</converter>
</tag>
</facelet-taglib>
Dans votre web.xml, n'oubliez pas de déclarer votre taglib :
4- Créer sa page
Il ne vous reste maintenant plus qu'à créer votre page sans oublier de déclarer votre taglib :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:custom="http://duwebduwebduweb.com/" >
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:custom="http://duwebduwebduweb.com/" >
......
<t:outputText value="#{item.description}">
<vulcain:trimMaxSize maxSize="50"/>
</t:outputText>
......<t:outputText value="#{item.description}">
<vulcain:trimMaxSize maxSize="50"/>
</t:outputText>
5 - Compatibilité avec t:commandSortHeader
Lorsque vos pages ont un état géré par JSF, et notamment par MyFaces via le tag t:StaveState ou t:commandSortHeader, votre converter doit pouvoir stocker et restaurer son état.
Pour cela il doit implémenter l'interface javax.faces.component.StateHolder. Pour cela vous devrez ajouter une propriété boolean _transcient (nécessaire au focntionnement du saveState) et redéfinir certaines fonctions comme suit :
protected boolean _transcient;
.....
public boolean isTransient()
{
return _transcient;
}
public void restoreState(FacesContext arg0, Object arg1)
{
Object[] values = (Object[])arg1;
this.maxSize = (Integer)values[0];
}
public Object saveState(FacesContext arg0)
{
Object[] values = new Object[1];
values[0] = this.maxSize;
return values;
}
public void setTransient(boolean arg0)
{
_transcient = arg0;
}
.....
public boolean isTransient()
{
return _transcient;
}
public void restoreState(FacesContext arg0, Object arg1)
{
Object[] values = (Object[])arg1;
this.maxSize = (Integer)values[0];
}
public Object saveState(FacesContext arg0)
{
Object[] values = new Object[1];
values[0] = this.maxSize;
return values;
}
public void setTransient(boolean arg0)
{
_transcient = arg0;
}
Voilà, tout y est. Enjoy !
Aucun commentaire:
Enregistrer un commentaire