I want to create my custom composite component in JSF (with primefaces) that shows a label in front of an input an adds a message at the end.
In order to do that here is my source code:
The composite:
<?xml version="1.0" encoding="UTF-8"?>
<!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:p="http://primefaces.org/ui"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface componentType="customInput">
<composite:attribute name="label" />
<composite:attribute name="value" />
</composite:interface>
<composite:implementation>
<h:panelGrid columns="3">
<h:outputText value="#{cc.attrs.label}:" />
<p:inputText id="abcde" value="#{cc.attrs.value}" />
<p:message for="abcde" />
</h:panelGrid>
</composite:implementation>
</html>
The backing bean:
#FacesComponent(value = "customInput")
public class CustomInput extends InputText implements NamingContainer {
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
}
So far, so good. Now I want to use the events inherited by the p:inputText component. Like for example:
<pch2:PchInputText2 label="Name" id="test2" value="#{testBean.test}">
<p:ajax event="blur" listener="#{chantierFormBean.updateMap()}" />
<p:ajax event="change" listener="#{chantierFormBean.updateMap()}" />
</pch2:PchInputText2>
I know that I could pass these events by adding
<composite:clientBehavior name="change" event="change" targets="abcde" />
to the composite:interface part, but then I have to add one client behavior for every event (in the future). Isn't there a method to pass all events inherited by the primefaces inputtext?
Thanks in advance
That's not possible.
A composite is in first place not the right tool for this job. It's not primarily intented to DRY out and refactor repeated XHTML code. It's intented to create a whole new (input) component tied to a single model value. For example, a <p:fileUpload> and <p:imageCropper> togeher which is tied to a single com.example.Image property. Or three <p:selectOneMenu> together which is tied to a single java.time.LocalDate property.
Use a tagfile instead.
<ui:composition ...>
<h:outputLabel for="#{id}" value="#{label}:" />
<p:inputText id="#{id}" value="#{value}">
<ui:insert />
</p:inputText>
<p:message for="#{id}" />
</ui:composition>
See also:
How to make a grid of JSF composite component?
When to use <ui:include>, tag files, composite components and/or custom components?
Related
I found a problem while using the bootsfaces inputText with ajax.
I'm using JSF 2.2, Bootsfaces 0.8.1 and Primefaces 5.3.
I'm trying to enter a date value into the inputText field. As soon as I enter the last value for the date the inputText should trigger the change event. At this point I would like to use ajax for calling a bean method. The problem is, that my field loses focus as soon as I try to enter the last value and the method's never been invoked.
So I tried a bit with Primefaces and it almost works like I wanted. At this point I got different questions:
Why does my inputText field lose the focus while entering the last value? (Bootsfaces)
Why is the bean method never called after I lose the focus? (Bootsfaces)
Is it possible to invoke the bean method after the bean value has been set by the field? (Primefaces)
I added the code below, so maybe you can reproduce this behaviour.
test.xhtml - sample xhtml with both primefaces and bootsfaces fields
<?xml version='1.0' encoding='UTF-8' ?>
<!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:b="http://bootsfaces.net/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta charset="UTF-8"/>
</h:head>
<h:body>
<h:form id="form">
<b:panel id="filterPanel" title="Filter properties" immediate="true" collapsed="false" collapsible="true">
<b:row>
<b:column span="12">
<b:inputText id="dateA" type="date" value="#{test.dateA}" immediate="true" class="form-control">
<f:ajax event="change" listener="#{test.searchA()}"/>
</b:inputText>
</b:column>
</b:row>
<b:row>
<b:column span="12">
<p:inputText id="dateB" type="date" value="#{test.dateB}" immediate="true" class="form-control">
<p:ajax event="change" listener="#{test.searchB()}"/>
</p:inputText>
</b:column>
</b:row>
</b:panel>
</h:form>
</h:body>
</html>
TestBean.java - my bean for setting the values and calling methods
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "test")
#ViewScoped
public class TestBean {
private String dateA;
private String dateB;
public void searchA() {
System.out.println("Search A");
}
public void searchB() {
System.out.println("Search B");
}
public String getDateA() {
return dateA;
}
public void setDateA(String dateA) {
this.dateA = dateA;
System.out.println(dateA);
}
public String getDateB() {
return dateB;
}
public void setDateB(String dateB) {
this.dateB = dateB;
System.out.println(dateB);
}
}
Please help me finding a solution or explain me what I'm doing wrong here.
Thanks
mweber
You've found a subtle difference between BootsFaces and PrimeFaces. I recommend you always define the values of process and update for the sake of clarity. In your case,
<b:inputText id="dateA" type="date" value="#{test.dateA}" immediate="true" class="form-control">
<f:ajax event="change" listener="#{test.searchA()}" render="#none"/>
</b:inputText>
makes the BootsFaces input field behave exactly like its PrimeFaces counterpart.
The default values of update and process are different. Since BootsFaces 0.8.5, the default values are:
process="#form" for <b:commandButton /> and <b:commandLink />
process="#this" for every other BootsFaces component
update="#form" for every BootsFaces component
According to Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes, the PrimeFaces default values are:
For the sake of convenience, here's my version of the XHTML file:
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
xmlns:b="http://bootsfaces.net/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta charset="UTF-8"/>
</h:head>
<h:body>
<h:form id="form">
<b:panel id="filterPanel" title="Filter properties" immediate="true" collapsed="false" collapsible="true">
<b:row>
<b:column span="12">
<b:inputText id="dateA" type="date" value="#{test.dateA}" immediate="true" class="form-control">
<f:ajax event="change" listener="#{test.searchA()}" render="#none"/>
</b:inputText>
</b:column>
</b:row>
<b:row>
<b:column span="12">
<p:inputText id="dateB" type="date" value="#{test.dateB}" immediate="true" class="form-control">
<p:ajax event="change" listener="#{test.searchB()}"/>
</p:inputText>
</b:column>
</b:row>
</b:panel>
</h:form>
</h:body>
</html>
I've tested it with BootsFaces 0.8.5.
I made a JSF composite component which uses f:convertNumber. However, it cannot convert value. How is this caused and how can I solve it?
currency.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!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:composite="http://java.sun.com/jsf/composite"
xmlns:f="http://java.sun.com/jsf/core">
<composite:interface>
</composite:interface>
<composite:implementation>
<f:convertNumber pattern="#,###" currencyCode="\\"/>
</composite:implementation>
</html>
index.xhtml
...
<h:outputText value="10000000">
<mycomp:currency />
</h:outputText>
...
result
10000000
This will indeed not work.
Composite components are interpreted as UI components. The <f:convertNumber>, however, is a taghandler, not an UI component. Basically, it will get applied on the composite itself (and render as useless), not on the target component as you intented.
You've at least two options:
Move <h:outputText> into the composite too,
<composite:interface>
<composite:attribute name="value" />
</composite:interface>
<composite:implementation>
<h:outputText value="#{cc.attrs.value}">
<f:convertNumber pattern="#,###" currencyCode="\\" />
</h:outputText>
</composite:implementation>
so you can ultimately use it as below.
<mycomp:currency value="10000000" />
Subclass NumberConverter with default values set in constructor and use it instead.
#FacesConverter("defaultCurrencyConverter")
public class DefaultCurrencyConverter extends NumberConverter {
public DefaultCurrencyConverter() {
setPattern("#,###");
setCurrencyCode("\\");
}
}
<h:outputText value="10000000" converter="defaultCurrencyConverter" />
When you register this converter in a tagfile as described here Creating custom tag for Converter with attributes,
<tag>
<tag-name>currency</tag-name>
<converter>
<converter-id>defaultCurrencyConverter</converter-id>
</converter>
</tag>
then you can ultimately use it as intented.
<h:outputText value="10000000">
<mycomp:currency />
</h:outputText>
See also:
How to avoid repetitions / use constants in Facelets page?
When to use <ui:include>, tag files, composite components and/or custom components?
I am building a simple component in JSF (Mojarra 2.1.x) where I have to access parent ui components to update them, currently I'm using binding to achieve this, but it only works as long as I don't use the component more than once on the same page.
So I need a solution that would allow me to use the component multiple times on same page.
In the following code I'm updating commandButton with binding="#{msButton}" and panel with binding="#{msPanel}":
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:layout="http://sterz.stlrg.gv.at/jsf/layout"
xmlns:p="http://primefaces.org/ui">
<cc:interface>
<cc:attribute name="controller" required="true" />
<cc:attribute name="converter" required="true" />
</cc:interface>
<cc:implementation>
<p:commandButton id="msButton#{cc.attrs.controller.class.getSimpleName()}" binding="#{msButton}" value="#{msg.mehr} (#{cc.attrs.controller.itemList.size()})" type="button" />
<p:overlayPanel id="msOverlayPanel" for=":#{msButton.clientId}" hideEffect="fade" my="right top" at="right bottom">
<p:panel id="msPanel#{cc.attrs.controller.class.getSimpleName()}" binding="#{msPanel}" styleClass="ui-panel-fit">
<ui:repeat id="repeat" value="#{cc.attrs.controller.itemList}"
var="item">
<p:commandButton id="removeButton"
actionListener="#{cc.attrs.controller.removeItem(item)}"
icon="ui-icon-trash" update=":#{msPanel.clientId} :#{msButton.clientId}" ajax="true"
process="#this" disabled="#{cc.attrs.controller.itemList.size() == 1}"/>
<p:selectBooleanButton id="value1" value="#{item.exclude}"
offLabel="und" onLabel="und nicht" style="width:80px;">
<p:ajax event="change" process="#this" />
</p:selectBooleanButton>
<p:autoComplete converter="#{cc.attrs.converter}"
readonly="#{cc.attrs.readonly}" value="#{item.from}"
dropdown="true"
completeMethod="#{cc.attrs.controller.autocomplete}" var="gp"
itemLabel="#{gp.displayName}" itemValue="#{gp}">
<p:ajax event="itemSelect" process="#this" />
</p:autoComplete>
<h:outputText value=" #{msg.bis} " />
<p:autoComplete converter="#{cc.attrs.converter}"
readonly="#{cc.attrs.readonly}" value="#{item.to}" dropdown="true"
completeMethod="#{cc.attrs.controller.autocomplete}" var="gp"
itemLabel="#{gp.displayName}" itemValue="#{gp}">
<p:ajax event="itemSelect" process="#this" />
</p:autoComplete>
<br />
</ui:repeat>
<hr />
<p:commandButton id="addButton" actionListener="#{cc.attrs.controller.addItem}"
icon="ui-icon-plus" value="#{msg.zufuegen}" update="#parent :#{msButton.clientId}"
ajax="true" process="#this"/>
</p:panel>
</p:overlayPanel>
</cc:implementation>
</ui:component>
Any help is much apprecieted.
The solution is to use the faces component bean
#FacesComponent("com.xxx.MultiselectorIdComponent")
public class MultiselectorIdComponent extends UINamingContainer
{
UIComponent msPanel;
// getters/settter and other ui compunents
}
tell the component interface what faces component bean to use
<cc:interface componentType="com.xxx.MultiselectorIdComponent">
bind the JSF component to the one in the faces component bean
<p:panel binding="#{cc.msPanel}"/>
and to access the components, for example to update the component, we use the binding
<p:commandButton value="My Button" update=":#{cc.msPanel.clientId}"/>
ALSO:
A good practice is to use a parent container (like <div>) with the following ID
<div id="#{cc.clientId}">
Hope this helps,
Regards
You could target the components for update by their style class
<p:commandButton styleClass="msButton" ... />
<p:panel styleClass="msPanel" ... />
And I guess you update them from addButton, which would look like this
<p:commandButton id="addButton" update="#(.msButton, .msPanel)" ... />
It should have no problems working with many cc instances on the same page.
UPDATE
You can try with update="#composite", which should refresh the whole custom component. Or, the cumbersome update="#parent #parent:#parent:#parent:#child(1)" which should target panel and button respectively. Or update="#parent #parent:#parent:#previous", which should do the same. Take a look at chapter 4.3 in Primefaces User Guide for more examples and supported keywords.
I solve similar problem by common bean "bindingBean" stored in ViewContext. BindingBean holds all binded component in internal MAP of component records. The key of hash map is an EL expression - it is factory of the component. EL is used for components creating. Components are hold in records stored in MAP in bind bean.
Example:
<h:panel binding="#{bindBean.get('msPanelFactory.getPanel()').component}"/>
Record:
public class BindingRecord {
private Object component;
private String compExpr;
public BindingRecord(String compExpr) {
this.compExpr = compExpr;
}
public Object getComponent() {
if (component == null) {
component = getValueExprValue("#{" + compExpr + "}");
}
return component;
}
public void setComponent(Object component) {
this.component = component;
}
public Object getStoredComponent() {
return component;
}
}
Binding bean:
public class BindingBean {
private final Map<String, BindingRecord> bindingMap = new HashMap<>();
public BindingRecord get(String key) {
BindingRecord result = bindingMap.get(key);
if (result == null) {
result = new BindingRecord(key);
bindingMap.put(key, result);
}
return result;
}
}
In you case you can use:
<h:panel binding="#{bindingBean.get('panelFactory.create()').component}"/>
Inside composite component you can use trick - Pass component name by composite parameter:
<h:panel binding="#{bindingBean.get('panelFactory.create('.concate(cc.attrs.componentName).concate(')')).component}"/>
(in this example we use primefaces components, but question is not related with Primefaces)
Introduction:
In order to have ajax support for composite component elements we just use element:
composite:clientBehavior
Let's look at this situation:
<composite:interface>
<composite:clientBehavior name="dateSelect" event="dateSelect" targets="id111 id222" />
</composite:interface>
<composite:implementation>
<p:calendar id="id111" value="#{csController.selectedDate}" mode="inline"
mindate="#{csController.minDate(2013,9)}"
maxdate="#{csController.maxDate(2013,9)}"/>
<p:calendar id="id222" value="#{csController.selectedDate}" mode="inline"
mindate="#{csController.minDate(2013,10)}"
maxdate="#{csController.maxDate(2013,10)}"/>
</composite:implementation>
We we have two elements and ajax support for these two elements. This works as expected.
We could even change to this interface:
<composite:interface>
<composite:clientBehavior name="dateSelect" event="dateSelect" targets="id111" />
<composite:clientBehavior name="dateSelect" event="dateSelect" targets="id222" />
</composite:interface>
and this still works fine.
Problem:
I would like to change implementation to show custom number of calendars, not exaclty two like shown above. So I tried this:
<composite:interface>
<composite:attribute name="firstMonth" default="1"/>
<composite:attribute name="lastMonth" default="12"/>
<c:forEach var="i" begin="#{cc.attrs.firstMonth}" end="#{cc.attrs.lastMonth}">
<composite:clientBehavior name="dateSelect" event="dateSelect" targets="#{cc.clientId}#{i}"/>
</c:forEach>
</composite:interface>
<composite:implementation>
<c:forEach var="i" begin="#{cc.attrs.firstMonth}" end="#{cc.attrs.lastMonth}">
<p:calendar id="#{cc.clientId}#{i}" value="#{csController.selectedDate}" mode="inline"
mindate="#{csController.minDate(2013,i)}"
maxdate="#{csController.maxDate(2013,i)}"/>
</c:forEach>
</composite:implementation>
This of course doesn't work.
Question:
How to get ajax support for all elements generated by c:forEach loop?
Actually you don't need to follow that procedure to add ajax functionality for your components. Just use f:ajax into your calendars. As c:forEach works before it, that's not a problem:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<cc:interface>
<cc:attribute name="val" />
</cc:interface>
<cc:implementation>
<c:forEach var="date" items="#{cc.attrs.val}">
<p:calendar value="#{date}" mode="inline">
<f:ajax event="dateSelect" listener="#{bean.printCurrentValues}" />
</p:calendar>
</c:forEach>
</cc:implementation>
</html>
Being this the main page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite/composites">
<h:head />
<h:body>
<h:form>
<composite:comp val="#{bean.calendars}" />
</h:form>
</h:body>
</html>
I added this listener method to the bean to check current dates are really changing:
#ManagedBean
#ViewScoped
public class Bean {
public List<Date> calendars = Arrays.asList(new Date(), new Date());
public List<Date> getCalendars() {
return calendars;
}
/**
* Just prints the updated values ;-)
*/
public void printCurrentValues() {
System.out.println("Current selected dates: " + calendars);
}
}
For your specific case you only would need to add a list of minDates and other one of maxDates in order to bind them to your calendar properties. Alternatively, you could also create your own class which wraps them to have everything packed. That's your own choice.
Solution above will work for dateSelect event and a provided listener. What if we want to have different events with different listeners?
Just define them on the interface and allow-deny them with JSTL's c:if. Here you have the composite implementation for a single input that can launch a listener method, also a dynamic number of p:calendar components, which will notify a user-defined method. By default none of them is launched.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<cc:interface>
<cc:attribute name="dateSelect" default="false" />
<cc:attribute name="click" default="false" />
<cc:attribute name="dateSelectListener" method-signature="void f()" />
<cc:attribute name="inputClickedListener" method-signature="void f()" />
<cc:attribute name="val" />
</cc:interface>
<cc:implementation>
<h:inputText>
<c:if test="#{cc.attrs.click}">
<f:ajax event="click" listener="#{cc.attrs.inputClickedListener}" />
</c:if>
</h:inputText>
<c:forEach var="date" items="#{cc.attrs.val}">
<p:calendar value="#{date}" mode="inline">
<c:if test="#{cc.attrs.dateSelect}">
<f:ajax event="dateSelect" listener="#{cc.attrs.dateSelectListener}" />
</c:if>
</p:calendar>
</c:forEach>
</cc:implementation>
</html>
And here the main page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite/composites">
<h:head />
<h:body>
<h:form>
<composite:comp val="#{bean.calendars}" dateSelect="true"
dateSelectListener="#{bean.printCurrentValues}" click="true"
inputClickedListener="#{bean.inputClicked}" />
</h:form>
</h:body>
</html>
Tested with Mojarra JSF 2.1.25 & Tomcat 7.
I'm trying to create a paginator composite component. The component should render a commandLink for each available page. It looks something like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:ui="http://java.sun.com/jsf/facelets">
<cc:interface>
<cc:attribute name="action" targets="jumpButton" required="true"/>
<cc:attribute name="bean" type="java.lang.Object" required="true"/>
</cc:interface>
<cc:implementation>
<ui:repeat value="#{cc.attrs.bean.pages}" var="page">
<h:commandLink id="jumpButton"
actionListener="#{cc.attrs.bean.jumpToPage(page)}">
<h:outputText value="#{page}"/>
</h:commandLink>
</ui:repeat>
</cc:implementation>
</html>
The component is used in various pages like this:
<ccc:paginator bean="#{myBean}"
action="/index?faces-redirect=true&includeViewParams=true"/>
Or:
<ccc:paginator bean="#{myOtherBean}"
action="/dir/index?faces-redirect=true&includeViewParams=true"/>
Notice the use of faces-redirect=true and includeViewParams=true, which as far as I know cannot be used directly on the commandLinks in the composite component.
The problem is that jumpButton cannot be target because it is inside an ui:repeat. I get the message:
javax.servlet.ServletException: /index?faces-redirect=true&includeViewParams=true : Unable to re-target MethodExpression as inner component referenced by target id 'jumpButton' cannot be found.
If I create a command link with id="jumpButton" outside the ui:repeat, the composite component and button works fine. How can I make my composite component work with the command link inside the ui:repeat?
Solution
The managed bean's jumpToPage action:
public String jumpToPage(String path, Integer page) {
...
setCurrentPage(page);
return path;
}
The composite component:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:ui="http://java.sun.com/jsf/facelets">
<cc:interface>
<cc:attribute name="bean" type="java.lang.Object" required="true"/>
<cc:attribute name="path" type="java.lang.String" required="true"/>
</cc:interface>
<cc:implementation>
<ui:repeat value="#{cc.attrs.bean.pages}" var="page">
<h:commandLink id="jumpButton"
action="#{cc.attrs.bean.jumpToPage(cc.attrs.path, page)}">
<h:outputText value="#{page}"/>
</h:commandLink>
</ui:repeat>
</cc:implementation>
</html>
Component usage examples:
<ccc:paginator bean="#{myBean}"
path="/index?faces-redirect=true&includeViewParams=true"/>
<ccc:paginator bean="#{myOtherBean}"
path="/dir/index?faces-redirect=true&includeViewParams=true"/>
You should remove the action attribute within <cc:interface>. It is not needed since you invoke the action via the bean attribute.
Update 1
And the outcome of the action you can also define as return value of your bean. Like this:
public class MyBean {
public String jumpToPage(int page){
// ...
return "/index?faces-redirect=true&includeViewParams=true";
}
}
And then use action instead of actionListener:
<h:commandLink id="jumpButton" action="#{cc.attrs.bean.jumpToPage(page)}">
<h:outputText value="#{page}"/>
</h:commandLink>