p:terminal does not have a update attribute.
Does it support any kind of ajax event?
how do I update another jsf component as a response to a terminal command?
It does not have any ajax events as can be seen in the documentation and/or the source. But in the implementation of commands for the terminal that you implement yourself, you can do anything you want. Including using the RequestContext to update other components.
At least that is what I expected (and did not explicitly test, sorry). Updating from the commandHandler does not work since the commandHandler is called during the render response phase and you cannot add updates to components in that phase.
See also the comment on the answer here: Can I update a JSF component from a JSF backing bean method?.
So the actual good answer is the one from the #Leo himself (although this answer helped a little ;-))
Here what worked for me
<p:terminal
id="terminal"
widgetVar="term"
prompt="Lab >> "
commandHandler="#{labMB.handleCommand}"
welcomeMessage="Welcome to Lab" />
<p:remoteCommand
name="rc"
update="history" />
<p:dataTable
id="history"(...)
and
public String handleCommand(String command, String[] params) {
RequestContext context = RequestContext.getCurrentInstance();
//(do things here)
context.execute("rc();");
}
it seems that just calling
context.update("form:history");
Related
let's say we have two types of events that will be directed to the same method as mentioned in the below example
<p:ajax event="cellEdit" listener="#{bean.eventype}"/>
<p:ajax event="change" listener="#{bean.eventype}"/>
and here is the bean method for example
public void eventype(){
println("");
}
The question is, is it possible if I want to identify which value came from which events in eventype method?
Is it possible to differentiate both mentioned events in eventype method?
Edited:
I did try to add eventype(AjaxBehaviorEvent event) and use event.getSource() but it seems like am just getting the source details like org.inputtext.component#something.
The type of event is posted in the request in order for the component being able to decode it to trigger the correct event. The parameter name is javax.faces.behavior.event, which you can get like:
String eventType = FacesContext.getCurrentInstance()
.getExternalContext()
.getRequestParameterMap()
.get("javax.faces.behavior.event");
This is implemented in PrimeFaces like:
https://github.com/primefaces/primefaces/blob/042b5a14116cd4a279a114883a8575e0788494b8/primefaces/src/main/java/org/primefaces/util/ComponentUtils.java#L197-L224
Note that you can also use the PrimeFaces constant Constants.RequestParams.PARTIAL_BEHAVIOR_EVENT_PARAM in your code instead of hardcoding "javax.faces.behavior.event".
First of all, sorry for my english. I have a RequestScoped ManagedBean in order to send parameters to other views, without getting the The scope of the object referenced by expression is shorter than the referring managed beans error. I also have in the same RequestScoped view a p:dataTable showing these beans objects, with an update button for each row, that retrieves this bean to another form in the same view to be update with new values.
The problem is, when I hit the submit button to record the new values, another record is created, instead of the older one being updated. Of course, because the bean is killed when the submit button is pressed (RequestScoped), creating a new bean and another record in the DB. How can I fix it in this scope?
I've seen some alternatives using #PostConstruct here, however I'm not entirely sure it would solve my specific problem.
EDIT:
After researching a bit more into this topic, I came to another doubt: I am using the same Bean in both views (in my case, ProjectBean), should I create a new Bean with RequestScoped annotation (something like ProjectIdBean), set the older one to ViewScoped (so I can reproduce updates naturally on my Database), and let this new Bean handle the requests for other views?
Submit button:
<p:commandButton value="Gravar" action="#{projetoBean.gravar}"
process="#form" update="#form :formTabelaProjetos:tabelaProjetos" />
'Gravar' method:
public void gravar() {
System.out.println("Gravando projeto " + this.projeto.getNome());
ProjetoDAO dao = new ProjetoDAO();
if (this.projeto.getId() == null) {
dao.adiciona(this.projeto);
projetosAtivos = this.getProjetosAtivos();
} else {
dao.atualiza(this.projeto);
}
this.projeto = new Projeto();
}
You can use request scoped backing bean for updating entities. The problem is, that the request life cycle ends when your page is rendered. So anything you loaded will get discarded. The submit creates another request, that will try to reload resources, but it is a different request than the previous one and for example request parameters often do not contain what the programmer expects. But this is what you found out already. There are two ways how to deal with the problem:
1) use simple getters and setters to set "String, Integer" and similar variables in your request scoped bean, that you use to reconstruct and modify the entity you want to update. It is not convenient for the programmer but request scoped beans save resources of your server.
2) change the scope of your backing bean. Session scope is not ideal, because it can stay in memory for a really long time. And you might realize you need to clean it up manually. Much better is ViewScoped bean as it allows you to work with the entities you loaded over several steps. It gets wiped out when the user leaves the page.
#javax.faces.bean.ViewScoped
#javax.faces.bean.ManagedBean
public class SomethingBean {
......
}
In a jsff file in my ADF project I have a button for searching some information which is displayed on the page.
<af:button actionListener="#{bindings.ExecuteWithParams.execute}"
text="SEARCH"
id="button"/>
After that I have a button for editing the displayed information.
<af:commandMenuItem text="edit"
actionListener="#{viewScope.bean.editPopup}"
id="editBtn" immediate="true">
The main idea here is when actionListener="#{viewScope.bean.editPopup}" is executed then actionListener="#{bindings.ExecuteWithParams.execute}" is executed after it, automatically.
Do you have any ideas how it can be achieved? Thank you!
In this case you can programmatically call executeWithParams in your ActionListener (editPopup)
Just add operation in your pageDef and call using OperationBinding
BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
OperationBinding method = bindings.getOperationBinding("methodAction");
Object result = method.execute();
You can capture the single button click in a backing bean and call both methods from there. This blog should help. Also this.
For the viewScope bean, there are helper Static classes that you can use to get a reference to the bean into your backing bean and then call the viewScope bean method there. Look at JSFUtils.java. This blog is older, but might help as well.
This question already has answers here:
Invoke JSF managed bean action on page load
(4 answers)
Closed 7 years ago.
I have to call a init method on my bean as first action on the page load, I have tried to simply call #{bean.init} at the very beginning of my page, but I have seen that the <c:if> tests are performed before the init(). I have something like
#{bean.init}
<c:if test="#{bean.conditionsCheck}">...</c:if>
and the conditionsCheck() method is called before the init(),
how can I fix it and call init() as really first thing?
You can use the #PostConstruct annotation to automatically invoke your init method:
#PostConstruct
public void init() {
// do something
}
This method is automatically invoked after construction of the bean.
Your solution looks more like a f:event with type="preRenderView" but this can't be used because the c:if tags are evaluated during view build time, while the f:event (respectively your solution) runs right before the view is rendered during render response phase. Have a look at this question and this question to get details.
Update: As you commented you are using a #SessionScoped bean where #PostConstruct is only called once per session and not on every page load. In this case another solution would be to call your init method as first statement in your conditionsCheck method (nearly the same as your suggestion with fake c:if boolean init). You could also use a custom PhaseListener but I guess that would be somewhat overdosed for this problem.
See also:
Why use #PostConstruct?
This works if you add a JSF Control like CommandButton, and in its value you write it as:
value="#{sessionScopedBean.method()}"
This method will be called whenever this page loads.
for anyone searching ...
We can use preRender of scriptCollector tag, if the used JSF implementation supports it, something like:
<scriptCollector id="scriptCollector1" preRender="#{bean.method}">
...
</scriptCollector>
I have the following button:
<h:commandButton
disabled="#{mybean.searching}"
binding="#{mybean.searchButton}"
actionListener="#{mybean.searchForLicenses}"
value="Search" />
When I debug I see that the actionListener is called twice first, then three times, next click four times and so on.
It seems like on every reload the actionListener is registered one more time.
I'm using Mojarra 2.1.3 (also tried 2.0.6) and Tomcat 7 with IceFaces.
The binding is done that way:
private javax.faces.component.UICommand searchButton;
public void setSearchButton(UICommand searchButton) {
this.searchButton = searchButton;
}
public UICommand getSearchButton() {
return searchButton;
}
That can happen if you've bound the component to a session or application scoped bean instead of a request scoped bean. This is simply a bad design. The very same component would be reused among multiple requests/views. You need to put the bean in the request scope, or to get rid of the component binding altogether.
Note that binding the component directly to a bean is often a sign of poor design somewhere in the code. What is it, the functional requirement and/or problem for which you thought that this is the solution? If you elaborate on that, we may be able to propose the right approach.
Also note that using an action listener alone is also a design smell. I'd expect "searchForLicenses" to be a normal action method. See also Differences between action and actionListener.
The similar issue takes place when component is using binding and validator or valueChangListener and backing bean is of View, Session or Application scope. Then corresponding listeners are called many times but not once during request (+1 time with every new request).
One possible solution is to override jsf class AttachedObjectListHolder which is used for storing component listeners. Current implementation simply add new listener to component even though the same listener is already there. So the proposed fix is to check that listener does not exist before adding it.
Details of the fix you can see here