PrimeFaces rendered attribute impact on performance - jsf

I'm developing a JSF application with PrimeFaces in which i plan to use mainly tabViews (multiple ones). To give you a general idea about how the application is going to work, I have a side menu from which the user should be able to choose "modules" that will display in the center layout as Tabs. Seeing as I have multiple "modules" and there will be more in the future, the solution I've decided on using is writing the code for all the tabs I have in the xhtml and then using the rendered attribute (set to false by default) in order to display them (when the user clicks on the corresponding menu).
Now comes my question, is setting a component's rendered attribute to false equivalent to that component not being there at all (no impact at performance at all)?

Now comes my question, is setting a component's rendered attribute to false equivalent to that component not being there at all (no impact at performance at all)?
It's NOT equivalent. If you set rendered=false, the component is still there in the component tree on the server side. Therefor it costs a little bit performance and memory.
Mojarra also had big performance problems in the past when the component tree is bigger: https://blog.oio.de/2013/05/16/jsf-performance-mojarra-improves-dramatically-with-latest-release/

To use your xhtml page like a template, follow this steps
Step 1 : Create my included page
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
>
<h:form id="form">
...
</h:form>
</ui:composition>
Let say that the name of this page is myTemplate.xhtml
Step 2 : use your template page each time you need it
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="/templates/templateCrb.xhtml"
xmlns:p="http://primefaces.org/ui"
>
<ui:define name="MyContent">
<ui:include src="/pages/.../myTemplate.xhtml">
</ui:include>
</ui:define>
</ui:composition>
In this case i included a complete page, but you can use it in a dialog, a tabView, you can also send parameter to you include element.
You can read more in more informations about include.
Hope that helped you.

Related

Best way to extend a particular section in JSF multilevel template

I have a multi level JSF template, say layout.xhtml, which extends from number of template which is depicted below.
layout.xhtml -> level3.xhtml -> level2.xhtml ->level1.xhtml
How to extend level1.xhtml and add one extra facelets ( I want 2 facelets overall) say customer-data.xhtml and supplier-data.xhtml ) inherited from level1.xhtml in place of navigation-module, and have all the facelets of layout.xhtml too?
Below is my template/level1.xhtml
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:insert name="navigation-module" />
<ui:insert name="time-module" />
</ui:composition>
I want to get the common template i.e. layout.xhtml I am not getting how to do this.
I believe that you want to add two pages for the navigation-module. Its very easy, just do the below
<ui:composition
template=template/layout.xhtml
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:define name="navigation-module">
<ui:insert name="WEB-INF/customer-data.xhtml" />
<ui:insert name="WEB-INF/supplier-data.xhtml" />
</ui:define>
As long as you provide the correct ui:insert name i.e. in your case it is navigation-module, and in your ui:define you are telling to JSF, please insert these pages in place of navigation-module. Two keypoints to note here are
Make sure you mention your template name i.e. you can see immediate after ui:composition tag, i.e. template/layout.xhtml ( the reason being you want all the template features)
Use the exact name you want to override in ui:define i.e. in your case it is navigation-module
I hope I am clear to you. Incase you need any further clarification please feel free to drop a comment.

JSF: how avoid 'Component ID has already been found in the view.' error on double insert of composite component

I know what causes the following problem. I am looking for an elegant way to address the problem rather than a brute-force (and non-DRY) workaround I've found.
I have a highly reusable h:form in a template (and I am aware of the dangers of "god forms", this is not quite a god form), and I insert editable content into that form via the template, with an identical action bar of command buttons both at the top and the bottom of the page. (There hundreds of clients to this template, and some insert different actions bars into the template.)
The only reason I am doing this (bar top and bottom) is user convenience; I have found when using many content management systems that it is annoying to have to scroll down or scroll up to find a Save button (or other buttons in an action bar) on long forms.
The template (please don't tell me it's a "god form") has:
<h:form prependId=".." id="form">
<div id="actions-upper" class="actions">
<ui:insert name="actions"/>
</div>
... other reusable stuff
<div id="actions-lower" class="actions">
<ui:insert name="actions"/>
</div>
</h:form>
Every edit.xhtml page (there are lots of them) that is a client to a template inserts the action bar, along with a compatible #{manager} backing bean parameter:
<ui:composition template="/template.xhtml">
...
<ui:define name="actions">
<util:edit_actions id="edit_actions" manager="#{manager}"/>
</ui:define>
... other insertions with editable content omitted
Note how above I have given that CC `util:edit_actions' an id (which I did not do on this CC until recently for reasons I'll explain below).
So you can see that the exact same actions toolbar is inserted into the top and bottom just inside form section of a page. If, however, you do this as shown above with an id passed for edit_actions you get:
javax.servlet.ServletException: Component ID edit_actions has already been found in the view.
I have been using this template with success for years until I introduced the explicit id, for reasons now illustrated below.
The edit_actions CC has some command buttons such as:
<composite:implementation>
<p:toolbar>
<p:toolbarGroup>
<p:commandButton
ajax ="true"
action="#{cc.attrs.manager.crud.update}"
value="Save"
update="#form"
id="save"
/>
...
Now that general Save button is not always the only button in the form; there are sometimes other buttons that perform interim AJAX actions with conditionally required input fields, such as this from an embedded links table editor:
<p:inputText
id="newLinkUrl"
value="#{cc.attrs.manager.newLinkUrl}"
required="#{param['edit_actions:save']==null}"
validator="urlValidator"
/>
<p:commandButton
value="Add new link !"
action="#{cc.attrs.manager.addNewLink(cc.attrs.element)}"
update="... newLinkUrl ..."
/>
(Where BTW that urlValidator does NOT throw on null, the system relies on the conditional required for that so that the general #form Save always works.)
But to get the conditional required to work:
required="#{param['edit_actions:save']==null}"
I have to give the inserted edit_actions CC an explicit id whenever performing the insert in any of the hundreds of edit.xhtml client pages that use it:
<ui:composition template="/template.xhtml">
...
<ui:define name="actions">
<util:edit_actions id="edit_actions" manager="#{manager}"/>
</ui:define>
But as shown above, if I do include the id there, it now causes an error (but without it I can't use the conditional required trick).
There are two workarounds I've found so far:
Simply don't have the action bar in the template twice. This is unacceptable, it simply breaks the feature by avoiding it.
Having 2 different insertion points in the template does work, but you have to be careful with the IDs.
And are problems with the 2nd one:
<ui:composition template="/template.xhtml">
<ui:define name="actions_upper">
<util:edit_actions id="edit_actions_upper" manager="#{manager}"/>
</ui:define>
<ui:define name="actions_lower">
<util:edit_actions id="edit_actions_lower" manager="#{manager}"/>
</ui:define>
Note that this code above is not Don't Repeat Yourself (DRY) code, which I consider one of the most important coding practices, and something JSF is usually particularly good at addressing. Ensuring that the above template insertion pattern and id pattern is addressed in hundreds of edit.xhtml page is just plain error prone, unless I can somehow encapsulate that ui:define pair while still being able to inject any compatible #{manager}.
And the conditional required test then has to test on both upper and lower Save buttons:
<p:inputText
id="newLinkUrl"
value="#{cc.attrs.manager.newLinkUrl}"
required="#{param['edit_actions_upper:save']==null and param['edit_actions_lower:save']==null}"
validator="urlValidator"
/>
All in all, a rather ugly non-DRY workaround.
Q1: Is there any way I can somehow dynamically change the id of an inserted edit_action.xhtml automatically so that it can appear in the template in 2 different places without a clashing component id error ?
Q2: Alternatively, is there some way I can encapsulate the two ui:define in the workaround for the upper vs lower bar insertion (as show in workaround 2.), while still having the ability to inject the #{manager} (so that I can include it and reuse it as encapsulated policy in hundreds of edit.xhtml clients to the template) ?
EDIT: this attempt to encapsulate my "double action bar" pattern does not seem to work. From /include/edit_actions_defines.xhtml:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:util="http://xmlns.jcp.org/jsf/composite/util">
<ui:define name="actions_upper">
<util:edit_actions id="edit_actions_upper" manager="#{manager}"/>
</ui:define>
<ui:define name="actions_lower">
<util:edit_actions id="edit_actions_lower" manager="#{manager}"/>
</ui:define>
</ui:composition>
With attempted use by edit.xhtml:
<ui:composition template="/template.xhtml">
<ui:include src="/include/edit_actions_defines.xhtml">
<ui:param name="manager" value="#{specificManager}"/>
</ui:include>
Seems to be ignored silently.
I've found an solution (workaround really) to my own problem meeting my requirements. Not pretty, but might be of use to others.
Instead of testing for a specific component id, I use a regexp:
/**
* Searches for a component id ending in ":save".
*
* #return
*/
public boolean isSaveButtonPressed() {
Map<String, String> parameterMap = FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap();
for (String key : parameterMap.keySet()) {
boolean matches = Pattern.matches("^j.*:save",key);
if (matches) return true;
}
return false;
}
And the required test is simply:
<p:inputText
id="newLinkUrl"
value="#{cc.attrs.manager.newLinkUrl}"
required="#{not cc.attrs.manager.saveButtonPressed}"
validator="urlValidator"
/>
Then when inserting my util:edit_actions component (which is to appear both top and bottom of the form via the template for user convenience) I don't pass it an explicit id, I just let JSF generate them, and they are different (no longer clash) for both Save buttons.
So I can have my twice-injected edit_actions cake and eat it. The required test on the URL string field fails correctly as desired for both Save buttons.

How to render XML from a JSF 2.0 page

I'd like to build VXML using JSF2.0 but I didn't find any supporting tags. What we've proposed is writing xhtml pages with vxml data (having references to backing bean where ever value needs to get replaced) by having content type as 'text/xml' so client can read the xml directly.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view contentType="text/xml">
<vxml>
<log>Caught the event </log>
<prompt bargein="true">
<audio src="built-in: #{myBackingBean.prompt}" />
</prompt>
</vxml>
</f:view>
</html>
But when ever I try to launch above xhtml page in a browser or using a REST webservice client -
1) I'm not seeing xml returned. But just Caught the event as output in browser. REST client is not seeing any output.
2) myBackingBean.prompt value is not getting replaced
Can any one suggest please? We do not want to use plain old servlets to construct the xml. We'd like to write XML manually but need values to be replaced from backing bean.

Unable to understand <h:head> behaviour

I have a template composition Button.xhtml which contains a <p:commandLink>:
<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:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<p:commandLink value="View" action="#{printClass.printPdf}"/>
</ui:composition>
The link's purpose is to generate PDF.
I have a template client defaultPage.xhtml where the Button.xhtml is been included.
<ui:composition template="../../WebPages/MasterPage/Template.xhtml">
<ui:define name="MainContent">
<ui:include src="../../WebPages/Facelets/Button.xhtml"/>
</ui:define>
</ui:composition>
The last one is Template.xhtml which inserts the MainContent template definition inside a <h:form>.
<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">
<h:body>
<h:form>
<ui:insert name="MainContent" />
</h:form>
</h:body>
</html>
When I place <h:head></h:head> in Template.xhtml, then the <p:commandLink> in Button.xhtml stops working, but CSS of page works perfect. When I remove the <h:head></h:head> or replace it by <head></head> then the <p:commandLink> starts working, but CSS stops working.
How is this caused and how can I solve it?
The <h:head> will auto-include all necessary JavaScript files for ajax behavior and CSS files for layout. When you remove it, then CSS will not be auto-included and ajax behavior will not be enabled. The <p:commandLink> would then act like as a plain vanilla link.
The <h:head> is absolutely necessary for proper functioning of JSF and PrimeFaces components and applying of the PrimeFaces look'n'feel. So you should not remove or replace it.
Let's concentrate on the problem of the failing <p:commandLink>. There are relatively a lot of possible causes, which are all mentioned in this answer: commandButton/commandLink/ajax action/listener method not invoked or input value not updated
You didn't show a fullworthy SSCCE, so it's impossible to copy'n'paste'n'run your code to see the problem ourselves (work on that as well in your future questions). So, I'll just mention the most probable cause for this problem based on the symptoms: you're nesting <h:form> components in each other. Placing the <h:form> in the master template is also a design smell. You should rather place it in the template client. Als note that the <p:dialog> should have its own form but that the <p:dialog> should by itself not be nested in another form.
Update: based on the comments, you're trying to return a whole PDF file as a response to an ajax request. This will indeed not work. The ajax engine expects a XML response with information about changes in the HTML DOM tree. A PDF file isn't valid information. Also, JavaScript has for obvious security reasons no facilities to programmatically trigger a Save As dialogue whereby possibly arbitrary content is provided.
You can't download files by ajax. You have to turn off ajax. In case of <p:commandLink> there are basically 2 solutions:
Use ajax="false".
<p:commandLink ... ajax="false" />
Just use <h:commandLink> instead.
<h:commandLink ... />
In Button.xhtml where you placed
<h:commandLink value="View" action="#{printClass.printPdf}"/>
You need to disable the ajax.So your new code should be like
<h:commandLink value="View" action="#{printClass.printPdf}">
<f:ajax disabled="true"></f:ajax>
</h:commandLink>

JSF custom tag wrapper dynamic parameters

I am trying to create a custom tag that will act as a wrapper to standard components and will define values for some common attributes
For example the custom tag will look like this
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jstl/core">
<rich:datascroller fastControls="false" fastStep="false" maxPages="20" id="#{value}"/>
</ui:component>
Then i will be able to use this tag every time i need a datascroller component like
<my:dataTable id="componentId"/>
My question is whether i can provide my custom tag with attributes that will be "transfered" to the jsf component without specifying each one explicitly. For example consider the following use of my custom component
<my:dataTable id="componentId" pagesVar="books" stepControls="true"/>
and this one
<my:dataTable id="componentId" pagesVar="items" renderIfSinglePage="false"/>
Attributes pagesVar, stepControls, renderIfSinglePage should be passed to the rich:datascroller component. I know i can do something like this
<rich:datascroller pagesVar=#{pagesVar ? pagesVar : ''} stepControls=#{stepControls ? true: false}/>
but i am wondering if there is a way to pass all attributes without specifying each one of them
but i am wondering if there is a way to pass all attributes without specifying each one of them
No, tag attributes does not support any form of inheritance.
You can however simplify your particular example more.
<rich:datascroller pagesVar="#{pagesVar}" stepControls="#{stepControls}" />

Resources