0

I am using (simple) JSF 2 custom components.

I mean that I am using a taglib.xml file like :

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib id="sentest"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
    version="2.0"
>
    <namespace>http://www.senat.fr/taglib/sentest</namespace>

[...]
    <tag>
        <description>
            <![CDATA[
            À COMPLÉTER
            ]]>
        </description>
        <tag-name>senMandats</tag-name>
    <source>tags/sen/senMandats.xhtml</source>
        <attribute>
            <description>
                <![CDATA[
        Identifiant unique.
        ]]>
            </description>
            <name>id</name>
            <required>true</required>
            <type>java.lang.String</type>
        </attribute>
        <attribute>
            <description>
                <![CDATA[
     Contexte de sélection du Sénateur.
    ]]>
            </description>
            <name>context</name>
            <required>true</required>
        </attribute>
    </tag>
</facelet-taglib>

The component is defined using ui composition :

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html lang="fr"
    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:composite="http://java.sun.com/jsf/composite"
    xmlns:p="http://primefaces.org/ui"
    xmlns:sen="http://java.sun.com/jsf/composite/sen"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions"
    xmlns:sf="http://www.senat.fr/taglib/senfunctions"
    xmlns:st="http://www.senat.fr/taglib/sentest"
    xmlns:o="http://omnifaces.org/ui"
    xmlns:of="http://omnifaces.org/functions">
    <h:head/>
    <h:body>
        <ui:composition>
    [...]
        </ui:composition>
    </h:body>
</html>

it works fine except for one very embarrassing point.

I am passing dynamic el values to those custom components.

Example :

<st:senMandats id="toto" context="#{selectionContext}"/>

The selectionContext bean being defined elsewhere.

In st:senMandats, I use other custom components in a nested way. Something like :

<st:listeMandats mandatContext="#{sensContext}" asen="#{selectionContext.selectedSen}"/>

The listeMandat component uses a primefaces dataTable to display some lists from the context. So, I have code like :

<h:outputLabel value="listeMandats de #{asen.libelleLong}" styleClass="bigTitleMandats" rendered="#{not empty asen}" />
<p:dataTable id="tableMandatsSenatoriaux" value="#{mandatContext.asList}" /* lots of other parameters */>

When I select an entry in the picker, the custom component gets properly updated. I can see that the valueDisplayed by the h:outputLabel is correctly updated depending on the selection.

When #{mandatContext.AsList} is called, I am retrieving #{asen} from the application context and performing some internal update before returning the requested list. There comes the problem : if #{asen} seems to be ok when rendering #{asen.libelleLong}, I can not get the updated value from the backing bean.

I am using the following function :

@SuppressWarnings("unchecked")
public static <T> T findBean(String name) {
    if ((name == null) || name.isEmpty())
        return null;
    FacesContext fc = FacesContext.getCurrentInstance();
    logger.debug("Retrieving #{" + name + "}");
    return (T) fc.getApplication().evaluateExpressionGet(fc,
            "#{" + name + "}", Object.class);
}

in the AsList method :

JSFUtils.findBean("#{asen}")

always return an old, not updated value.

What should I do so that my bean can access the updated value ? I tried the solutions 4, 5 and 6 proposed by mykong in http://www.mkyong.com/jsf2/access-a-managed-bean-from-event-listener-jsf/ but still does not get the right value.

Am I forced to code a custom component class, deriving from a specific class ? If so, am I forced to also code a renderer ? I would like to avoid that, as I appreciate to have the layout in an xhtml file.

Thanks in advance.

I am using :

  • PrimeFaces 3.4.1
  • CODI 1.0.5
  • OpenWebBeans 1.1.6
  • MyFaces 2.1.9
  • Tomcat 7.0.32 (edit : set "extra question" as a another question)
Ludovic Pénet
  • 1,136
  • 1
  • 16
  • 32
  • I don't have time to read this all, but I just want to quickly sanitize a misconception: you don't have custom component here at all, but just a tag file. See also http://stackoverflow.com/questions/6822000/when-to-use-uiinclude-tag-files-composite-components-and-or-custom-componen/6822269#6822269 – BalusC Oct 31 '12 at 17:08
  • I just tried to explain the context. In a nutshell : how a bean method called from a tag file can get updated tag attributes on update ? – Ludovic Pénet Oct 31 '12 at 18:01
  • ever heard of [sscce](http://sscce.org/)??? – Kerem Baydoğan Oct 31 '12 at 18:15
  • I took the time to read it and I noticed that you actually have 2 questions. I suggest to remove the 2nd question and post it in its own Question. – BalusC Oct 31 '12 at 19:19
  • @kerem with jsf, you can rarely be both short and self-contained . Count jsf questions with a full working example... – Ludovic Pénet Oct 31 '12 at 19:20
  • @BalusC Ok, I will post the 2nd question as an independant one. Thx for your attention. – Ludovic Pénet Oct 31 '12 at 19:22
  • Coming back to the concrete problem, *"When #{mandatContext.AsList} is called, I am retrieving #{asen} from the application context and performing some internal update before returning the requested list"* Does this mean that you're performing the business job in the getter method of the datatable, without checking in which phase JSF is currently sitting in? Why don't you perform this job in an ajax listener method which is triggered by the picker? The datatable getter is called multiple times in JSF lifecycle. Chance exist that you're trying to access it *before* UPDATE_MODEL_VALUES phase. – BalusC Oct 31 '12 at 19:26
  • I do not perform business job in the getter. As you point, it would be inappropriate. I just want to know which "asen" is currently selected. In my app, there are different kinds of pickers whose instances do not know what is done with their selections. They are just "pickers". I have ~10 types of "mandatContext", who are updated according to the current selection. Those know that there is a picker, but not its kind. – Ludovic Pénet Oct 31 '12 at 20:00
  • (../..) For know, with "plain JSF" (everything on a page) or in a composite component, I always could retrieve the current "asen" using the "evaluateContextGet" method. So, I would just like to understand why this does not work here. I will off course proceed another way if I need to. I do not think that it is a phase problem, or I would have tracked the "right" value in the last calls to the "AsList" method. I wondered if there was some tweaking to perform to "refresh" the value of dynamic parameters of tag components for backing beans. – Ludovic Pénet Oct 31 '12 at 20:04
  • Okay. Well, this sounds like a bug in the JSF impl used as to referencing EL expressions in tag file attributes. I don't recall ever having seen this. At least not in Mojarra. Do you see any chance to try this use case with Mojarra instead of MyFaces and check if it exposes the same problem or instead just works fine? You can download Mojarra from http://javaserverfaces.java.net (currently 2.1.14). It's a matter of dropping the `javax.faces.jar` file in classpath. – BalusC Oct 31 '12 at 20:08
  • ok, I will try with Mojarra on monday. I will probably also submit the question on the myfaces users list and provide feedback there. – Ludovic Pénet Oct 31 '12 at 20:16
  • So : I did not have a reply on myfaces user list. And I could not test with glassfish. I am using OWB+MyFaces+CODI, including specific annotations like "@ Advanced" and, even with Weld, glassfish is not a drop in replacement. – Ludovic Pénet Nov 05 '12 at 12:29
  • As we should finally drop tomcat 6 for tomcat 7, I just pass the "asen" as a parameter of a mandatContext.anotherMethod function and everything is fine. Investigating further, I noticed that I can access the right value of "real" beans. "asen", in my example, is not really a bean, but an attribute of the tag component. I tried to retrieve the component with a standard findComponent method but could not find it. Getting this component then exploring its attributes could have been another solution... – Ludovic Pénet Nov 05 '12 at 12:32

0 Answers0