Motivation: I want to reduce the size of the page when is accessed, so I thought that lazy rendering on modalPanels would help. The idea is to render the modalPanel when the user clicks the link that displays it.
I want to lazy render on rich:modalPanel when the link to display it is clicked. To achieve this I've found a way:
Code of the modalPanel, wrapped inside a a4j:outputPanel
<a4j:outputPanel id="a4jPanel">
<rich:modalPanel id="panel" rendered="#{bean.renderPanel}">
<!-- here modalPanel things -->
</rich:modalPanel>
</a4j:outputPanel>
Code of the backing bean (session scope):
public boolean isRenderPanel() {
return renderPanel; //default value is false;
}
public void setRenderPanel(boolean value){
this.renderPanel=value;
}
public setRenderFalse(){
this.setRenderPanel(false);
}
Code of the page where it is invoked:
<a4j:form>
<a4j:jsFunction name="setRenderFalse" action="#{user.setRenderFalse}"/>
<a4j:commandLink value="render and show" oncomplete="Richfaces.showModalPanel('panel');setRenderFalse();" reRender="a4jPanel">
<f:setPropertyActionListener target="#{user.renderPanel}" value="true" />
</a4j:commandLink>
</a4j:form>
Problems:
The modalPanel needs to be wrapped inside an a4j:outputPanel because reRendering directly the modalPanel does not work (I never understood why).
After rendering it, an extra request is needed to set the render value to false (the bean is session scoped). Otherwise if we reload the page there would not be any lazy rendering because the value was set to true.
The backing bean has to handle one property to keep the state for each modalPanel, although this property is set to true whenever the link is clicked and set to false when the request is finished. I've tried to keep the rendered state with JS variables but it does not seem to work (they are just read once the page is loaded and never again).
Any more elegant way to do this?
There is a nice solution regarding your question. All is needed is a way to detect postback and couple of xhtmls.
First of all we need a bean that will help with indication of postback
public class HelperBean {
public boolean isPostback() {
FacesContext context = FacesContext.getCurrentInstance();
return context.getRenderKit().getResponseStateManager().isPostback(context);
}
}
empty.xhtml - for a blank content
<ui:composition 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/jstl/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
</ui:composition>
modal.xhtml - for wrapping the modal definition
<ui:composition 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/jstl/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<rich:modalPanel id="myLazyModal">
<h:outputText value="Modal Content"/>
</rich:modalPanel>
</ui:composition>
lazyModal.xhtml - for handling inclusion of the above xhtmls
<ui:composition 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/jstl/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<a4j:include id="lazyModal" layout="block"
viewId="#{helperBean.postback ? 'modal.xhtml' : 'empty.xhtml'}"/>
</ui:composition>
finally use it
<h:form id="frmTest">
<a4j:include id="lazyModalContainer" layout="block" viewId="lazyModal.xhtml"/>
<a4j:commandButton id="btnSubmit" value="Submit" reRender="lazyModalContainer"
oncomplete="Richfaces.showModalPanel('myLazyModal');"/>
</h:form>
Now when the page is loaded empty.xhtml will be included till btnSubmit is clicked.
Regarding to the problems you mentioned (1):
Re-rendering components with the rendered attribute is a bit catchy. When the rendered expression is evaluated to false no markup is sent back to the client. Therefore, supplying the id of the none rendered component to the reRender attribute will never work cause there is no such id on the client side (DOM).
i think you should make separate xhtml(facelet) of modal panel and use ui:include and than on link click the link no need of boolean property than.
enter code here : <ui:include src="modalPanel path">, <a4j:commandLink id="abclink" oncomplete="#{rich:component('yourPanelname')}.show()" reRender="yourPanelForm"/>
Another solution is to set the render attribute of your modalpanel programmatically in the JSF component tree. So you wont't need an additional backing bean which has to handle one property to keep the state for each modalPanel:
Managed Bean:
public void togglePanel(ActionEvent event) {
UIComponent component = event.getComponent();
String forId = (String) component.getAttributes().get("for");
FacesContext currentInstance = FacesContext.getCurrentInstance();
UIComponent findComponent = ComponentFinder.findComponent(currentInstance.getViewRoot(), forId);
findComponent.setRendered(!findComponent.isRendered());
}
View:
Open the panel:
<a4j:commandLink actionListener="#{myBean.togglePanel}" value="Open">
<f:attribute name="for" value="targetPanelId" />
Close the Panel:
<a4j:commandLink id="closePanel" actionListener="#{myBean.togglePanel}" value="someLabel">
<f:attribute name="for" value="targetPanelId" />
The modalpanel:
<a4j:outputPanel ajaxRendered="true">
<rich:modalPanel id="targetPanelId" width="800" height="500" rendered="false" showWhenRendered="true">
Related
I have a JSF page that loads the properties of an object (for which the id is passed in the URL). The loading can last more seconds, so I would like to display a wait/busy indicator or a "Loading..." message.
This is done using "viewAction"
<f:metadata>
<f:viewAction action="#{myBean.loadParams}" />
</f:metadata>
Is there a simple way to accomplish this goal? I'm using Primefaces.
PrimeFaces has already a component ready for that: the <p:outputPanel deferred="true">. You only need to make sure that the #{heavyBean} is only referenced in a component (and thus definitely not in a tagfile like <c:xxx> for the reasons explained here) within the <p:outputPanel> and not somewhere else.
...
#{notHeavyBean.property}
...
<p:outputPanel deferred="true">
...
#{heavyBean.property}
...
</p:outputPanel>
...
#{anotherNotHeavyBean.property}
...
Then you can do the heavy job in its #PostConstruct method. Do the job you originally did in <f:viewAction> there in the #PostConstruct.
#Named
#ViewScoped
public class HeavyBean implements Serializable {
#PostConstruct
public void init() {
// Heavy job here.
}
// ...
}
If you need to access properties of other beans, simply #Inject those beans in the HeavyBean. E.g. in case you needed the ID view param:
<f:viewParam name="id" value="#{notHeavyBean.id}" />
#Inject
private NotHeavyBean notHeavyBean; // Also #ViewScoped.
#PostConstruct
public void init() {
Long id = notHeavyBean.getId();
// Heavy job here.
}
The <p:outputPanel> already comes with an animated gif. You can easily customize it via CSS.
.ui-outputpanel-loading {
background-image: url("another.gif");
}
I would like to propose also this simple approach:
one "landing" page (the page where we first navigate in) with a wait indicator and an autoRun remoteCommand with an event that read the parameter "param" from the URL and save it in the bean.
the remoteCommand does a redirect to another page (where the long-running method loadParams is executed)
In this way the wait indicator is shown until the second page is ready to be displayed.
Do you see any weaknesses?
Here the landing page:
<!DOCTYPE html>
<html
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:p="http://primefaces.org/ui">
<h:head>
...
</h:head>
<f:metadata>
<f:event type="postAddToView" listener="#{notHeavyBean.readProperty}" />
<f:viewParam name="param"/>
</f:metadata>
<h:body>
<p:outputPanel layout="block">
<i class="fa fa-circle-o-notch fa-spin layout-ajax-loader-icon" aria-hidden="true" style="font-size: 40px;position: relative;top: 50%;left: 50%;"></i>
</p:outputPanel>
<h:form>
<p:remoteCommand action="#{notHeavyBean.redirect}" autoRun="true"/>
</h:form>
</h:body>
I have the below Test.xhtml where i can select mode as Sea/Air. I don't want to load the all the 4 pages(Page1.xhtml, Page2.xhtml, Page3.xhtml, Page4.xhtml) into the jsf view tree. In my scenario, mode once selected and saved that can not be changed to other mode. The saved mode will be shown as view mode. Since at any point of time i need only 2 files (Page1.xhtml, Page2.xhtml (or) Page3.xhtml, Page4.xhtml)... I am using the JSTL tag handler for dynamic including the pages. the below thing is working fine. But i am not able to understand how the rendering working.
Test.xhtml
<!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:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head><title>JSF And JSTL</title>
<link href="../css/styles.css"
rel="stylesheet" type="text/css"/>
</h:head>
<h:body>
<div align="center">
<h:form id="form1">
<h:panelGrid columns="2">
<h:outputLabel value="Select Mode"/>
<h:selectOneMenu id="selectPageId" value="#{testBean.selectedMode}">
<f:selectItem itemLabel="Select" />
<f:selectItem itemLabel="Sea" itemValue="sea" />
<f:selectItem itemLabel="Air" itemValue="air" />
<f:ajax execute="#this" render="pageGroup"/>
</h:selectOneMenu>
</h:panelGrid>
<h:panelGroup id="pageGroup">
<c:if test="#{'sea' eq testBean.selectedMode}">
<ui:include src="Page1.xhtml" />
<ui:include src="Page2.xhtml" />
</c:if>
<c:if test="#{'air' eq testBean.selectedMode}">
<ui:include src="Page3.xhtml" />
<ui:include src="Page4.xhtml" />
</c:if>
</h:panelGroup>
</h:form>
</div>
</h:body>
</html>
TestBean.java
package com.test;
#ManagedBean(name = "testBean")
#ViewScoped
public class TestBean {
private String selectedMode;
public String getSelectedMode() {
return selectedMode;
}
public void setSelectedMode(String selectedMode) {
this.selectedMode = selectedMode;
}
}
Updated Again
Please help to clarify the below.
When i send a request first time to access the Test.xhtml, the jsf view (UIViewRoot) gets created. Since testBean.selectedMode by default is null.. this created view would not contain any component details of <c:if> and <ui:include> which are inside of <h:panelGroup id="pageGroup">.
After that when i send a second request(ajax postback) by selecting the mode as sea, the UIViewRoot gets created again for the request in the Restore View Phase. While UIViewRoot creation for this request in Restore View Phase, the tag handlers(<c:xxx>, <f:xxx>, <ui:include>) will get executed.
Since the selected value 'sea' will be updated to model(TestBean.java) only in Update Model Values Phase, in the Restore View Phase the EL #{testBean.selectedMode} will be evaluated to null.
So in my example Test.xhtml page the both tag handlers (<c:if test="#{'sea' eq testBean.selectedMode}"> and <c:if test="#{'air' eq testBean.selectedMode}">) will be evaluated to false. So the UIViewRoot does not contain any information related to the components inside <h:panelGroup id="pageGroup">.
Even though the UIViewRoot does not contain the components information inside the <h:panelGroup id="pageGroup">, How JSF able to render the included pages(<ui:include src="Page1.xhtml" />,<ui:include src="Page2.xhtml" />) successfully?
I am not sure how JSF rendering happening here. While Rendering, Is JSF re-creating the component tree for the particular rendering part(<h:panelGroup id="pageGroup">).?
Note: The example is working fine when i select mode as sea/air. The corresponding parts are rendering correctly.
I have the below Test.xhtml where i can select mode as Sea/Air. I don't want to load the all the 4 pages(Page1.xhtml, Page2.xhtml, Page3.xhtml, Page4.xhtml) into the jsf view tree. In my scenario, mode once selected and saved that can not be changed to other mode. The saved mode will be shown as view mode. Since at any point of time i need only 2 files (Page1.xhtml, Page2.xhtml (or) Page3.xhtml, Page4.xhtml)... I am using the JSTL tag handler for dynamic including the pages. the below thing is working fine. But i am not able to understand how the rendering working.
Test.xhtml
<!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:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head><title>JSF And JSTL</title>
<link href="../css/styles.css"
rel="stylesheet" type="text/css"/>
</h:head>
<h:body>
<div align="center">
<h:form id="form1">
<h:panelGrid columns="2">
<h:outputLabel value="Select Mode"/>
<h:selectOneMenu id="selectPageId" value="#{testBean.selectedMode}">
<f:selectItem itemLabel="Select" />
<f:selectItem itemLabel="Sea" itemValue="sea" />
<f:selectItem itemLabel="Air" itemValue="air" />
<f:ajax execute="#this" render="pageGroup"/>
</h:selectOneMenu>
</h:panelGrid>
<h:panelGroup id="pageGroup">
<c:if test="#{'sea' eq testBean.selectedMode}">
<ui:include src="Page1.xhtml" />
<ui:include src="Page2.xhtml" />
</c:if>
<c:if test="#{'air' eq testBean.selectedMode}">
<ui:include src="Page3.xhtml" />
<ui:include src="Page4.xhtml" />
</c:if>
</h:panelGroup>
</h:form>
</div>
</h:body>
</html>
TestBean.java
package com.test;
#ManagedBean(name = "testBean")
#ViewScoped
public class TestBean {
private String selectedMode;
public String getSelectedMode() {
return selectedMode;
}
public void setSelectedMode(String selectedMode) {
this.selectedMode = selectedMode;
}
}
Updated Again
Please help to clarify the below.
When i send a request first time to access the Test.xhtml, the jsf view (UIViewRoot) gets created. Since testBean.selectedMode by default is null.. this created view would not contain any component details of <c:if> and <ui:include> which are inside of <h:panelGroup id="pageGroup">.
After that when i send a second request(ajax postback) by selecting the mode as sea, the UIViewRoot gets created again for the request in the Restore View Phase. While UIViewRoot creation for this request in Restore View Phase, the tag handlers(<c:xxx>, <f:xxx>, <ui:include>) will get executed.
Since the selected value 'sea' will be updated to model(TestBean.java) only in Update Model Values Phase, in the Restore View Phase the EL #{testBean.selectedMode} will be evaluated to null.
So in my example Test.xhtml page the both tag handlers (<c:if test="#{'sea' eq testBean.selectedMode}"> and <c:if test="#{'air' eq testBean.selectedMode}">) will be evaluated to false. So the UIViewRoot does not contain any information related to the components inside <h:panelGroup id="pageGroup">.
Even though the UIViewRoot does not contain the components information inside the <h:panelGroup id="pageGroup">, How JSF able to render the included pages(<ui:include src="Page1.xhtml" />,<ui:include src="Page2.xhtml" />) successfully?
I am not sure how JSF rendering happening here. While Rendering, Is JSF re-creating the component tree for the particular rendering part(<h:panelGroup id="pageGroup">).?
Note: The example is working fine when i select mode as sea/air. The corresponding parts are rendering correctly.
i have a JSF projekt and in there i have different views, which are backed by ManagedBeans.
What i would like to achieve is to change some views while others stay where they are. this has to happen dynamically. In other words. I want to inject and remove views from an xhtml page without a page refresh. I have no clue how to achieve this.
Even better would be a dynamic view injection based on urls. angularjs does that very well.
But even without routing it would be great.
Thanks in advance.
Here is an example in pseudo code:
<nav>
<h:link action="navigationBean.changeView(view1)" method="ajax">Link1</h:link>
<h:link action="navigationBean.changeView(view2)" method="ajax">Link2</h:link>
</nav>
<h:viewContainer>
// view selected by clicking the nav links should be injected here without page reload
</h:viewContainer>
What you ask is better done using Facelet templating. You'll be able that way to have a page template with the shared content (the navigation menu in your case) and make the rest of the views inherit from it.
What can I see from your suggested solution is that you're abusing the POST calls. #{fragmentsPresenter.changeView('viewOne')} doesn't make sense just because you already know where you want to go to when you press that link (to viewOne), So you'll be better using plain links for that.
Here you've got an example showing how to handle navigation in a proper way. Let's suppose you've got a view controller even you won't need it in most of the cases:
ViewController.java
/**
* Give the scope you want to your bean depending on what are your operations
* oriented to. This example could be #ApplicationScoped as well
*
* #author amaeztu
*
*/
#ManagedBean
#SessionScoped
public class ViewController {
/**
* Just gets the current view path and switches to the other one
*
* #return
*/
public String changeView() {
String viewId = FacesContext.getCurrentInstance().getViewRoot()
.getViewId();
if (viewId.equals("/view1.xhtml")) {
return "/view2";
} else {
return "/view1";
}
}
}
This controller's job is just to check what view are you coming from and switch to the other one. It's pointless to perform a POST request (to send a form) just to navigate to the other view, while you could evaluate it before page rendering.
Here you've got how the template view is built:
template.xhtml
<ui:composition 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">
<h:head />
<h:body>
<h:form>
<!-- Use POST requests like this only when you have
to determine the destination dinamically at server side -->
<h:commandButton value="Switch View with POST"
action="#{viewController.changeView}" />
<br />
</h:form>
<!-- For plain navigation, use GET requests -->
<h:link value="Go to view 1" outcome="/view1" />
<br />
<!-- Determine where we are at page rendering time
and evaluate the other view path -->
<h:link value="Switch view without POST"
outcome="#{view.viewId eq '/view1.xhtml' ? '/view2' : '/view1'}" />
<br />
<br />
<ui:insert name="content" />
</h:body>
</ui:composition>
This template page defines a shared button/link set and calls for content. I've implemented different kind of navigation options. Using <h:link /> is, in this case, the most straight-forward way. Check the second link, here we evaluate the current view id when it gets rendered and a link to go to the opposite one is created. Cool, isn't it?
Now here it is the implementation of the child views:
view1.xhtml
<ui:composition 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" template="/template.xhtml">
<ui:define name="content">
<!-- Here you could have some #ViewScoped
bean managing the content i.e. #{view1Bean} -->
View 1
</ui:define>
</ui:composition>
view2.xhtml
<ui:composition 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" template="/template.xhtml">
<ui:define name="content">
View 2
</ui:define>
</ui:composition>
You'll be able to type their address in your browser and see them, that's what's called bookmarkable ;-)
See also:
Get current page programmatically
Ok, i solved it as follows:
my View:
<h:body>
<nav>
<h:form>
<h:commandLink action="#{fragmentsPresenter.changeView('viewOne')}">
viewOne
<f:ajax execute="#this" render="fragment-container" />
</h:commandLink>
<h:commandLink action="#{fragmentsPresenter.changeView('viewTwo')}">
viewTwo
<f:ajax execute="#this" render="fragment-container" />
</h:commandLink>
</h:form>
</nav>
<h:panelGroup id="fragment-container">
<ui:fragment rendered="#{fragmentsPresenter.activeView('viewOne')}">
<div>i am view one!</div>
</ui:fragment>
<ui:fragment rendered="#{fragmentsPresenter.activeView('viewTwo')}">
<div>i am view Two!</div>
<ui:include src="fragment.xhtml"/>
</ui:fragment>
</h:panelGroup>
and my ManagedBean:
#ManagedBean
#SessionScoped
public class FragmentsPresenter {
private String activeView;
public void setActiveView(String viewName) { this.activeView = viewName; }
public String getActiveView() { return this.activeView; }
public FragmentsPresenter() { this.activeView = "viewOne"; }
public void changeView(String viewName) { this.activeView = viewName; }
public boolean activeView(String viewName) {
return activeView.equals(viewName);
}
}
This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 6 years ago.
I have a page that has a preRender call that prepares everything to be displayed in the page. I'm not sure if it's relevant, but the page recieves a few params from the index.xhtml that precedes the experience.
I have a commandButton that I need to execute a server-side method (an update, to be precise). There is no need for a refresh on the page.
So I'm using ajax. Here's the button's, code
<h:commandButton value="Save">
<f:ajax event="click" listener="#{bean.save}"/>
</h:commandButton>
So far, on the java side, here's the bean's save method
public void save(){
log.debug("Save executed!");
}
I've added some logging to check what's being executed. When I click the button, the only thing that happens is that the preRender method is executed (and not entirely, just a part of it). Nothing else happens. Visually, the page is not refreshed or anything.
I suspect that when I click the button, the page is being refreshed and therefore, the preRender method (called Build()) is executed, but since there are no parameters (remember that the Build requires parameters passed through <f:param>), something bugs out.
Bottom line: I just need to execute the save method when clicking on the button without refreshing or redirecting anything.
Ideas?
--EDIT--
INDEX.XHTML
<html 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/jstl/core">
<ui:define name="body">
<h:link outcome="agreementDetail.xhtml" value="EA-15558">
<f:param name="serviceId" value="EA-15558" />
<f:param name="site" value="NIC" />
</h:link>
</ui:define>
</html>
AgreementDetail.XHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html 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/jstl/core">
<f:view>
<f:event type="preRenderView" listener="#{agreement.build}"/>
</f:view>
<ui:define name="body">
<f:view>
<h:form>
<h:commandButton value="Save" action="#{agreement.save}">
<f:ajax/>
</h:commandButton><br/><br/>
<h:dataTable value="#{agreement.licenseServerNames}" var="licenseServerName">
<h:column>
<h:inputText value="#{licenseServerName}"/>
</h:column>
</h:dataTable>
</h:form>
</f:view>
</ui:define>
</html>
AgreementBean.java
#ManagedBean(name="agreement")
#RequestScoped
public class AgreementBean {
#ManagedProperty("#{param.serviceId}")
private String serviceId;
#ManagedProperty("#{param.site}")
private String site;
private List<String> licenseServerNames; //GETTERS AND SETTERS OMITTED TO AVOID EXCESS CODE
#PostConstruct
public void build(){
logger.debug("START");
methodOne();
logger.debug("END");
}
public void save(){
logger.debug("SAVE!!!!!");
for(String name : licenseServerNames){
logger.debug("Servername = "+name);
}
}
}
This worked for me."Show" is a boolean that you can set upon successful save.
<h:commandButton id="ajax" value="Save" action="{agreement.save}" >
<f:ajax execute="#form" render="#form" />
</h:commandButton>
<h:outputScript rendered="#{agreement.show}">alert("save");</h:outputScript>