Call spring controller method from JSF commandbutton - spring

I am trying to integrating spring and JSF(Primefaces).I configured the spring controller as component using #component annotation to be worked as JSF bean but it is not calling the action method of commandbutton.
XHTML File:
<h:form id="productForm" >
<h:panelGrid columns="1">
<p:outputLabel for="name" value="Name: " />
<p:inputText id="name" value="#{cust.customerForm.name}" />
<p:outputLabel for="address" value="address" />
<p:inputNumber id="address" value="#{cust.customerForm.address}" />
<p:outputLabel for="email" value="Email: " />
<p:inputNumber id="email" value="#{cust.customerForm.email}" />
<p:outputLabel for="mobile" value="Mobile: " />
<p:inputNumber id="mobile" value="#{cust.customerForm.mobile}" />
<p:commandButton value="Save" action="#{cust.save}" />
</h:panelGrid>
</h:form>
Spring controller used as JSF Bean:
#Scope(value="session")
#Component(value = "cust")
#ELBeanName(value = "cust")
#Controller
#RequestMapping("/customer")
public class CustomerController {
#Autowired
private CustomerRepository customerRepo;
private List<Customer> customerList;
private Customer customerForm;
public List<Customer> getCustomerList() {
return customerList;
}
public Customer getCustomerForm() {
return customerForm;
}
public void setCustomerForm(Customer customerForm) {
this.customerForm = customerForm;
}
public String save(){
System.out.println("save called:::::::::::");
return("Customer");
}
}
kindly help me out in figuring out what wrong I am doing.

You need to configure the org.springframework.web.jsf.el.SpringBeanFacesELResolver in your faces-config.xml. Otherwise JSF can't find spring beans.
When combining JSF and Spring Boot, you should definetl try Joinfaces which does exaclty this (and some other helpfull stuff)

Related

All bean attributes are assigned null

I'm writing an application using Spring Boot. I'd like to create an instance of the bean LobbyBean, but after heaving filled out the form, all attributes are still null. Does anybody have an idea, why the input data doesn't get through to the controller? Any help is greatly appreciated.
Here is the (simplified) code:
LobbyBean
#Component
#Scope("session")
public class LobbyBean {
#GeneratedValue
private int pin;
private QuestionSet questionSet;
private User host;
private QuestionDifficulty questionDifficulty;
private int maxNumberOfPlayers;
private boolean hasJoker;
// getters and setters for all attributes
LobbyController
#Component
#Scope("view")
public class LobbyController {
#Autowired
private GameManager gameManager;
#Autowired
private UserService userService;
private LobbyBean newLobby = new LobbyBean();
// getter and setter for newLobby
public void createLobby()
{
newLobby.setHost(userService.getAuthenticatedUser());
gameManager.saveLobby();
newLobby = new LobbyBean();
}
lobbycreation.xhtml
<ui:define name="content">
<h:form id="lobbysettings">
<p:panel>
<h:panelGrid id="settings" columns="2">
<p:outputLabel value="Questionset: "/>
<p:selectOneMenu id="questionset" value="#{lobbyController.newLobby.questionSet}">
<f:selectItems value="#{lobbyDetailController.allQuestionSetNames}"/>
</p:selectOneMenu>
<p:outputLabel value="Difficulty: "/>
<p:selectOneMenu id="difficulty" value="#{lobbyController.newLobby.questionDifficulty}" >
<f:selectItems value="#{lobbyDetailController.allQuestionDifficulties}"/>
</p:selectOneMenu>
<p:outputLabel value="Max Num of Players: "/>
<p:inputNumber decimalPlaces="0" value="#{lobbyController.newLobby.maxNumberOfPlayers}" />
<p:outputLabel value="Joker?"/>
<p:inputSwitch value="#{lobbyController.newLobby.hasJoker}" />
<p:commandButton id="createLobbyButton" value="Lobby Erstellen" process="#this"
action="#{lobbyController.createLobby}"/>
</h:panelGrid>
</p:panel>
</h:form>
</ui:define>
Replace the process="#this"on your p:commandButton with process="#form" otherwise only the commandButton will be part of the submit.

Implement callback method in JSF composite component

I'd like to implement a "callback" feature in my composite component. This method would be called from the backing component when necessary.
The XHTML part is:
<cc:interface componentType="partnerSelComp">
<cc:attribute name="value" type="com.app.data.Partner"/>
<cc:attribute name="callback" method-signature="void notify(java.lang.Long)"/>
</cc:interface>
<cc:implementation>
<span id="#{cc.clientId}">
<p:inputText id="code" binding="#{cc.partnerCode}">
<p:ajax event="blur" update="code name msg" listener="#{cc.validate}" />
</p:inputText>
<p:outputLabel id ="name" binding="#{cc.partnerName}"/>
<p:message id="msg" for="code"/>
</span>
</cc:implementation>
The relevant part of backing component is:
#FacesComponent("partnerSelComp")
public class PartnerSelComp extends UIInput implements NamingContainer {
private InputText partnerCode;
private OutputLabel partnerName;
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
public void validate() {
...
MethodExpression exp = (MethodExpression) getAttributes().get("callback");
...
}
...
}
Above the exp gets null value. How can I get the callback attribute, and how can I execute it?
A solution (Java 1.8) to call a function with no args.
Component:
<composite:interface>
<composite:attribute name="buttonCallback" type="java.util.function.Consumer"/>
</composite:interface>
<composite:implementation>
<p:commandButton value="Submit" action="#{cc.attrs.buttonCallback.accept(null)}"/>
<composite:implementation>
Usage in view:
<mycomp:myCC buttonCallback="#{myBackingBean.myCallback}"/>
Usage in backing bean:
private Consumer<Void> myCallback;
#PostConstruct
public void init() {
myCallback= this::myFunction;
}
public void myFunction(Void v) { //... }

p:commandButton update action won't clear input fields after submission

<h:form id="registrationForm">
UserName:
<p:inputText id="usernameInput" value="#{userUI.thisUsername}" />
<br />
Password:
<p:inputText id="passwordInput" value="#{userUI.thisPassword}" />
<br />
<p:commandButton actionListener="#{userUI.createUser}"
update="registrationForm" value="Create" />
</h:form>
I want this form to reset its values after submission.
I enter the username and password, hit submit, it resets the values and persists empty values, not the ones i entered. Tried moving the commandButton out of h:form but it didn't change a thing. Also tried adding
<p:ajax update="registrationForm" resetValues="true" />
It still persisted empty values.
How do i do it right?
Give this a try:
Bean is of scoped Request.
To reset values reinitialize fields in post constructor, or call it manually in your createUser method.
#ManagedBean
#RequestScoped
public class UserUI implements Serializable {
private static final long serialVersionUID = 1L;
private String thisUsername;
private String thisPassword;
public UserUI(){
}
#PostConstruct
public void init(){
thisUsername="";
thisPassword="";
}
public void createUser(){
System.out.println("ThisUserName :"+thisUsername);
System.out.println("thisPassword :"+thisPassword);
init();
}
/////////GETTER SETTER
//thisUsername
//thisPassword
}
Your webPage.xhtml will be look like:
<h:form id="registrationForm">
<p:panelGrid columns="2">
<h:outputLabel value="UserName:" for="usernameInput" />
<p:inputText id="usernameInput" value="#{userUI.thisUsername}" />
<h:outputLabel value="Password:" for="passwordInput" />
<p:inputText id="passwordInput" value="#{userUI.thisPassword}" />
<p/>
<p:commandButton action="#{userUI.createUser}" update="#form" value="Create" />
</p:panelGrid>
</h:form>

p:commandButton action not invoked after and ajax update

I have a JSF page which has a p:commandButton which has ajax=true and renders a p:panel which is wrapped in p:outputPanel when clicked. When this button is clicked the action method will set showCreateUser value in ManagedBean to true and this is used to render the Panel. This works fine - on button click the panel is rendered properly. Inside the p:panel there is another p:commandButton. This commanButton is not working as nothing happens when I click on it. The action method is never invoked. When I debug I realised that even though the ajax action sets showCreateUser to true but when I click on second button the showCreateUser value is false. So, the panel panel rendered=false and so the action is never invoked. Following are the xhtml and managedbean class. How can I resolve this? Thanks for your help!
registration.xhtml
<h:form id="userForm" style="background-color:white;border:0px; width:90%;">
<p:messages id="messagesForDebugging"
showDetail="true"
autoUpdate="true" />
<ui:debug hotkey="x"/>
<div style="margin-bottom: 10px;">
<p:commandButton id="btnConfirmYes" value="Yes" ajax="true" update="userRegOutPanel"
action="#{regBean.confirmYes}" styleClass="button" style="height:35px;">
<!-- <f:ajax render="userRegOutPanel" execute="userRegOutPanel"/> -->
</p:commandButton>
<p:commandButton id="btnConfirmNo" value="No" ajax="false"
action="#{regBean.confirmNo}" styleClass="button" style="height:35px;"/>
</div>
<p:outputPanel id="userRegOutPanel">
<p:panel id="userRegPanel" rendered="#{regBean.showCreateUser}">
<p:panelGrid id="userRegPanelGrid">
<p:row>
<p:column style="width:40%;background-color:#00a5b6;-moz-border-radius: 10px;-webkit-border-radius: 10px;-khtml-border-radius: 10px;border-radius: 10px;text-align:left;">
<h:inputHidden id="ssn" value="#{regBean.ssn}"/>
<p:panelGrid>
<p:row>
<p:column>
<p:commandButton value="Submit" ajax="true" action="#{regBean.submitRegistration}"
styleClass="button" style="width:140px;height:35px;" type="submit"/>
</p:column>
</p:row>
</p:panelGrid>
</p:column>
</p:row>
</p:panelGrid>
</p:panel>
</p:outputPanel>
</h:form>
Managed Bean
#ManagedBean
#ViewScoped
public class RegBean implements Serializable{
private static final long serialVersionUID = 1L;
static Logger log = LoggerFactory.getLogger(RegBean.class);
private String ssn;
private boolean showCreateUser = false;
public void confirmYes(){
setShowCreateUser(true);
}
public String confirmNo(){
log.info("In retrieveRegistration");
FacesContext fc = FacesContext.getCurrentInstance();
fc.addMessage("registrationError", new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"Error. Contact customer service",
"Error. Contact customer service"));
return "/registration/registrationError";
}
public String submitRegistration() {
log.info("In submitRegistration");
FacesContext fc = FacesContext.getCurrentInstance();
return "/secured/home";
}
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
public boolean isShowCreateUser() {
return showCreateUser;
}
public void setShowCreateUser(boolean showCreateUser) {
this.showCreateUser = showCreateUser;
}
}
<p:commandButton id="btnConfirmNo" value="No" ajax="false"
action="#{regBean.ConfirmNo}"
styleClass="button" style="height:35px;"/>
In above code ,you've set action to be "ConfirmNo". I don't see any method as such.
Change above code as :
<p:commandButton id="btnConfirmNo" value="No" ajax="false"
action="#{regBean.agentConfirmNo}"
styleClass="button" style="height:35px;"/>
Now, it will invoke the method agentConfirmNo from your registration bean.
I hope that helps.

Primefaces ajax pagination not working

I have following jsf page, in which datatable is populated via ajax request from database. Problem is, after pushing another page button on pagination bar, table shows no results. Changing scope of backing bean to session helps, but it is not a solution. Why it is happening?
<h:form>
<h:panelGrid columns="2" cellpadding="8" style="width: 545px">
<h:panelGroup>
<p:outputLabel value="Client name: " for="searchString" />
<br />
<p:inputText id="searchString" title="searchString" value="#{findClientBean.searchString}" />
</h:panelGroup>
<h:panelGroup>
<br />
<p:message for="searchString" />
</h:panelGroup>
<p:commandButton value="Search" styleClass="pCommandButton" >
<f:ajax execute="searchString" listener="#{findClientBean.findClient}" render=":resultTable" />
</p:commandButton>
</h:panelGrid>
</h:form>
<br />
<p:dataTable id="resultTable" var="client" value="#{findClientBean.resultList}" paginator="true" rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15" paginatorPosition="bottom">
<p:column headerText="Search results">
<h:outputLink value="../temp.xhtml?id=#{client.id}">#{client.firstName} #{client.lastName}</h:outputLink>
</p:column>
</p:dataTable>
<h:form>
Backing bean code:
#Named
#RequestScoped
public class FindClientBean implements Serializable {
#Inject
private ClientDAO clientDAO;
#NotNull(message="Search string cannot be empty")
private String searchString;
private List<Client> resultList;
public void findClient() {
resultList = clientDAO.findClientByNameOrLastnamePart(searchString);
}
public void setResultList(List<Client> resultList) {
this.resultList = resultList;
}
public List<Client> getResultList() {
return resultList;
}
public String getSearchString() {
return searchString;
}
public void setSearchString(String searchString) {
this.searchString = searchString;
}
}
Your Client resultList is being populated whenever the user presses the Search button.
As the collection is inside a RequestScoped bean, the resultList will be erased as soon as it is sent back to the View (along with the entire bean).
As a result, when the user tries to navigate to another page (thus making a second request) the component won't find a populated resultList anymore and a "No records found" message will be displayed.
"Promote" you bean to ViewScoped (or any scope that would make your bean live longer).
#Named
#ViewScoped
public class FindClientBean implements Serializable{
(...)
}

Resources