I have a screen in which am using
<html 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">
<h:body>
<h:form>
<f:event listener="#{pageload.getPageLoad}" type="preRenderView" />
<h:dataTable value="#{pageload.fieldConfig}" var="field"
columnClasses="lblFirstCol,lblSecondCol,lblThirdCol,lblFourthCol" id="table1" styleClass="tblSecond" >
<h:column >
<h:outputText value="#{field.label_name}" />
</h:column>
<h:column>
<h:inputText value="#{searchdevice.device.terminal_name}" />
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{searchdevice.searchButtonAction}"/>
</h:form>
</h:body>
And my backing bean
#ManagedBean(name="pageload")
#RequestScoped
public class PageLoadBean {
private List<FieldConfigVO> fieldconfig;
//getters and setters
// method to populate the ArrayList
public void getPageLoad(){
//getting populated from Database
fieldconfig = common.getFieldConfig("001");
}
}
The other input bean
#ManagedBean(name="searchdevice")
#RequestScoped
public class SearchDeviceBean {
private DeviceVO device;
public SearchDeviceBean() {
device = new DeviceVO();
}
public DeviceVO getDevice() {
return device;
}
public void setDevice(DeviceVO device) {
this.device = device;
}
public String searchButtonAction(){
System.out.println(device.getTerminal_name()+"****TERMINAL NAME******");
FacesContext context = FacesContext.getCurrentInstance();
if (context.getMessageList().size() > 0) {
return(null);
}else {
return("success");
}
}
}
My Device Object has the terminal_name property.I have a command button which invokes method in SearchDeviceBean and on submitting the form whatever value I enter doesn't get populated
Any help appreciated
You're performing data initialization logic in preRenderView event. This is the wrong place for code which needs to prepare the model for the postback. When JSF needs to update the model values during form submit, it is encountering a completely empty fieldConfig and therefore JSF can't set the submitted/converted/validated values in there. The fieldConfig is in your case only prepared during a later phase, the render response phase, which is thus too late.
You need to initialize it in #PostConstruct instead. It's invoked immediately after bean's construction and dependency in jection. Get rid of the whole <f:event> altogether and put a #PostConstruct annotation on the getPageLoad() method. I'd by the way also rename that method to init() or loadFieldConfig() as it isn't a getter method at all and therefore a very confusing name to other people reading/maintaining your code.
See also:
When to use f:viewAction / preRenderView versus PostConstruct?
Related
Using JSF 2.0 and EL, I am trying to call a method on a POJO which is an attribute of a viewscoped bean. The code is actually very similar to #BalusC's tutorial here. When I call a method that takes no arguments, everything's fine. But when I try to call a method that takes an argument, I get the following exception:
javax.faces.el.MethodNotFoundException: javax.el.MethodNotFoundException:
/user.xhtml at line 42 and column 32 action="#{users.user.removeFriend(friend)}":
Method not found: model.User#67f2b0dd.removeFriend()
Here are some more details:
user.xhtml
<f:metadata>
<f:viewParam name="id" value="#{users.id}" />
<f:event type="preRenderView" listener="#{users.init}" />
</f:metadata>
...
<h:form id="usersForm">
<p:outputPanel>
<p:dataTable id="userTable" value="#{users.user.friendList}" var="friend">
<p:column>
<h:outputText value="#{friend.name}" />
</p:column>
<p:column>
<p:commandButton action="#{users.user.removeFriend(friend)}"
ajax="true"
update="userTable somethingElse" process="#this"
onerror="errorDialog.show();"
icon="ui-icon-delete"
title="delete user">
</p:commandButton>
</p:column>
</p:dataTable>
</p:outputPanel>
<p:commandButton action="#{users.user.removeAllFriends()}" ajax="true"
update="userTable somethingElse"
process="#this"
icon="ui-icon-close"
value="delete all friends?">
</p:commandButton>
</h:form>
I have the following ViewScoped bean:
Users.java
#ManagedBean(name = "users")
#ViewScoped
public class Users implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private User user;
#ManagedProperty("#{userService}")
private UserService userService; // session scoped
public void init() {
user = userService.getCart(id);
}
public final String getId() {
return id;
}
public final void setId(String id) {
this.id= id;
}
public final User getUser() {
return user;
}
public final void setUser(User user) {
this.user= user;
}
public final void setUserService(UserService userService) {
this.userService = userService;
}
}
The User class - a POJO - has a private List<Friend> friends attribute, with getter and setters and a public method User#removeFriend(Friend f). It has another public method; User#removeAllFriends().
The page renders fine but I get the exception when I click the "Remove" commandButton next to a user in the table.
What's wrong here? Why can I successfully call a parameter-less method but can't pass arguments to another?
Edit: The application is deployed on Tomcat 7.0, if that's any good.
Any help appreciated.
Update: As BalusC and Neo pointed, this is an issue with Tomcat 7.0. I installed WebLogic 12.1 and it all worked fine.
This is a bug in Tomcat. It works when you call the method on the bean directly, but not when you call it on a nested property. I recall this issue as issue 50449 which I have ever reported but was closed as "works for me" (perhaps they did not test it very properly, I didn't find it worth the effort to argue with Tomcat guys again, I haven't had very good experiences with them). In any way, I have re-reported it as issue 52445 with a more solid testcase -I hope.
In the meanwhile, replacing the EL implementation with a different one, from Glassfish for example, should work out. But I can tell you that whatever you're trying to do is not really the proper approach. You've declared a business method on the model (the User entity class) instead of on the controller (the Users managed bean class). This is not right. The model should solely be used to hold the data. The controller should be used to hold the business actions.
I recommend to rewrite your case as follows:
<h:form id="usersForm">
<p:outputPanel>
<p:dataTable id="userTable" value="#{users.user.friends}" var="friend">
<p:column>
<h:outputText value="#{friend.name}" />
</p:column>
<p:column>
<p:commandButton action="#{users.removeFriend(friend)}"
process="#this" update="userTable somethingElse" onerror="errorDialog.show();"
icon="ui-icon-delete" title="delete user" />
</p:column>
</p:dataTable>
</p:outputPanel>
<p:commandButton action="#{users.removeAllFriends}"
process="#this" update="userTable numUsers"
value="delete all friends?" />
</h:form>
and put the business methods in the Users managed bean instead:
public void removeFriend(Friend friend) {
userService.removeFriend(user, friend);
// ...
}
public void removeAllFriends() {
userService.removeAllFriends(user);
// ...
}
Also the UserService being another #ManagedBean is not entirely right. It should actually be an #Stateless EJB, but that's another story. EJBs are not supported on Tomcat anyway without enriching it with for example OpenEJB. Without EJB, it does not necessarily need to be another managed bean. You don't want to expose those services into the view directly.
Ahh.. that explains it # Tomcat.. The way in which you are passing the parameter "#{users.user.removeFriend(friend)}" is EL 2.2. You can overcome that by following the steps here: http://www.mkyong.com/jsf2/how-to-pass-parameters-in-method-expression-jsf-2-0/ OR by using some other way as described here: http://www.mkyong.com/jsf2/4-ways-to-pass-parameter-from-jsf-page-to-backing-bean/. Good luck!
If you are using Tomcat you can do the following.
In the xhtml file you do something like this.
#{ItemInformationController.setFindItem(525)}
#{ItemInformationController.findItem}" var="AVar">
In your controller file you can do something like this:
int itemId;
public List<Item> getFindItem() {
return getJpaController().findLevel3Item(levelId);
}
public void setFindItem(int id) {
itemId= id;
}
This works find with Tomcat 6/7...
enter code here
#ManagedBean(name = "customerBean")
#SessionScoped
public class CustomerBean implements Serializable {
/**/
private static final long serialVersionUID = 1L;
CustomerManager customerManager = CustomerManager.getInstance();
private Book book;
private Long id;
private String name, vorname, addresse, ort;
Customer customer = new Customer();
ArrayList<Customer> customerList;
public void findCustomer(String name){
CustomerManager.getInstance().findCustomerByName(name);
System.out.println("Hello" + customer.getName());
}
getters and setters...
public class CustomerManager {
static EntityManagerFactory emf;
static EntityManager em;
static CustomerManager instance;
EntityTransaction entityTransaction = null;
public CustomerManager() {
emf = Persistence.createEntityManagerFactory("customerRegistration");
em = emf.createEntityManager();
}
List<Customer> customerstList = new ArrayList<Customer>();
Book book = new Book();
Set<Book> bookList = new HashSet<Book>();
Customer customer = new Customer();
public void findCustomerByName(String name) {
// Query for a single object.
Query query = em.createQuery("Select c FROM Customer c WHERE c.name = :name");
query.setParameter("name", name);
System.out.println("Hello from Business");
customer = (Customer)query.getSingleResult();
}
<ui:define name="content">
<h:body>
<h:form id="main">
<p:panelGrid columns="2">
<p:outputLabel for="name" value="#{texts.name}" />
<p:inputText id="name" value="#{customerBean.customer.name}" />
<h:commandButton value="Search"
action="#{customerBean.findCustomer()}" />
</p:panelGrid>
</h:form>
</h:body>
</ui:define>
My JavaScript:
function setJson(value) {
document.getElementById("json").value = value;
}
My XHTML:
<h:inputHidden id="json" value="#{indexManaged.json}" valueChangeListener="#{indexManaged.goTo('datatable')}" />
My ManagedBean:
#ManagedBean
#ViewScoped
public class IndexManaged implements Serializable {
private String json;
public String getJson() { return json; }
public void setJson(String json) { this.json = json; }
public String goTo(String page) {
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.put("json", json);
return page + "?faces-redirect=true";
}
}
The scenario:
I have a Java Applet that fires the function setJson(value). But when the applet sets a new value to my inputHidden, isn't the valueChangeListener suposed to fire my ManagedBean method? What am I doing wrong?
The valueChangeListener isn't a client side listener. It's a server side listener which runs when the form is submitted. So, you need to submit the form as well.
Wrap it in a form
<h:form id="form">
and submit it as follows
document.getElementById("form").submit();
Don't forget to fix the client ID of the hidden input accordingly:
document.getElementById("form:json").value = value;
See also:
When to use valueChangeListener or f:ajax listener?
Unrelated to the concrete problem, there are cleaner ways to achieve this. Have a look at PrimeFaces <p:remoteCommand> and OmniFaces <o:commandScript>.
Not sure about the <h:inputHidden
But you can use the following thing:
<h:inputText id="json" value="#{indexManaged.json}" style="display:none">
<f:ajax listener="#{myBean.myListener}"/>
</h:inputText>
and trigger it with jquery like this:
$("#json").change();// instead of `json` you might be needed to provide
//full id like this, $("#myform\\:json").change()
I have problems with SelectOneMenu. I write this:
<h:selectOneMenu id="listaEstados"
styleClass="comboboxStyle"
value="#{detalleSistemaBean.sistema.indEstado}"
immediate="true">
<f:selectItems value="#{detalleSistemaBean.indEstados}" />
</h:selectOneMenu>
<h:commandButton id ="SubmitModificar"
value="Modificar"
styleClass="botonPeque"
action="#{detalleSistemaBean.modificaSistema}">
</h:commandButton>
But when I choose one value from the list "indEstados" and I submit the form, the bean "sistema.indEstado" doesn't change. I have seen that the bean property changes just before the method modificaSistema, but inside this method (where I have a database connection and a sql sentence), "sistema.indEstado" returns to its original value. Why this happens? I have tried to save the value using valueChangeListener, and that works, but I guess that is not a neat solution.
That can happen when you're doing data loading inside the getter method instead of inside the (post)constructor of the bean class.
Fix your managed bean code to not do anything else inside getter methods than just returning the property.
I.e. do not do
public Sistema getSistema() {
return sistemaService.find(someSistemaId);
}
but rather do
private Sistema sistema;
#PostConstruct
public void init() {
sistema = sistemaService.find(someSistemaId);
}
public Sistema getSistema() {
return sistema;
}
Can you try without setting
immediate="true"
JSF commandButton with immediate="true"
I cant seem to get the view scoped managed bean to work with setPropertyActionListener:
<h:commandButton value="Edit" action="edit-company.xhtml">
<f:setPropertyActionListener target="#{companyHolder.item}" value="#{company}"/>
</h:commandButton>
This works fine if companyHolder is session or request scoped but doesnt work if its view scoped. Is this normal?
A brand new view scoped bean is been created when a new view is created. The target view holds a different instance of the view scoped bean than where the property is been set by the action method on the initial view with the form.
This is at first sight indeed unintuitive, but that's how the view scope works. A view scoped bean lives as long as the view lives. It makes sense after all.
Your best bet is using <f:param> instead of <f:setPropertyActionListener> and let the target view set it by <f:viewParam>.
E.g.
<h:commandButton value="Edit" action="edit-company.xhtml">
<f:param name="companyId" value="#{company.id}"/>
</h:commandButton>
with
<f:metadata>
<f:viewParam name="companyId" value="#{bean.company}" required="true" />
</f:metadata>
and
#ManagedBean
#ViewScoped
public class Bean {
private Company company;
// ...
}
and
#FacesConverter(forClass=Company.class)
public class CompanyConverter implements Converter {
#Override
public void getAsObject(FacesContext context, UIComponent component, Object value) throws ConverterException {
try {
return companyService.find(Long.valueOf(value));
} catch (Exception e) {
throw new ConverterException(new FacesMessage(
String.format("Cannot convert %s to Company", value)), e);
}
}
// ...
}
As a completely different alternative, you can also just navigate back to the same view by returning void or null and render the include conditionally.
<ui:include src="#{bean.editmode ? 'edit' : 'view'}.xhtml" />
This however doesn't work if you require to support GET instead of POST (for which you would need to replace <h:commandButton> by <h:button> by the way).
Has anybody used JSF2, PrimeFaces, and Highcharts together?
I am really confused on how I should put all these together, specially regarding the ajax request to get the data from the server to feed into Highcharts on the view to update the chart.
What I have right now is a servlet that handles the Ajax request, which is sent using JQuery.ajax() method and use JQuery to update the chart with the new data received as JSON object. And I am using GSon.toJSon to convert Java object into JSON object.
What I am trying to achieve here is that I want to replace that servlet with the JSF2. Instead of using a different servlet, I want to use JSF and have some backing bean to prepare and send the JSON object to the client.
Anybody?
In the example below the the p:commandButton starts the ajax request. The JSON object you want to use can be stored in the h:inputHidden field. When the p:commandButton completes the javascript function is called to update the chart. The javascript function will be able to access the JSON object from the h:inputHidden field.
xhtml
<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:p="http://primefaces.prime.com.tr/ui">
<h:head>
<script type="text/javascript">
function dosomething() {
var value = jQuery("#beanvalue").attr('value');
alert(value);
}
</script>
</h:head>
<h:body>
<h:form prependId="false" >
<p:commandButton value="update" action="#{testBean.update}" update="beanvalue" oncomplete="dosomething();" />
<h:inputHidden value="#{testBean.output}" id="beanvalue" />
</h:form>
</h:body>
</html>
Bean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class TestBean {
private String output;
public TestBean() {
output = "1";
}
public void update() {
output += "1";
}
public String getOutput() {
return output;
}
public void setOutput(String output) {
this.output = output;
}
}