p:commandButton results in an IllegalStateException [duplicate] - jsf-2

This question already has answers here:
Adding <h:form> causes java.lang.IllegalStateException: Cannot create a session after the response has been committed
(5 answers)
Closed 7 years ago.
I get this error when I click on a p:commandButton in my page
java.lang.IllegalStateException: PWC3999: Cannot create a session
after the response has been committed
The button is in an h:form and looks like this:
<p:commandButton value="Save" action="#{discussionManager.save}" ajax="false"/>
But an h:commandButton works fine:
<h:commandButton value="Save" action="#{discussionManager.save}"/> (this works)
This is the bean with the method in it
#Named
#RequestScoped
public class DiscussionManager {
private static final Logger logger = Logger.getLogger("DiscussionManager");
#Inject
private DiscussionDao discussionDao;
private Discussion discussion = new Discussion();
#Produces
#Named
#RequestScoped
public Discussion getDiscussion() {
return discussion;
}
public String save() {
logger.info("Hello");
discussionDao.create(discussion);
return "list";
}
}
I've waited all day before posting this question because I feel like I should know how to get this working. But I've read and re-read my book, and loads of other posts. I just don't understand why it's not working.

I can't comment on your final answer so I have to add another answer. I believe what you did to make your example work was to add widgetVar to your editor component. I had this problem as well. The example on the PrimeFaces Demo wouldn't work properly until I added the widgetVar line. You need to reference the widgetVar name in your onclick call rather than the id. I use different names between the id and widgetVar for clarity so I would change your editor code to:
<h3>Write your message below</h3>
<p:editor id="editorID"
value="#{discussion.message}"
widgetVar="editorWidget"
width="600"
required="true"/>
<h:message for="editor"/>
<h:panelGrid columns="2" style="margin-top:10px">
<p:commandButton id="submitButton" value="Save" action="#{discussionManager.save}" ajax="false" icon="ui-icon-disk"/>
<p:commandButton id="clearButton" type="button" value="Clear" onclick="editorWidget.clear()" icon="ui-icon-close" />
</h:panelGrid>
I hope that helps clarify.

I suspect that it is because the bean goes out of scope. When you turn off ajax it submits the form and you are actually dealing with a new request. Try expanding your scope to a view scope.

Not quite sure what I changed to get it working, because now the whole thing is working fine. But for completeness, here's the relevant part of my page
<h3>Write your message below</h3>
<p:editor id="editor"
value="#{discussion.message}"
widgetVar="editor"
width="600"
required="true"/>
<h:message for="editor"/>
<h:panelGrid columns="2" style="margin-top:10px">
<p:commandButton id="submitButton" value="Save" action="#{discussionManager.save}" ajax="false" icon="ui-icon-disk"/>
<p:commandButton id="clearButton" type="button" value="Clear" onclick="editor.clear()" icon="ui-icon-close" />
</h:panelGrid>
And here's my bean. Hope someone finds this useful...
#Named
#RequestScoped
public class DiscussionManager implements Serializable {
private static final Logger logger = Logger.getLogger("DiscussionManager");
#Inject
private DiscussionDao discussionDao;
private Discussion discussion = new Discussion();
#Produces
#Named
#RequestScoped
public Discussion getDiscussion() {
return discussion;
}
public String save() {
logger.info("Hello");
discussionDao.create(discussion);
return "list";
}
}

Related

JSF2.2 Multiple field validation message not appearing.. the message is associated to a component [duplicate]

JSF 2.0 only allows you to validate the input on one field, like check to see if it's a certain length. It doesn't allow you to have a form that says, "enter city and state, or enter just a zip code."
How have you gotten around this? I'm only interested in answers that involve the validation phase of JSF. I'm not interested in putting validation logic in Managed Beans.
The easiest custom approach I've seen and used as far is to create a <h:inputHidden> field with a <f:validator> wherein you reference all involved components as <f:attribute>. If you declare it before the to-be-validated components, then you can obtain the submitted values inside the validator by UIInput#getSubmittedValue().
E.g.
<h:form>
<h:inputHidden id="foo" value="true">
<f:validator validatorId="fooValidator" />
<f:attribute name="input1" value="#{input1}" />
<f:attribute name="input2" value="#{input2}" />
<f:attribute name="input3" value="#{input3}" />
</h:inputHidden>
<h:inputText binding="#{input1}" value="#{bean.input1}" />
<h:inputText binding="#{input2}" value="#{bean.input2}" />
<h:inputText binding="#{input3}" value="#{bean.input3}" />
<h:commandButton value="submit" action="#{bean.submit}" />
<h:message for="foo" />
</h:form>
(please note the value="true" on the hidden input; the actual value actually doesn't matter, but keep in mind that the validator won't necessarily be fired when it's null or empty, depending on the JSF version and configuration)
with
#FacesValidator(value="fooValidator")
public class FooValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
UIInput input1 = (UIInput) component.getAttributes().get("input1");
UIInput input2 = (UIInput) component.getAttributes().get("input2");
UIInput input3 = (UIInput) component.getAttributes().get("input3");
// ...
Object value1 = input1.getSubmittedValue();
Object value2 = input2.getSubmittedValue();
Object value3 = input3.getSubmittedValue();
// ...
}
}
If you declare the <h:inputHidden> after the to-be-validated components, then the values of the involved components are already converted and validated and you should obtain them by UIInput#getValue() or maybe UIInput#getLocalValue() (in case the UIInput isn't isValid()) instead.
See also:
Validator for multiple fields (JSF 1.2 targeted)
Alternatively, you can use 3rd party tags/components for that. RichFaces for example has a <rich:graphValidator> tag for this, Seam3 has a <s:validateForm> for this, and OmniFaces has several standard <o:validateXxx> components for this which are all showcased here. OmniFaces uses a component based approach whereby the job is done in UIComponent#processValidators(). It also allows customizing it in such way so that the above can be achieved as below:
<h:form>
<o:validateMultiple id="foo" components="input1 input2 input3" validator="#{fooValidator}" />
<h:inputText id="input1" value="#{bean.input1}" />
<h:inputText id="input2" value="#{bean.input2}" />
<h:inputText id="input3" value="#{bean.input3}" />
<h:commandButton value="submit" action="#{bean.submit}" />
<h:message for="foo" />
</h:form>
with
#ManagedBean
#RequestScoped
public class FooValidator implements MultiFieldValidator {
#Override
public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) {
// ...
}
}
The only difference is that it returns a boolean and that the message should be specified as message attribute in <o:validateMultiple>.
Apache ExtVal was not mentioned here.
There are some cross validations in it (among other validations which might be useful):
https://cwiki.apache.org/confluence/display/EXTVAL/Property+Validation+Usage#PropertyValidationUsage-CrossValidation

#SessionScoped bean instantiated over and over [duplicate]

This question already has an answer here:
#SessionScoped bean looses scope and gets recreated all the time, fields become null
(1 answer)
Closed 8 years ago.
Using PrimeFaces 5.10, JSF 2, and Wildfly, I am trying to get my xhtml page to interact with a single instance of a #SessionScoped bean with a PF poll component. Each time the poll calls the bean method, a new instance of the bean is created. I've tried #ViewScoped and #SessionScoped with no change in behavior. I've noticed other similar questions, but have not seen any with a solution I have been able to implement.
I know the println's are not a reliable way to show order of method calls, but i'm using them to merely demonstrate which methods are being called and it appears that the init() method gets called over and over, even though I have #PostConstruct, so it's new instantiations. I'm even printing out "this" and it's showing different hashes each time it prints.
It never gets through the if statement in refreshTweets() because the stopPolling field never gets set to false in the right context.
I've run into this problem before and have been able to work around it rather than solve it. If anyone has any ideas as to what I am doing wrong, please let me know.
Below is the relevant xhtml code:
<p:layoutUnit id="center" position="center" styleClass="dataBox">
<h:form id="TwitterFeed">
<p:panelGrid columns="2">
<p:outputLabel value="Twitter topic to query: " />
<p:inputText value="#{dataBean.tweetTopic}"/>
<p:outputLabel value="Number of Twitter Results: " />
<p:inputText value="#{dataBean.tweetCount}" />
<p:commandButton value="Submit" action="#{dataBean.toggleRenderTweets}" update="tweets"/>
<p:commandButton value="Polling" action="#{dataBean.togglePolling}" update="tweets"/>
</p:panelGrid>
<p:panel visible="#{dataBean.renderTweets}" id="tweets">
<p:panelGrid columns="1">
<p:dataTable id="twitterTable" value="#{dataBean.tweetList}" var="tweetStatus">
<p:columns value="#{dataBean.tweetColumns}" var="column" columnIndexVar="colIndex">
<f:facet name="header">
<h:outputText value="#{column.header}"/>
</f:facet>
<h:outputText value="#{tweetStatus[column.property]}"/>
</p:columns>
</p:dataTable>
<p:poll interval="10" listener="#{dataBean.refreshTweets}" update="twitterTable" widgetVar="tweetPoll" id="tweetPoll" autoStart="true"/>
</p:panelGrid>
</p:panel>
</h:form>
</p:layoutUnit>
The relevant bean code is below:
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.annotation.PostConstruct;
import java.io.Serializable;
#SessionScoped
#ManagedBean
public class DataBean implements Serializable {
private List<TwitterStatusModel> tweetList;
private boolean renderTweets;
private boolean stopPolling;
#PostConstruct
public void init() {
<<initialize fields>>
stopPolling = true;
System.out.println(this + " init()");
}
private void getTweets() {
<<this method sets the List above tweetList>>
}
public void refreshTweets() {
if (!stopPolling) {
<<Method never passes the if statement because stopPolling is set to true in init()
}
public void togglePolling() {
stopPolling = !(stopPolling);
System.out.println(this + "Toggling polling - now " + stopPolling);
}
You should use the correct imports of #SessionScoped etc.
With a #ManagedBean you need the javax.faces.bean.* ones not the javax.enterprise.context ones or javax.faces.view
See also Why are there different bean management annotations

Delete from list and order of execution of backing bean methods

I have a simple CDI bean. The problem is that when I invoke method removeCustomer from the JSF page, method getCustomers() is executed before removeCustomer instead the opposite way. First I thought that producer itself is the problem but I'm getting same behavior if I put the list inside the controller. When I get response page the row in the table is not removed ether it is removed from the database. When I refresh page once more I don't see the deleted row.
#Named
#RequestScoped
public class CustomersController {
#Inject
private CustomerService customerService;
#Produces()
#RequestScoped
#Named("customers")
public List<Customer> getCustomers() {
return customerService.findCustomers();
}
/**
* #param customerId
*/
public String removeCustomer(Long customerId) {
customerService.deleteCustomer(customerId);
return null;
}
}
<h:form id="customers-form">
<h:dataTable value="#{customers}" var="customer"
styleClass="table">
<h:column>
<f:facet name="header">#{msg['customer.name']}</f:facet>
#{customer.name}
</h:column>
<h:column>
<f:facet name="header">#{msg['customer.vat']}</f:facet>
#{customer.vat}
</h:column>
<h:column>
#{msg['global.edit']}
</h:column>
<h:column>
<h:commandButton styleClass="btn btn-danger"
action="#{customersController.removeCustomer(customer.id)}"
value="#{msg['global.delete']}" aria-hidden="true">
<f:ajax render="#form"></f:ajax>
</h:commandButton>
</h:column>
</h:dataTable>
I'm using JBoss WildFly beta 1 but I'm guessing that it uses stable JSF 2.x version.
Check this answer
The method getCostumers is called before because the EL expresion (#customers) is being evaluated several times while processing the request (more details in the link).
The solution is to make your getters and setters "dumb". Just make them change a variable of your class. Avoid logic with side effects (like customerService.findCustomers();). If you need initialization, you can perform it in a #PostConstruct method or in a method fired by a JSF event).
Also, take into account that with a #RequestScoped bean, a new instance of the bean will be created for every request (either to render the page, or to save changes to the values).
Actually it is pretty easy to achieve what I want.
Here is updated CDI bean.
#Named
#RequestScoped
public class CustomersController {
#Inject
private CustomerService customerService;
#Inject
private List<Customer> customers;
#Produces()
#RequestScoped
#Named("customers")
public List<Customer> getCustomers() {
return customerService.findCustomers();
}
/**
* #param customerId
*/
public void removeCustomer(Customer customer) {
customerService.deleteCustomer(customer.getId());
customers.remove(customer);
}
}
As you can see. On ajax request to remove the customer producer is invoked before method removeCustomer. Logically because in restore view phase jsf is restoring view and evaluating EL expressions and this is happening before event processing phase. So we have list of customers in request scope and we need to inject it in controller bean so we can remove from the list selected customer in the removeCustomer method. I hope I was clear enough.

How to get command link value(display name) from backing bean?

I have a p:commandLink in my xhtml with the value toggling between "Show"/"Hide".
Is there any way by which I can get the value of this commandlink from the backing bean?
I mean, I want to know what value the command link is showing currently i.e. Show/Hide?
To the point, the invoking component is just available in ActionEvent argument:
<h:commandLink id="show" value="Show it" actionListener="#{bean.toggle}" />
<h:commandLink id="hide" value="Hide it" actionListener="#{bean.toggle}" />
with
public void toggle(ActionEvent event) {
UIComponent component = event.getComponent();
String value = (String) component.getAttributes().get("value");
// ...
}
However, this is a poor design. Localizable text should absolutely not be used as part of business logic.
Rather, either hook on component ID:
String id = (String) component.getId();
or pass a method argument (EL 2.2 or JBoss EL required):
<h:commandLink id="show" value="Show it" actionListener="#{bean.toggle(true)}" />
<h:commandLink id="hide" value="Hide it" actionListener="#{bean.toggle(false)}" />
with
public void toggle(boolean show) {
this.show = show;
}
or even just call the setter method directly without the need for an additional action listener method:
<h:commandLink id="show" value="Show it" actionListener="#{bean.setShow(true)}" />
<h:commandLink id="hide" value="Hide it" actionListener="#{bean.setShow(false)}" />
As #BalusC suggested, your approach is not a good solution. But if you really want to do that, you can bind the component (p:commandLink) to your backingbean, as seen in What is the advantages of using binding attribute in JSF?.
After the component was bound, you can access the value attribute from the p:commandLink.

How to save a list/map/set in JSF with h:inputText + managed bean

What I'm trying to achieve is very similar to the one posted in the following link.
How to save an array in JSF with ui:repeat + h:inputText + managed bean?
I'm particularly fascinated with the answer provided by Arjan Tijms in the link above however what I want to achieve is slightly different. Consider the following code snippets.
The bean
import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
#RequestScoped
#Named
public class MyBean {
List<String> choices;
public List<String> getChoices() {
return choices;
}
#PostConstruct
public void initChoices() {
choices= new ArrayList<String>();
}
public String save() {
// should save all the choices into some repository
return "";
}
}
and the facelet page
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:body>
<h:form>
<ui:repeat value="#{myBean.choices}" varStatus="status">
<h:inputText value="#{myBean.choices[status.index]}" />
</ui:repeat>
<h:commandButton value="Save" action="#{myBean.save}" />
</h:form>
</h:body>
</html>
The thing is, this will work if we have some initial data in the list at the beginning. What about situations where the initial list will be empty?
The ideal solution which I'm looking for is to have 1 h:inputText for each choice and when save button is clicked, all choices in each h:inputText is then added to the choices list. I've searched high and low but can't seem to find any hints on how this can be done.
If JSF 2 really doesn't support this, I guess I'll have to use the ugly way with just one h:inputText and use a converter to convert to and from a list but I'm still hoping that an ideal solution can be found.
Hopefully someone from stackoverflow can shed a light in the right direction for me.
Just add an "add" button which adds a new String to the list.
<ui:repeat value="#{myBean.choices}" varStatus="status">
<h:inputText value="#{myBean.choices[status.index]}" />
</ui:repeat>
<h:inputText value="#{myBean.newChoice}" />
<h:commandButton value="Add" action="#{myBean.add}" />
<h:commandButton value="Save" action="#{myBean.save}" />
with
private String newChoice;
public void add() {
choices.add(newChoice);
newChoice = null;
}
// ...
Note that this only works if bean is put in view scope. A request scoped one would be constructed on every request and hereby recreate the list everytime.

Resources