I wrote an new renderer for a primefaces component, now i want to make have this "new" component available under a new namespace:
I created a new taglib for that:
<facelet-taglib 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.whitebyte.com/commentbox</namespace>
<tag>
<tag-name>tree</tag-name>
<component>
<component-type>org.primefaces.component.Tree</component-type>
<renderer-type>commentbox.CustomTreeRenderer</renderer-type>
</component>
<attribute>
<description><![CDATA[Unique identifier of the component in a namingContainer.]]></description>
<name>id</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Boolean value to specify the rendering of the component, when set to false component will not be rendered.]]></description>
<name>rendered</name>
<required>false</required>
<type>java.lang.Boolean</type>
</attribute>
<attribute>
<description><![CDATA[An el expression referring to a server side UIComponent instance in a backing bean.]]></description>
<name>binding</name>
<required>false</required>
<type>javax.faces.component.UIComponent</type>
</attribute>
<attribute>
<description><![CDATA[Name of the client side widget.]]></description>
<name>widgetVar</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[A TreeNode instance as the backing model.]]></description>
<name>value</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Name of the request-scoped variable that'll be used to refer each treenode data during rendering.]]></description>
<name>var</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Specifies the ajax/client toggleMode. Default is false.]]></description>
<name>dynamic</name>
<required>false</required>
<type>java.lang.Boolean</type>
</attribute>
<attribute>
<description><![CDATA[Specifies caching on dynamically loaded nodes. When set to true expanded nodes will be kept in memory. Default is true.]]></description>
<name>cache</name>
<required>false</required>
<type>java.lang.Boolean</type>
</attribute>
<attribute>
<description><![CDATA[Javascript event to process when a tree node is clicked.]]></description>
<name>onNodeClick</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[TreeNode array to reference the selections.]]></description>
<name>selection</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Style of the main container element of tree.]]></description>
<name>style</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Style class of the main container element of tree.]]></description>
<name>styleClass</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Defines the selectionMode.]]></description>
<name>selectionMode</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Highlights nodes on hover when selection is enabled, set to false to disable highlighting.]]></description>
<name>highlight</name>
<required>false</required>
<type>java.lang.Boolean</type>
</attribute>
<attribute>
<description><![CDATA[Unique key of the data presented by tree nodes.]]></description>
<name>datakey</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[When enabled, Displays slide effect during toggling of a node.]]></description>
<name>animate</name>
<required>false</required>
<type>java.lang.Boolean</type>
</attribute>
</tag>
I added the render in faces-config.xml too:
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>commentbox.CustomTreeRenderer</renderer-type>
<renderer-class>commentbox.CustomTreeRenderer</renderer-class>
</renderer>
</render-kit>
The new component is also seen in eclipse but when i open the page in the browser i get:
javax.faces.FacesException: Cannot find component with identifier "tree" referenced from "j_idt62:j_idt76".
at org.primefaces.util.ComponentUtils.findClientIds(ComponentUtils.java:273)
at org.primefaces.util.AjaxRequestBuilder.addIds(AjaxRequestBuilder.java:102)
at org.primefaces.util.AjaxRequestBuilder.update(AjaxRequestBuilder.java:90)
at org.primefaces.renderkit.CoreRenderer.buildAjaxRequest(CoreRenderer.java:196)
at org.primefaces.component.commandbutton.CommandButtonRenderer.encodeMarkup(CommandButtonRenderer.java:74)
at org.primefaces.component.commandbutton.CommandButtonRenderer.encodeEnd(CommandButtonRenderer.java:49)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875)
at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:59)
at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:43)
at org.primefaces.component.outputpanel.OutputPanelRenderer.encodeEnd(OutputPanelRenderer.java:46)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875)
at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:59)
at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:43)
at org.primefaces.component.outputpanel.OutputPanelRenderer.encodeEnd(OutputPanelRenderer.java:46)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:312)
at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:105)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779)
at com.sun.faces.renderkit.html_basic.CompositeRenderer.encodeChildren(CompositeRenderer.java:78)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
The solution was to create the "whole" component and register that in the taglib like described here:
https://stackoverflow.com/a/10569044/441907
(I didn't register the taglib just put it into META-INF in classes that worked).
Related
When we define java.lang.String or string and boolean or java.lang.Boolean as attribute type in items.xml in hybris.
Since Hybris version 4, it is possible to use primitive Java types instead of the related wrapper classes e.g. boolean instead of java.lang.Boolean. The advantage of doing so is that the attribute definition gets a default value automatically. This removes the need for handling null values.
Thus, you can change the following definition
<attribute qualifier="myAttribute" type="java.lang.Boolean">
<modifiers read="true" write="true" initial="true" optional="false"/>
<persistence type="property"/>
</attribute>
into
<attribute qualifier="myAttribute" type="boolean">
<modifiers read="true" write="true" initial="true" optional="false"/>
<persistence type="property"/>
</attribute>
and perform the system update to make the change effective.
I am developing a JSF 2.2.12 application with IntelliJ IDEA 2016.2.1 Ultimate. The problem is that many of the attributes of ui:repeat (and possibly other components) are missing.
For example, I'd like to use the step attribute of ui:repeat, as defined here. When I attempt to use it, this is what happens:
If I ctrl + click on repeat to go to its source, and I am taken to the file
...\IntelliJ IDEA 2016.2.1\plugins\JSF\lib\jsf-support.jar!\resources\schemas\ee7\tld\jsf-ui.tld
which has this definition of repeat:
<tag>
<name>repeat</name>
<tag-class></tag-class>
<tei-class></tei-class>
<body-content>JSP</body-content>
<description>
<![CDATA[
The repeat tag should be used in almost all cases instead of the c:forEach to iterate over content with JSF.
The repeat tag is often used in conjunction with the jsfc feature.
]]>
</description>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description></description>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
<description>The name of a collection of items that this tag iterates over. The collection may be a List, array, java.sql.ResultSet, or an individual java Object. If the collection is null, this tag does nothing.</description>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
<description>The literal name of the variable to use while iterating.</description>
</attribute>
</tag>
The only attributes defined are id, value, and var! Why are the other attributes not here?
Here is my pom.xml entry for JSF:
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.12</version>
<scope>provided</scope>
</dependency>
We have a custom JSF component that renders some buttons and a select box in a specific way. This is done by a class that extends UIInput. This custom component used in the xhtml templates like so:
<xx:fooComponent
value="#{fooBean.someProperty}"
valueChangeListener="#{fooBean.someMethodInBean}"
someOtherProperties="true" />
Now since we changed from JBoss 4.2.2 running JSF 2.0 to JBoss 7.1.1 running with the built-in JSF libs, it complains about someMethodInBean not being a property. Of course it's not a property, it's a method. Who in the world would bind a property to a valueChangeListener?
At first I thought, this had something to do with the method being in a superclass of the referenced bean, but that wasn't the case. Adding this particular method to FooBean did not make any difference.
So my question is, what did they change so that this breaks now and how can I fix it in a migrating-friendly way?
edit
The component is declared as such in our *.taglib.xml:
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<!-- ... -->
<tag>
<tag-name>fooComponent</tag-name>
<component>
<component-type>myProject.FooComponent</component-type>
</component>
</tag>
... which leads to this declaration in faces-config.xml:
<component>
<component-type>myProject.FooComponent</component-type>
<component-class>com.myproject.somemore.UIFooComponent</component-class>
</component>
... which leads to the class UIFooComponent extends UIInput.
edit 2
Now the taglib xml looks like this:
<facelet-taglib version="2.0"
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">
<tag>
<tag-name>fooComponent</tag-name>
<component>
<component-type>myProject.FooComponent</component-type>
</component>
<attribute>
<name>valueChangeListener</name>
<method-signature>void valueChanged(javax.faces.event.ValueChangeEvent)</method-signature>
</attribute>
</tag>
</facelet-taglib>
Still, he complains about fooBean not having the property someMethodInBean.
edit 3
The stack trace is:
Caused by: javax.el.ELException: /abc/abc.xhtml: The class 'com.myproject.managedbeans.foo.FooBean' does not have the property 'someMethodInBean'.
at com.sun.faces.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:94)
at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185)
at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:129)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:402)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
at org.apache.myfaces.tomahawk.application.ResourceViewHandlerWrapper.renderView(ResourceViewHandlerWrapper.java:93)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
... 21 more
This indicates that the tag attribute isn't been declared as a <method-signature> in the component's <tag> declaration in the .taglib.xml file as follows:
<attribute>
<name>valueChangeListener</name>
<method-signature>void valueChange(javax.faces.event.ValueChangeEvent)</method-signature>
</attribute>
Make sure that this is properly been declared as above.
Update: you need to make sure that you've declared the .taglib.xml file conform JSF 2.x Facelets XSD (and thus not a DTD as it was in legacy Facelets 1.x).
<facelet-taglib
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"
>
<!-- Tags here -->
</facelet-taglib>
we have following taglib:
<facelet-taglib version="2.0" 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">
<namespace>http://www.example.com/mytaglib</namespace>
<composite-library-name>common</composite-library-name>
<tag>
<tag-name>selectOneRadio</tag-name>
<component>
<component-type>psa.selectOneRadio</component-type>
<renderer-type>psa.selectOneRadioRenderer</renderer-type>
</component>
<attribute>
<name>styleClass</name>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>itemStyleClass</name>
<type>java.lang.String</type>
</attribute>
</tag>
The tag lib combines composite components in /resources/common (composite-library-name) and java written components.
It all works fine, but when using the selectOneRadio (java) component, we get the following error (but without a "real" error -> the selectOneRadio component also works fine):
08:31:31,202 ERROR [ResourceImpl:98] Resource handler [com.sun.faces.application.resource.ResourceHandlerImpl#1c22bcb0] was unable to create a resource for resourceName=[selectOneRadio.xhtml] libraryName=[common] contentType [application/xhtml+xml]
Its clear, because the selectOneRadio component is a java written component, the selectOneRadio.xhtml does not exist.
Thanks
Dirk
I would like to use jsf4birt to put birt report into xhtml pages. I tried to deploy exadel-jsf4birt-demo.war under jboss 6 but failed. Max#exadel said that jsf4birt only suppourts JSF 1.2, so does anyone have experience of using jsf4birt under JBoss 6? Thanks.
I figured this out. There is a bug in jsf4bir's tag definition file jsfbirt.tld:
<attribute>
<description>Defines UI Option name</description>
<name>name</name>
<deferred-value>
<type>java.lang.String</type>
</deferred-value>
<required>true</required>
</attribute>
this should be:
<attribute>
<description>Defines UI Option name</description>
<name>name</name>
<required>true</required>
<deferred-value>
<type>java.lang.String</type>
</deferred-value>
</attribute>