Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing JSF2 composite component attributes in backing component

I'm developing a JSF2/Primefaces app and I'm having trouble with accessing attributes defined in an interface of a composite component in this component's backing bean.

My component is defined as follows:

<!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:composite="http://java.sun.com/jsf/composite">

<composite:interface componentType="testComponent">
    <composite:attribute name="text" required="true" type="java.lang.String" />
</composite:interface>

<composite:implementation>

    <h:outputText value="Passed text is: #{cc.attrs.text}" />

</composite:implementation>

</html>

It is stored in a file called text.xhtml located in: application/src/main/webapp/resources/my_component directory.

I use this component on another page (which is a Facelets composition element) like so:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:myc="http://java.sun.com/jsf/composite/my_component"
    template="./resources/templates/template.xhtml">

<ui:define name="content"> 
    <h:form id="products">
        <myc:test id="test" text="A text" />
    </h:form>
</ui:define>    

</ui:composition>

The backing component class is defined as follows:

package my.application.component;

import javax.faces.component.FacesComponent;
import javax.faces.component.UINamingContainer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@FacesComponent ( value="testComponent" )
public class TestComponent extends UINamingContainer {
    Logger log = LoggerFactory.getLogger(TestComponent.class);

    public TestComponent() {
        log.debug("TestComponent constructor");
        log.debug("getAttributes().size(): " + getAttributes().size());
    }
}

The component itself works as expected. The using page renders Passed text is: A text output. Also, logger output displays log messages from TestComponent constructor, so it seems that the component xml definition is correctly bound with the TestComponent class.

Now, the problem is that the getAttributes() method invoked in TestComponent constructor always returns a zero-sized map. If I understand this correctly, I should be able to access the text attribute declared in component's interface using a call:

getAttributes().get("text");

in the TestComponent class, but it always returns null as the attributes map is empty.

I also tried to access the text attribute using a call:

String text = FacesContext.getCurrentInstance().getApplication(). evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{cc.attrs.text}", String.class));

but it also resolves to null.

What am I doing wrong? Any tips will be much appreciated as I have no idea what to try next.

/Tukasz.

like image 856
Łukasz Łukasik Avatar asked Feb 20 '12 08:02

Łukasz Łukasik


1 Answers

My guess is that the constructor is too early to reference those attributes.

JSF will construct an instance of the backing component first, and will then at some point give it a reference to its attributes. In a method that's called later, eg the encode method, you should have access to them.

like image 86
Mike Braun Avatar answered Nov 13 '22 17:11

Mike Braun