Does the component-type name needs to be unique for custom components? - jsf

I am new to Custom components topic starting with JSF 2.2
However, I am first considering the case with JSF2.0
Consider the snippet:
#FacesComponent(value = "components.WelcomeComponent1", createTag = true)
public class WelcomeComponent extends UIComponentBase {
}
Do notice value = "components.WelcomeComponent1"
referencing it in the UI wireframe-
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:t="http://xmlns.jcp.org/jsf/component">
<h:head>
<title></title>
</h:head>
<h:body>
<t:welcomeComponent value="Welcome" to="Rafael Nadal"/>
</h:body>
</html>
Consider the second case with the same name of the class as in first case but in a different package with a different component-type name:
#FacesComponent("components.WelcomeComponent")
public class WelcomeComponent extends UIComponentBase {
// code goes here
}
Do notice the "components.WelcomeComponent"
taglib.xml in WEB_INF
<namespace>http://atp.welcome.org/welcome</namespace>
<tag>
<tag-name>welcome</tag-name>
<component>
<component-type>components.WelcomeComponent</component-type>
</component>
<attribute>
<name>id</name>
<type>java.lang.String</type>
<description>Component id</description>
<required>false</required>
</attribute>
</tag>
</facelet-taglib>
and referencing the latter -
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:t="http://atp.welcome.org/welcome">
<h:head>
<title></title>
</h:head>
<h:body>
<t:welcome value="Welcome" to=""/>
</h:body>
</html>
Both of the above examples are part of the same web app & work fine.
However if I change the component-type name in the second case to make it the same as in first case,
#FacesComponent("components.WelcomeComponent1")
I do get-
Warning: This page calls for XML namespace
http://xmlns.jcp.org/jsf/component declared with prefix t but no
taglibrary exists for that namespace
Clearly the entry/tag declared in taglib.xml is preferred.
So, the component-type name needs to be unique in each case. Right?
I know it very well that the namespace http://xmlns.jcp.org/jsf/component was introduced with JSF2.2.

Short answer is yes, it should be unique. JSF thinks of it as a name for your custom component (in the similar way as a #ManagedBean). Basically, component-type allows Application instance to create new instances of UIComponent subclasses (your and every other custom component) by using defined component-type and createComponent() method.

Related

primefaces framework doesn't work [duplicate]

I am trying to use Picklist from Primefaces. When the page is rendered, the javascript engine in Chrome cannot find Primefaces object. I get the following error 'Uncaught ReferenceError: PrimeFaces is not defined'. Am I missing to include any resource (js) in my .xhtml file? Please advise. Thanks.
Xhtml
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
<link rel="stylesheet" type="text/css"
href="../jquery-ui-1.8.23.custom/css/ui-lightness/jquery-ui-1.8.23.custom.css" />
<link rel="stylesheet" type="text/css" href="css/form.css" media="all" />
<script src="../jquery-ui-1.8.23.custom/js/jquery-1.8.0.min.js"></script>
<script
src="../jquery-ui-1.8.23.custom/js/jquery-ui-1.8.23.custom.min.js"></script>
</head>
<h:body>
<form id="form_486588" class="appnitro" method="post">
<div class="form_description"></div>
<p:pickList id="pickList" value="#{editorsMB.editors}" var="editor"
itemLabel="#{editor}" itemValue="#{editor}" />
<p:commandButton id="citySubmit" value="Submit"
style="margin-top:5px" />
</form>
</h:body>
</html>
Managed bean
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.model.DualListModel;
#ManagedBean(name = "editorsMB")
#SessionScoped
public class AdminEditorsBean {
private DualListModel<String> editors;
public AdminEditorsBean(){
List<String> adminsSource = new ArrayList<String>();
List<String> adminsTarget = new ArrayList<String>();
adminsSource.add("aaa");
adminsTarget.add("target1");
editors = new DualListModel<String>(adminsSource, adminsTarget);
}
public DualListModel<String> getEditors() {
return editors;
}
public void setEditors(DualListModel<String> editors) {
this.editors = editors;
}
}
PrimeFaces will auto-include the necessary JS/CSS resources in <h:head>.
However, you don't have that tag. You've there a "plain HTML" <head>. Fix it accordingly:
<html>
<h:head>
...
</h:head>
<h:body>
...
</h:body>
</html>
This mistake should also have been logged in the server log as below:
One or more resources has the target of 'head' but not 'head' component has been defined within the view
See also How to include another XHTML in XHTML using JSF 2.0 Facelets? and When to use <ui:include>, tag files, composite components and/or custom components? for various correct examples of authoring JSF/Facelets pages.
Unrelated to the concrete problem: PrimeFaces as being a jQuery based JSF component library already ships with jQuery and jQuery UI bundled. You should remove the manually included scripts from your page to avoid conflicts. See also Adding jQuery to PrimeFaces results in Uncaught TypeError over all place.
Take immediately the opportunity to replace that verbose <link> by a <h:outputStylesheet>. See also How to reference CSS / JS / image resource in Facelets template?

Custom tag attributes are leaking into children

Our application is using Mojarra 2.1.29-03 and we are having a problem with attributes in our custom tags as they are being copied to nested tags as well.
For example, given the following tag definition:
cc.taglib.xml
<?xml version="1.0" encoding="UTF-8" ?>
<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://temp.com/jsf/customcomponents</namespace>
<tag>
<tag-name>wrapper</tag-name>
<source>wrapper.xhtml</source>
<attribute>
<description>The style class for the component</description>
<name>styleClass</name>
</attribute>
</tag>
</facelet-taglib>
wrapper.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">
<ui:component xmlns:ui="http://java.sun.com/jsf/facelets">
<div style="border: 1px solid black; margin: 5px;">
<p>styleClass: #{styleClass}</p>
<ui:insert />
</div>
</ui:component>
</html>
And a client page:
<?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:cc="http://temp.com/jsf/customcomponents">
<h:body>
<cc:wrapper styleClass="cc-style">
<cc:wrapper />
</cc:wrapper>
</h:body>
</html>
The result is as follows:
styleClass: cc-style
styleClass: cc-style
... so the styleClass attribute is also being applied to the inner tag even though the client page does not set it.
We have noted that we can workaround this by processing all our client pages to set styleClass="" if it is not explicitly set but this is an approach we would like to avoid (it's a very ugly solution and cannot be enforced going forward).
Is this a bug? Is there any way to work around it other than that mentioned above - preferably with the workaround in the tag rather than the client pages?
Thanks
Ivor
This is not strictly a bug, but this is indeed unintuitive and undesired behavior which should have been addressed in the JSF/Facelets spec.
The work around solution is not trivial, a custom taghandler is needed to clear out the Facelet scope. JSF utility library OmniFaces has since version 2.1 exactly such one: <o:tagAttribute> (source code here).
Usage (do note that prolog, doctype and html tags are unnecessary, this is the file in its entirety):
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:o="http://omnifaces.org/ui"
>
<o:tagAttribute name="styleClass" />
<div style="border: 1px solid black; margin: 5px;">
<p>styleClass: #{styleClass}</p>
<ui:insert />
</div>
</ui:composition>
Unrelated to the concrete problem, this is not a custom component, but a tagfile. And, in JSF 2.x, the term "cc" is usually associated with composite components, which is a completely different subject altogether. To get your knowledge and terminology right (so that you don't confuse yourself or others while reading your or other's code), head to When to use <ui:include>, tag files, composite components and/or custom components?
For info we identifed an alternative approach that might be of use to others as it is slightly easier to implement and understand.
First I need to add a bit of context to the situation that we found ourselves in ... we had recently migrated from 2.1.12 to 2.1.29-03 and as part of that process we changed one of our building blocks from a composite component (which has isolated scope for its attributes) to a custom tag (which has the behaviour described above). The same behaviour regarding custom tag attributes existed in 2.1.12 but we were unaware of it so we considered the following approach instead as it would restore the behaviour we had prior to migration because we would only need to apply it to the component that we changed.
wrapper.xhtml (I've changed the namespace to 'ct' rather than 'cc')
<ui:component xmlns:ct="http://temp.com/jsf/customtags" xmlns:ui="http://java.sun.com/jsf/facelets">
<ct:tagAttribute name="styleClass" />
<div style="border: 1px solid black; margin: 5px;">
<p>styleClass: #{styleClass}</p>
<ct:eraseAttribute name="styleClass" />
<ui:insert />
</div>
</ui:component>
Where tagAttribute is the solution suggested by BalusC to prevent the tag inheriting attributes from its parents and in addition we call eraseAttribute tag before calling ui:insert to remove the attribute from scope (this obviously requires that the custom tag is finished with the attribute). This means that this one tag neither inherits nor leaks attributes and other tags could remain unchanged and maintain the same behaviour they had prior to migration.
ct.taglib.xhtml (snippet)
<tag>
<tag-name>eraseAttribute</tag-name>
<handler-class>com.temp.jsf.customtags.EraseTagAttribute</handler-class>
<attribute>
<name>name</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
</tag>
EraseTagAttribute.java
package com.temp.jsf.customtags;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagConfig;
import javax.faces.view.facelets.TagHandler;
public class EraseTagAttribute extends TagHandler {
private final String name;
public EraseTagAttribute(TagConfig config) {
super(config);
name = getRequiredAttribute("name").getValue();
}
public void apply(FaceletContext context, UIComponent parent) throws IOException {
context.getVariableMapper().setVariable(name, null);
}
}
Ultimately we did not use it however as we felt the answer provided by BalusC (which we applied to every attribute in all our custom tags) was the correct and cleaner approach even though it might have additional consequences in our very specific situation.

Saving and reusing tag definition in PrimeFaces

Let's say I have the following construct polluting the simplicity of my JSF code in many places:
<p:calendar id="decisionDate"
effect="explode"
yearRange="2000:2100"
pattern="MM/dd/yyyy"
navigator="true" display="inline"
value=""
label="Decision Date"
maxlength="10"
size="20">
<f:convertDateTime pattern="MM/dd/yyyy" />
</p:calendar>
As can be seen, this has nine (9) attributes and a nested tag. This is an awful amount of tedious detail to consume with your eye.
Is there a way I can reuse PrimeFaces tags in a similar way as CSS: to save a complex tag definition as <px:myCalendar/> with the above parameters minus the ID ones, which should be set for each instance of use nonetheless, where px would be my namespace and then each time I need to invoke it, I would just say <px:myCalendar id="uniqueCalID"/> and ... BOOM ... there goes all the repeated clutter?
POST ANSWER EDIT: Check out this tutorial
You can define composite component. It is defined with xhtml+ jsf namespaces and, but in your case it is unnesessary, backing component, which is java class, instantiated for every composite component usage.
Within composite component interface you can define attributes, which vary its behaviour. And in implementation you then can insert needed primefaces' component with some hardcoded attributes and some passed from your composite component invocation.
Consider this tutorial: https://docs.oracle.com/javaee/6/tutorial/doc/giqzr.html
Example
Composite component is resource, so we put it below /resources folder. Let's create subfolder /resources/myCompositeComponents and create xhtml file myCalendar.xhtml there. It will be our composite component. Basically, it is xhtml file with additional namespace xmlns:cc="http://java.sun.com/jsf/composite". Here is the code. You can notice two elements: <cc:interface> and <cc:implementation>. And <cc:attribute> element inside the <cc:interface> is the input of our composite component.
<?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:f="http://xmlns.jcp.org/jsf/core"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui" xmlns:h="http://java.sun.com/jsf/html">
<cc:interface>
<cc:attribute name="label" default="Decision Date"/>
</cc:interface>
<cc:implementation>
<h2>#{cc.clientId}</h2>
<h:outputLabel
id="Label"
value="#{cc.attrs.label}"/>
<p:calendar id="Calendar"
effect="explode"
yearRange="2000:2100"
pattern="MM/dd/yyyy"
navigator="true" display="inline"
value=""
label="Label"
maxlength="10"
size="20">
<f:convertDateTime pattern="MM/dd/yyyy" />
</p:calendar>
</cc:implementation>
</html>
Then, let's use it. To be able to declare our brand new component we will put additional namespace into the using page: xmlns:my="http://java.sun.com/jsf/composite/myCompositeComponents". The last part of the namespace uri corresponds to the folder under /resources, where composite component lives. Give it any prefix you like. Here is source code:
<?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:my="http://java.sun.com/jsf/composite/myCompositeComponents">
<h:head>
<title>Simple JSF Facelets page</title>
</h:head>
<h:body>
<my:myCalendar id="LetsUseIt" label="MyLabel"/>
</h:body>
</html>
Have a notice of attribute "label" - that very attribute, that is declared in the "interface" element.
This is quite basic usecase, though it will help in your situation. More complex scenarios include passing typed attributes and implementing backing component - java class, instantiated every time the component is used.

Private/scoped variable in JSF2/Facelets <ui:component>?

I might not be thinking correctly in terms of visual components in JSF, but I guess that's part of my question. My question is around the seeming lack of scope around variables declared within JSF <ui:component> implementations.
So, say I have /resources/comp/myPanel.xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<ui:component 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:c="http://java.sun.com/jsp/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface>
</cc:interface>
<cc:implementation>
<f:loadBundle var="bundle" basename="panelOnly.bundle" />
<h:outputText value="#{bundle.myText}" />
</cc:implementation>
</ui:component>
And there is a resource bundle that gets loaded in that component, panelOnly/bundle.properties:
myText = This is a panel resource
And then I have a page that places the myPanel component, mainPage.xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<html 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:comp="http://java.sun.com/jsf/composite/comp">
<h:body>
<f:view>
<f:loadBundle basename="mainPage.bundle" var="bundle" />
<comp:myPanel />
<h:outputText value="#{bundle.myText}" />
</f:view>
</h:body>
</html>
and there is a resource bundle that gets loaded in the main page, mainPage/bundle.properties:
myText = This is a main page resource
Now, I would assume that my page should render as:
This is a panel resource
This is a main page resource
But, instead, I get:
This is a panel resource
This is a panel resource
And I assume that is because I clobbered what the "bundle" symbol refers to in my component so that when the mainPage.xhtml tries to resolve that value, it looks to the component's "bundle" object and not the original mainPage's.
My workaround to date has been to just use unique named variables within my components that would never clash with variables on my main pages. But I would prefer if there was a way to coax JSF to recognize anything declared in my component as locally scoped variables and not clobber the caller's symbols.
I think there are and other tags that one can use to make locally scoped variables under #{cc.attrs...}. If you could enumerate my local scoping options in your answer, that would be very helpful. I suspect my <f:loadBundle> is a special case, and maybe there isn't a workaround for that one as it was not designed with <ui:component> in mind.
Thanks!
P.S. I'm running Mojarra 2.1.1 (FCS 20110408)
(edited for formatting and copy and paste bugs 6/15/2011)
Unfortunately, that's how <f:loadBundle> works. It's an one-time setting for the entire view. And any subsequent <f:loadBundle> calls in the same view will just override the previous one.
Your best bet is to manage it by a backing component.
<cc:interface componentType="myPanel">
with
#FacesComponent(value="myPanel")
public class MyPanel extends UIComponentBase implements NamingContainer {
private ResourceBundle bundle;
public MyPanel() {
bundle = ResourceBundle.getBundle("panelOnly.bundle",
FacesContext.getCurrentInstance().getViewRoot().getLocale());
}
#Override
public String getFamily() {
return "javax.faces.NamingContainer";
}
public ResourceBundle getBundle() {
return bundle;
}
}
which can be used as
<cc:implementation>
<h:outputText value="#{cc.bundle.myText}" />
</cc:implementation>

Facelet Custom Component - prevent rendering

After reading this answer, I am still stumped. I agree that JSTL should be avoided and understand how its evaluation occurs in the wrong phase. However, per the documentation on the facelets development site, it appears that <ui:fragment> tags only supports two attributes, id and binding. So, even if some implementation support rendered, it seems like you would be tempting fate to make use of it. The other suggestion was to use <h:panelGroup>, however, that inserts a <div> element in the response which could cause undesirable side effects (like changing your content from inline to block). Does anyone know a way around this? In particular, I am attempting the following:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:ice="http://www.icesoft.com/icefaces/component"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition>
<ice:selectOneListbox binding="#{binding}" rendered="#{modeExisting}">
<f:selectItems
value="#{binding.allTagsSelectItems}" />
</ice:selectOneListbox>
<ice:inputText binding="#{binding.name}" />
<ice:inputText binding="#{binding.description}" />
</ui:composition>
</html>
Which is basically a listbox used to select an element with a name and description which when selected will allow the user to edit them. I could put an <ice:panelGroup> around the block, and use the rendered attribute of it, but again, there could be side effects of injecting that additional div. Is there any way to make this work?
Also, it may be worth mentioning that I am using the above custom component paired with this facelet-taglib:
<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://www.mitre.org/asias/jsf</namespace>
<tag>
<tag-name>configurationTagEditor</tag-name>
<source>../component/configurationTagEditor.xhtml</source>
</tag>
<tag>
<tag-name>configurationTagSelector</tag-name>
<source>../component/configurationTagSelector.xhtml</source>
</tag>
<tag>
<tag-name>configurationTagRegexTable</tag-name>
<source>../component/configurationTagRegexTable.xhtml</source>
</tag>
</facelet-taglib>
To allow me to use this in my jsf xhtml:
...
<ice:panelTab label="Existing" styleClass="configurationTagsExisting">
<m:configurationTagEditor tag="#{configuration.existingTag}" />
</ice:panelTab>
...
The other suggestion was to use <h:panelGroup>, however, that inserts a <div> element in the response
The <h:panelGroup> doesn't render a <div> by default. It only renders that if you add layout="block". For all other HTML attributes (like id, styleClass, etc), it only renders a <span>. If no layout attribute is present and all other HTML attributes are absent, it renders nothing.

Resources