7

I am learning about composite components with JSF 2.0 and i want my component to be able to trigger methods from backing beans, so i created a simple example, but something is wrong.

This is the component i created:

<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>
        <composite:attribute name="attribute1"/>
        <composite:attribute name="attribute2"/>
        <composite:attribute name="actionBtnText"/>
        <composite:attribute name="actionMethod" method-signature="java.lang.String action()"/>
</composite:interface>

<composite:implementation>
    <h:form>
            <h:inputText value="#{cc.attrs.attribute1}"/>
            <br/>
            <h:inputText value="#{cc.attrs.attribute2}"/>
            <br/>
            <h:commandButton action="#{cc.attrs.actionMethod}" value="#{cc.attrs.actionBtnText}"/>          
    </h:form>

</composite:implementation> 

</html>

This is how i use it in a JSF page

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:custom="http://java.sun.com/jsf/composite/custom">

...

    <h:body>
    <custom:demoCustomComponent attribute1="#{demoBB.value1 }" attribute2="#{demoBB.value2 }" actionBtnText="Button text!" actionBtn="#{demoBB.act}"/>
    </h:body>

And this is the backing bean that gives support to the page where the component is

@Named("demoBB")
@RequestScoped
public class DemoBB {

    private String value1;
    private String value2;
    public String getValue1() {
        return value1;
    }

    public String act() {
        System.out.println("Input 1: " + value1 + "\nInput 2: " + value2);
        return null;
    }

    //Getters and setters
    public void setValue1(String value1) {
        this.value1 = value1;
    }
    public String getValue2() {
        return value2;
    }
    public void setValue2(String value2) {
        this.value2 = value2;
    }   
}

The component seems to render fine, but when i press the button i get an exception that says:

javax.faces.FacesException: Unable to resolve composite component from using page using EL expression '#{cc.attrs.actionMethod}'

Did i make any mistake in the interface or implementation of the component? Why doesn't work?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
javing
  • 12,307
  • 35
  • 138
  • 211

1 Answers1

13

You definied the action method using attribute name actionBtn:

<custom:demoCustomComponent ... actionBtn="#{demoBB.act}"/>

but you're expecting it to be the attribute name actionMethod:

<composite:attribute name="actionMethod" method-signature="java.lang.String action()"/>

Align it. They should be the same.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Ups, i see now, what a silly mistake. I was all the time looking at the customComponent but my mistake was in the index.xhtml, i just wrote wrong the name of the attribute :) Thanks! – javing Oct 19 '11 at 06:57
  • 1
    **Sorry for reviving an old thread** To anyone who struggles with actions in composite components like I did: If you make the `method-signature` like this: `method-signature="void action([Ljava.lang.Object;)"` then you will be able to pass in one page a method with one argument, in another page - a method with two arguments, etc. Also seems fine if the attribute is called `action` - to be consistent with the standard components. I had a NPE because the `action` attribute did not have a `method-signature` but once it does have it, seems to work. – Vasil Svetoslavov Oct 18 '19 at 07:29