I'm using Richfaces to develop some web pages, with a datatable I try to display some data information from remote server. But its quite slow to load all data in one time, so I use a cache to store data, Firstly my cache is empty and data table is empty.
The ideal goal is loading one row from server(let say 1mins for each row) and store into my cache, then append into data table's end, my question is how can I render the content of data table from managedbean once I retrieve some new data into cache?
I also use a timer to update the cache values from server during a fixed period (1hour), that means later, new data could be added into cache, and old data could be removed from cache, that all depend on server's latest data. same question when I get a fresh cache and need rerender data table content according to cache values.
Thanks,
The most easy way to do this is rerendering your table. There are two approaches to do this using RichFaces library:
Client Side
The a4j:poll component defines a way to periodically poll a server in order to trigger state changes, or update parts of your page. It uses a timer to trigger each N milliseconds.
You can use it to check your cache data on your server and then rerender your table.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition 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:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<h:form>
<a4j:poll id="poll" interval="2000" enabled="#{pollBean.pollEnabled}" render="poll,grid" />
</h:form>
<h:form>
<h:panelGrid columns="2" width="80%" id="grid">
<h:panelGrid columns="1">
<h:outputText value="Polling Inactive" rendered="#{not pollBean.pollEnabled}"></h:outputText>
<h:outputText value="Polling Active" rendered="#{pollBean.pollEnabled}"></h:outputText>
<a4j:commandButton style="width:120px" id="control" value="#{pollBean.pollEnabled?'Stop':'Start'} Polling"
render="poll, grid">
<a4j:param name="polling" value="#{!pollBean.pollEnabled}" assignTo="#{pollBean.pollEnabled}" />
</a4j:commandButton>
</h:panelGrid>
<h:outputText id="serverDate" style="font-size:16px" value="Server Date: #{pollBean.date}" />
</h:panelGrid>
</h:form>
</ui:composition>
More information on RichFaces a4j:poll.
Server Side
The a4j:push works as a consumer/producer architecture, which uses no timer, instead it uses a message that will instruct the client to re-render part of the page.
Using this component you will be able to have an impact on the client side (rerender HTML) from the java methods in your ManagedBean. Maybe the problem here will be to communicate your current cache architecture with your JSF Managed Bean.
More information on RichFaces a4j:push.
Regards,
Related
I've been facing some problems using JSF with AJAX to render a table without reloading the whole page every time I submit a form.
When I first run the server, my database is empty, so the page is supposed to show only a form to add books. When user submits the form, a fieldset whith all books is supposed to be rendered. I don't want this fieldset to be shown when database is empty.
This is a simple version of my code (it is just a small form and a table to be refreshed using AJAX):
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!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:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
<h:graphicImage library="img" name="caelum-logo.png"/>
<h:form>
<p>Book Title:</p>
<h:inputText id="title" value="#{livroBean.livro.titulo}" />
<h:commandButton value="Add book" action="#{livroBean.addFirstBook}">
<f:ajax execute="#form" render="title :addedBooksTable" />
</h:commandButton>
</h:form>
<div id="addedBooksTable">
<p:fieldset rendered="#{livroBean.numberOfBooks > 0}">
<h:dataTable value="#{livroBean.allBooks}" var="book">
<h:column>
<h:outputText value="#{book.titulo}" />
</h:column>
</h:dataTable>
</p:fieldset>
</div>
</h:body>
</html>
And i wanna focus on this part:
<h:commandButton value="Add book" action="#{livroBean.addFirstBook}">
<f:ajax execute="#form" render="title :addedBooksTable" />
</h:commandButton>
The fieldset and the table inside it are supposed to be hidden when there's no book added to the database, that's why i used <p:fieldset rendered="#{livroBean.numberOfBooks > 0}">. But I want it to be rendered after I click the commandButton, even if there's nothing at the inputText.
Here's what's happening when I test the code:
if I test the code just as it is with an empty database, the inputText is refreshed (it "erases" what were typed before the submisssion) when I click on the commandButton, but the fieldset is not. I know that the fieldset has a rendered="#{livroBean.numberOfBooks > 0}" and the inputText does not, but the method getNumberOfBooks is called everytime i click the commandButton, that's why I don't get it...
if I change the f:ajax tag so it ends up like this <f:ajax execute="#form" onevent="click" render="title :addedBooksTable" />, it solves the problem, but i can realize the screen flashing for a while when I click the commandButton. As far as I know, one of the uses of AJAX is that we don't want the screen flashing when a request is made.
Why is the fieldset rendered only when I use onevent="click"? Should I consider the flashing something normal? Is there a more elegant solution for that?
Thanks!
You can't ajax-update a plain HTML element. You can only ajax-update a JSF component. Simple reason is that the target must be resolveable by UIViewRoot#findComponent(), so that JSF can find it in the component tree and render the updated HTML into the Ajax response.
Replace
<div id="addedBooksTable">
by
<h:panelGroup layout="block" id="addedBooksTable">
Normally, this should have thrown an exception as described in How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar", but they removed this check in Mojarra 2.2.5 in order to support ajax-updating a specific iteration of <ui:repeat> and <h:dataTable> (this missing check will be fixed later on as that's indeed unhelpful to starters like you).
As to why adding onevent="click" appear to work, that's because it caused a JavaScript error which in turn caused the whole JavaScript/Ajax thing to break down, which in turn caused that the command button fall backs to default synchronous behavior with a full page reload (as if you aren't using <f:ajax> at all). You likely meant to use event="click" instead. The onevent attribute serves a different purpose. See also a.o. Proccess onclick function after ajax call <f:ajax>.
we are building a Java EE 7 website and having a problem with performance in some situations.
We are using the following components and technologies:
Java 1.7
JSF 2.2
EclipseLink 2.5.1
PrimeFaces 4.0
Glassfish Server 4.0
Advantage Database Server 10.10
So, what is our problem exactly? In our main page (round about 2000 DOM elements, mainly JSF and Primefaces elements) we are using the actionListener-Tag of a p:commandButton to call a Java method in a backing bean which opens a dialog (JaNeinDialog) of the primefaces dialog framework.
Since our JaNeinDialog is quite simple, we would expect it to be opened in the browser (firefox 27.0.1) almost immediately. But in fact, it takes 1-2 seconds unitl it is visible.
Amazingly, we have found out, that this waiting time is directly dependent from the original place from where it has been called: As soon as this commandLink is located within a very simple xhtml-page, we see what we had expected: The dialog opens with almost no delay.
So the question is: Why depends the loading time of the same dialog from the complexity of the page from where it has been called?
p:CommandButton which calls a Java method in order to open the JaNeinDialog:
<p:commandLink ajax="true" process="#this"
actionListener="#{patientController.starteMitarbeiterSucheDialog()}">
<p:graphicImage value="/resources/img/png/find_1.png" width="18"
height="21" title="Suche nach Mitarbeiter" />
<p:ajax event="dialogReturn" update="editPflegeDatenPanel"
listener="#{patientController.setPatientMitarbeiter}" />
</p:commandLink>
JaNeinDialog.xhtml:
<!DOCTYPE html>
<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"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title><h:outputText
value="#{stringKonstanten.jaNeinDialogTitel}"/></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"></meta>
<h:outputStylesheet library="css" name="jortho.css" />
</h:head>
<h:body>
<h:form>
<center>
<p:panelGrid id="JaNeinDialogPanel" cellspacing="5">
<p:row>
<p:column colspan="2">
<center>
<h:outputText value="#{jaNeinDialogController.dialogText}" />
</center>
</p:column>
</p:row>
<p:row>
<p:column colspan="2">
<center>
<h:outputText value="Aktion ausführen?" />
<BR />
<BR />
</center>
</p:column>
</p:row>
<p:row>
<p:column>
<center>
<p:commandButton id="positiveButton"
actionListener="#{jaNeinDialogController.entscheidungWeiterleiten(true)}"
value="#{stringKonstanten.ja}" icon="ui-icon-check" />
<p:commandButton id="negativeButton"
actionListener="#{jaNeinDialogController.entscheidungWeiterleiten(false)}"
value="#{stringKonstanten.nein}" icon="ui-icon-close" />
</center>
</p:column>
</p:row>
</p:panelGrid>
</center>
</h:form>
</h:body>
</ui:composition>
The used JSF version is the standard Mojarra 2.2.0 implementation which comes along with the Glassfish 4 server.
We've also checked, that there are no scripts being loaded in the body section. Only 2 scripts are
loaded in the head section.
Trying the suggestion with flushing, we have followed BalusCs instuction on
How to flush buffer early in JSF 2.0? in
order to reduce the waiting time for the response. Indeed, this waiting time has decreased by
round about 150 ms, but came along with some strange side-effects. Since BalusC does not recommend
to use this approach, we reverted this changes.
Using the Firefox-plugin YSlow, we have measured the response time until the dialog shows up. The waiting time for the first element (main.xhtml)
takes more than 800 ms waiting time. But the size of this first element is only
987 B. So, how can we find out, what exactly happens in the waiting time of the first element?
We have learned from https://blog.oio.de/2013/05/06/jsf-performance-tuning/ that changing the
JSF implementation from Mojarra to MyFaces will improve the performance significantly and we will
try to change it now at our Glassfish web server.
We would greatly appreciate any help. Thanks a lot in advance!
UPDATE:
Like suggested from lu4242 (thanks a lot for your assistance!), we tried to change the JSF implementation from Mojarra 2.2.0 to MyFaces.
Unfortunately, we were not able to deploy our application after we did this. The whole procedure is described here:
Java EE 7 Application not deploying on Glassfish 4 Sever after switching from Mojarra to MyFaces
After that, we learned from http://blog.oio.de/2013/05/16/jsf-performance-mojarra-improves-dramatically-with-latest-release/
that since Mojarra Version 2.1.22 the vast performance loss for sites with a high amount of DOM elements has been fixed.
Therefore we updated Mojarra from version 2.2.0 to 2.2.6, but there is still no improvement of our waiting time. Regardless of what we are doing on our main page, we still have a waiting time of round about 700ms.
YSlow shows, that the size of data transferred from server to browser is minimal (less than 10KB). But the main page is keeping the server busy for a much too long time.
So, we would appreciate any more tipps on this topic.
Thanks a lot in advance.
I want to share my experience using primefaces, f:viewParam and p:commandButton, and ask a few questions.Take a look at this page:
<?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:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<f:metadata>
<f:viewParam required="true" name="id_file" value="#{bean.idFile}" />
</f:metadata>
<h:form id="tableform" prependId="false">
<p:commandButton actionListener="#{bean.myMethod())}" icon="ui-icon-search" title="View" />
</h:form>
<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true" />
</h:body>
</html>
The backing bean have a "myMethod()" method that does nothing. When you enter the page it expects the "id_file" parameter and put it in the idFile property of the backing bean. Then you click the button and the myMethod is called. Then you click again and you get an obscure validation error and myMethod is never called:
j_idt1: Validation Error: Value is required.j_idt1: Validation Error: Value is required.
First of all, remember that without p:messages you can't see this message, you have to dig the XML that primefaces send on ajax calls. Secondly, after 4 hours of debugging I've tried to change the f:viewParam like this:
<f:viewParam name="id_file" value="#{bean.idFile}" />
without "required": magically everything start working, I can click 1,2,3,etc and myMethod is called every time. So, the problem is that the ajax submit validate the parameter specified with f:viewParam, it sounds silly to me, but ok, I can live with it.
My questions are:
why this validation error doesn't appear the first time button is clicked? If you look at the ajax POSTs they are identical
it is supposed to be ok to validate the view parameters (that, in my idea, belongs to the view) on a partial ajax call?
is there a way to tell to primefaces not to validate on particular ajax request (process="#this" does not resolve)?
Thank you, I hope that my experience will allow you to avoid spending hours doing debugging!
The viewParam is a UIComponent. That means it's semantically no different from a <h:commandButton/> or a <h:inputText/> and it's liable to go thru every prescribed JSF request processing lifecycle phase, up to and including validation and conversion. In fact, the tag itself causes any given view to go into the full processing of any given page, just by being there
The <p:commandButton/> is going to do a postback, meaning, it's going to be re-requesting the same view, using a POST. So to solve your current problem, you need to base your required condition on that fact:
<f:viewParam required="#{!facesContext.postback}" name="id_file" value="{bean.idFile}"/>
What you get from the new condition is that the parameter will be required only on the first request. Subsequent postbacks will not trigger the condition. Just be sure you don't have any logic (maybe in a #PostConstruct that's built around that expectation
I don't know if I'm doing something wrong or if it might be a bug or something.
My setup contains IntelliJ IDEA 12, JBoss AS 7.2.0.Final, Richfaces 4.3.4 within a war-File within an ear-Project (no Maven).
I have this index-page:
<ui:composition 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:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich">
<rich:notifyMessage stayTime="3500" showShadow="true" showCloseButton="true" />
<f:view>
<h:head> <title> title </title> </h:head>
<h:body>
<!-- some more divs for page-design, but commented out at the moment -->
<div id="page">
<div id="index_workspace" style="width:1000px;margin:auto;">
<h:panelGrid columns="2" id="index_workspace_table">
<rich:panel id="index_workspace_navi_left" style="width:180px;min-height:600px;max-height:600px;">
<ui:include src="general/navi_left.xhtml"/>
</rich:panel>
<rich:panel id="index_workspace_content" style="width:550px; min-height:600px; max-height:600px;" rendered="#{not empty naviBean.content}">
<a4j:outputPanel id="index_workspace_content_ajax" ajaxRendered="true">
<ui:include src="#{naviBean.content}" id="current_site" />
</a4j:outputPanel>
</rich:panel>
</h:panelGrid>
</div>
<!-- some more divs for page-design, but commented out at the moment -->
</div>
</h:body>
</f:view>
</ui:composition>
Within the section I load the pages with forms and all the other cool stuff RF brings. But I have a rendering problem with this part of a loaded page:
<rich:select id="someID_1" rendered="true" immediate="true" required="true" enableManualInput="true" defaultLabel="someLabel">
<a4j:ajax render="true">
<f:selectItems id="selectlist" value="#{BackingBean.SelectableItem-ListGetter}"/>
</a4j:ajax>
</rich:select>
And here my problem is located:
This drop-down list only gets rendered on a page reload, e.g. F5 or CTRL-R action.
Also I could observe that if I set this element on some Kind of a "start page" (initially loaded on the index.xhtml) it gets rendered very well. In this case every other page containing this kind of element renders it correctly also.
I tried
updating JSF from 2.1 to 2.2.1 - that only brought up more problems - so I rolled it back.
The "standard" h:selectOneMenu behaves the same.
additional options within rich:select (e.g.: rendered, immediate, required, ...)
different ajax commands within the navigation (server, client, ajax, on different levels)
googling around since days - found no useable hint
I would appreciate every hint that guides me into the right direction as I feel confident, that I make some mistake I can't figure out...
Additionally my navigation looks like this (in another div on the index.xhtml):
<ui:composition 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:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich">
<h:form id="navi_left">
<rich:panel>
<rich:panelMenu itemMode="ajax" groupMode="ajax" itemChangeListener="#{naviBean.updateContent}" >
<rich:panelMenuGroup itemLeftIcon="disc" label="Erfassung" name="#{naviBean.content}">
<rich:panelMenuItem label="someLabel_navi" name="path/to/page-not-getting-rendered-well.xhtml"/>
</rich:panelMenuGroup>
</rich:panel>
</h:form>
</ui:component>
Hope this helps helping me.
<a4j:ajax render="true">
<f:selectItems id="selectlist" value="#{BackingBean.SelectableItem-ListGetter}"/>
</a4j:ajax>
The above construct is not legal(as you've already seen yourself). The render attribute in there is not used for what you'd expect: to conditionally render the component; Rather, it's supposed to contain a list of on-page components to update via ajax.
To achieve the output I presume you're trying to get, you should use the following instead:
<a4j:region>
<rich:select id="someID_1" rendered="true" immediate="true" required="true" enableManualInput="true" defaultLabel="someLabel">
<f:selectItems id="selectlist" value="#{BackingBean.SelectableItem-ListGetter}"/>
</rich:select>
<a4j:region>
I think I found the problem. As my navigation and my desired site with the not correctly rendered component lie nested in <div>s on the third participating site - my index.xhtml - it seems to be impossible to let a jsf-component be rendered without having all (i.e. the navigation and the desired) sites processed on the server. So the following code-snippets work for my situation:
index.xhtml snippet:
<rich:panel id="index_workspace_content" style="width:550px; min-height:600px; max-height:600px;" rendered="#{not empty naviBean.content}">
<ui:include src="#{naviBean.content}" id="current_site" />
</rich:panel>
navi_left.xhtml snippet:
<h:form id="navi_left">
<rich:panel>
<rich:panelMenu itemMode="server" groupMode="client" itemChangeListener="#{naviBean.updateContent}">
<rich:panelMenuGroup label="someLabel" name="#{naviBean.content}">
<rich:panelMenuItem label="anotherLabel" name="path/to/page-being-rendered-correctly.xhtml"/>
</rich:panelMenuGroup>
...
</h:form>
component snippet in the desired.xhtml:
<rich:select id="someId" rendered="true" immediate="true" required="true" enableManualInput="true">
<f:selectItems var="#{backingBean.selectableItemList}" id="selectlist" value="#{backingBean.predefinedItem}"/>
</rich:select>
So what I have changed is the itemMode to "server", both of the others (ajax and client) will not work!
Setting the groupMode to "client" does not affect the renderprocess of desired.xhtml as it only describes the way the rich:panelMenu behaves.
What makes me feel a bit confused is, that the URL now gets extended with a "/index.xhtml". Before the change it was always just the url:port/context (e.g. localhost:8080/app ).
So it works now, but maybe it's not really what I wanted. I'll observe and report future facts concerning this itemMode-option here.
Hi JSF experts out there ...
<?xml version="1.0" encoding="UTF-8"?>
<!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"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:o="http://omnifaces.org/ui">
<h:head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
</h:head>
<h:body>
<h:form>
<o:validateOneOrMore components="one two three" id="validate"/>
<p:message for="validate"/>
<p:inputText id="one" value="#{testBean.valueOne}">
<p:ajax event="change" process="#this" update="#form"/>
</p:inputText>
<p:inputText id="two" value="#{testBean.valueTwo}">
<p:ajax event="change" process="#this" update="two"/>
</p:inputText>
<p:inputText id="three" value="#{testBean.valueThree}">
<p:ajax event="change" process="#this" update="one two validate"/>
</p:inputText>
<p:commandButton process="#form"
update="#form"
value="Submit"
partialSubmit="true"
action="#{testBean.submit}"/>
</h:form>
</h:body>
</html>
a simple form with requirement of at least one form filled, immediate error reset and tab-able.
But i didn't get it work, tried different things as you can see in sample code.
What happens
hit submit -> error message shown: fine
enter entry in field one and leave with tab: fine (all fields are not in error state anymore and message is gone) BUT focus lost after complete AJAX update. Ok expected behavior of JSF and browsers as i read here, but how to solve?
delete all entries, hit enter -> input in field three and leave the field ... nothing changes ... even message is not gone sth. i also do not understand, since i updated all fields
Is there any solution out, for having a form like that ... where after each input validation of form will happen (meaning remove such global errors) and still have it quickly usable by using the tab-key?
thx.
This is a very annoying issue, which has to do with the way JSF preforms partial renders, there is an in depth post regarding JSF 2 AJAX focus issues.
Which offers a potential solution in the form of using the JSF JavaScript API to listen for triggered AJAX request and refocusing, have a look at the post for further details.