[JSF/Facelets] Doorgeven parameter aan custom component

Pagina: 1
Acties:

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

Topicstarter
Voor mijn huidige project hebben we met JSF een aantal templates en custom components gemaakt. Een aantal maanden werkte het prima, maar nu lopen we tegen een probleem aan, namelijk omdat we een converter willen registreren die niet goed werkt.

Ik zal het even proberen te schetsen.
We hebben een component, namelijk een column voor in een dataTable. Die is ervoor om zaken als CSS en sorteren wat generieker te maken. Zie code:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
<html ...>

    <ui:composition>
        <h:column id="#{id}">
            <f:facet name="header">
                Vanalles voor de header...
            </f:facet>
            <h:outputText value="#{value}" id="value_#{id}_text">
                <ui:insert />
            </h:outputText>
        </h:column>
    </ui:composition>
</html>


Die column wordt als volgt gebruikt in een client pagina:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html ...>

    <ui:composition>
        ...
            <h:form>
            #{i18n.Statushistorie}
            <h:dataTable value="#{bean.property}" var="current" ...>
                <o:column label="..." value="#{current.datumProperty}">
                    <o:datumConverter pattern="dd-MM-yyyy HH:mm:ss" />
                </o:column>

                <h:column label="..." >
                    <h:outputText value="#{current.prop}">
                        <o:datumConverter pattern="dd-MM-yyyy HH:mm:ss" />
                    </h:outputText>
                </h:column>
            </h:dataTable>
        </h:form>
    </ui:composition>
</html>


Wat is nu het probleem? Die datumConverter werkt niet wanneer deze zich in een custom component bevindt (o:column). De converter krijgt namelijk een object van het type String binnen in plaats van een Datum. Wanneer ik een h:column gebruik, dan werkt het prima.

Ik denk dat ik de reden ook wel weet, namelijk dat een EL expressie naar een String evalueert omdat het alleen gebruikt wordt voor weergave.

Ik geef dit mee aan de component:
<o:column label="..." value="#{current.datumProperty}">
<o:datumConverter pattern="dd-MM-yyyy HH:mm:ss" />
</o:column>

Maar wat gebeurt er?
De expressie wordt uitgevoerd, retourneert een string, dat wordt in het component gestopt en de converter krakt omdat hij eigenlijk een Date verwacht.

Weet iemand hoe je kunt zorgen dat de expressie niet direct uitgevoerd wordt?

Fat Pizza's pizza, they are big and they are cheezy


  • rrrandy
  • Registratie: Juli 2005
  • Laatst online: 27-06 13:00
Die custom component heb je zelf gebouwd? Dan kun je die toch aanpassen zodat je wel een datum krijgt?

Anders kun je je datumconverter bijvoorbeeld zo aanpassen dat er een Object in gaat ipv een Date. Is dit object van het type Date, dan ga je gewoon verder. Is het object echter van het type String, dan ga je iets anders doen of geef je hem direct terug. Wel een vieze oplossing natuurlijk.

Ik zou eerst eens kijken of je niet iets in je custom component kunt doen.

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

Topicstarter
rrrandy schreef op vrijdag 10 november 2006 @ 13:12:
Die custom component heb je zelf gebouwd? Dan kun je die toch aanpassen zodat je wel een datum krijgt?

Anders kun je je datumconverter bijvoorbeeld zo aanpassen dat er een Object in gaat ipv een Date. Is dit object van het type Date, dan ga je gewoon verder. Is het object echter van het type String, dan ga je iets anders doen of geef je hem direct terug. Wel een vieze oplossing natuurlijk.

Ik zou eerst eens kijken of je niet iets in je custom component kunt doen.
Nou, het probleem is vooral dat het niet echt een geprogrammeerd component is, maar een XHTML waarin verschillende componenten geaggregeerd worden tot één component.

Die vieze oplossing hadden we hier idd ook al bedacht, maar je zegt het zelf al, het is vies. :P

Fat Pizza's pizza, they are big and they are cheezy


  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

Als je de custom component niet kan aanpassen, dan zie ik ook geen "nettere" oplossing dan hetgeen rrrandy suggereert :)

[OT]Overigens, GoT kent sinds een tijdje ook [norml][code=jsp] en
Java Server Faces:
1
[/norml] tags ;)

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
JKVA schreef op vrijdag 10 november 2006 @ 12:56:
Wat is nu het probleem? Die datumConverter werkt niet wanneer deze zich in een custom component bevindt (o:column). De converter krijgt namelijk een object van het type String binnen in plaats van een Datum. Wanneer ik een h:column gebruik, dan werkt het prima.

Ik denk dat ik de reden ook wel weet, namelijk dat een EL expressie naar een String evalueert omdat het alleen gebruikt wordt voor weergave.
Hmmm, dit is toch wel apart. Welke JSF implementatie gebruik je? Het is waarschijnlijk een Facelets specificiek iets. De normale gang van zaken is ongeveer als volgt:

De ConverterTag zoekt z'n (UIComponent) parent in de tree en stopt daar een Converter in.

Als het component een output component is, zal deze eerst kijken of er een Converter gezet is, en dan z'n data door deze Converter halen. Of het component dit doet, en of het component z'n data direct erin stopt of eerst kijkt of het een ValueBinding is, is component specificiek.

De Myfaces output componenten (UIOutput) besteden deze logica uit aan RenderUtils, deze kijkt weer of het component een ValueHolder is, en roept daardan getValue() op aan.

getValue() is gedefineerd in de base class UIOutput waar ook HTMOutputText van inherrit (HTMLOutputText is het faces component achter de tag <h:outputText>). Deze getValue() functie kijkt altijd of de value een EL expressie is, en zoja dan wordt deze resolved (uitgevoerd) en wordt het object uit de bean waar de EL heen verwees teruggegeven. Is het geen EL, dan wordt de waarde zelf teruggegeven.

Nu weet ik niet hoe het agregatie mechanisme van facelets precies werkt, maar ik kan me voorstellen dat het dynamisch door facelets gegenereerde custom component inderdaad zelf de EL kan uitvoeren en ergens een toString op het verkregen Object gaat uitvoeren. Dit lijkt me echter wel een beetje ongewenst als dit niet uit te schakelen is.

Een andere mogelijkheid zou nog kunnen zijn dat de ConverterTag in de tree niet direct het HTMLOutputText element (<h:outputText>) tegenkomt, maar alleen het door facelets gemaakte component vind. Het zal dan op dit component setConverter aanroepen, en facelets weet dan niet naar welk subcomponent het deze call moet doorpropageren.

Wat je mischien het beste kan doen is dit gewoon even in een IDE debuggen. Voeg een source attachment voor alle code toe (myfaces, facelets) en zet een breakpoint in de getDatumProperty method van je bean. Step in method die jouw method aanroept en volg wat er met de waarde gebeurd. Daarnaast kun je ook even een breakpoint zetten in de doStartTag van de ConverterTag. Let vooral op welke parent er gevonden wordt, en step in de call naar setConverter om te kijken wat er mee gebeurd.

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
rrrandy schreef op vrijdag 10 november 2006 @ 13:12:
Anders kun je je datumconverter bijvoorbeeld zo aanpassen dat er een Object in gaat ipv een Date.
Wat bedoel je hier nu mee?

De DatumConverter implementeerd de Converter interface. Daar krijgt de getAsString method altijd al een Object mee.

Aangezien het hier om output gaat (een Encoding operatie in Java termen), zal de getAsString worden aangeroepen, en die krijgt dus altijd een Object mee. In je Converter kun je natuurlijk wel checken of dit Object een Date of String instance is.

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.

Pagina: 1