Parameter passing one page to another page in JSF-2.0? - java

I would like to pass a parameter from one page to another.
Each page will have a ViewScoped JSF Backing Bean.
Although, I try to use <f:param> I get the following error:
when I click <h:commandLink> will navigate to another page.
ERROR :
] Root cause of ServletException.
com.sun.faces.mgbean.ManagedBeanCreationException: Unable to create managed bean ReservationActionBean. The following problems were found:
- The scope of the object referenced by expression #{param.resvDataModel}, request, is shorter than the referring managed beans (ReservationActionBean) scope of view
at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:265)
at com.sun.faces.el.ManagedBeanELResolver.resolveBean(ManagedBeanELResolver.java:244)
at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:116)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
.........
page1.xhtml
<p:panelGrid style="margin-top:-1px;" id="dashboard">
<ui:repeat value="#{DashBoard.dayList}" var="day">
<p:row>
<p:column style="background:#C1CDCD;width:100px;">
<h:outputText value="#{day}" style="color:#333333;font-size:13px;">
<f:convertDateTime type="date" pattern="EEE, yyyy-MM-dd"/>
</h:outputText>
</p:column>
<ui:repeat value="#{DashBoard.timeSlot}" var="timeSlot">
<p:column style="background:#C1CDCD;text-align: center;">
<h:outputText value="#{timeSlot}" style="font-size:12px;"/>
</p:column>
</ui:repeat>
</p:row>
<ui:repeat value="#{DashBoard.resourceList}" var="res">
<p:row>
<p:column>
<h:outputText value="#{res.name}" style="font-size:12px;"/>
</p:column>
<ui:repeat value="#{DashBoard.getResvDataModelList(day, res)}" var="model">
<p:column style="background:#{model.colour};" colspan="#{model.section}">
<h:commandLink action="reservation" style="display:block;width:#{model.section * 50}px;height:20px;">
<f:param name="model" value="#{ReservationActionBean.resvDataModel}"/>
<!--h:outputText value="#{model.user}"rendered="#{model.resource.name == res.name ? true : false}"style="font-size:12px;"/-->
</h:commandLink>
</p:column>
</ui:repeat>
</p:row>
</ui:repeat>
</ui:repeat>
</p:panelGrid>
page2.xtml
<h:form id="reservationEntryFrom">
<f:metadata>
<f:viewParam name="resvDataModel" value="#{ReservationActionBean.resvDataModel}"/>
</f:metadata>
<!-- other -->
</h:form>
DashBoard.java
#ManagedBean(name = "DashBoard")
#ViewScoped
public class DashBoard extends BaseBean {
public List<ResvDataModel> getResvDataModelList(
Date date, MeetingRoom meetingRoom) {
// do operation
}
}
ReservationActionBean.java
#ManagedBean(name="ReservationActionBean")
#ViewScoped
public class ReservationActionBean extends BaseBean {
#ManagedProperty("#{param.resvDataModel}")
private ResvDataModel resvDataModel;
//other operations
}
ResvDataModel.java
public class ResvDataModel {
// attribute, getter and sertter
#Override
public boolean equals(Object object) {
return EqualsBuilder.reflectionEquals(this, object);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
}

The #ManagedProperty is invoked only once during bean's construction. Imagine that the bean is in session scope and the managed property references a request scoped variable (e.g. a request parameter), then only the parameter of the very first request would be set and it would never be updated with changed request parameter values in subsequent requests after the session bean construction. This is considered undesired behaviour. Hence #ManagedProperty cannot reference something which has a narrower scope than the #ManagedBean itself.
In this particular case, you need <f:viewParam> instead. Put the following in page2.xhtml:
<f:metadata>
<f:viewParam name="resvDataModel" value="#{ReservationActionBean.resvDataModel}" />
</f:metadata>
See also:
ViewParam vs #ManagedProperty(value = "#{param.id}")
However, there's another problem with this approach. You're passing non-String object along as a request parameter. The value would be only com.example.ResvDataModel#hashcode (or whatever the toString() method of your ResvDataModel class returns). This information is insufficient to reconstruct exactly the desired ResvDataModel instance.
You need to pass some unique identifier or action parameter value along instead of a whole complex Java object which can't be uniquely represented as a String.

Related

Error : non-serializable attribute value into ViewMap

i have the same application in 2 systems(laptops) but its working in one but not in another.i get the following error in another system. i have also posted the code below.what i want to do is cascading dropdown with a button that calls method of a different managed bean, and a placeOrder button to add a record in database.but i get the following error at the time of page loading
WARNING: Setting non-serializable attribute value into ViewMap: (key: stockOrderBean, value class: beans.stockOrderBean)
SEVERE: Error Rendering View[/ClientTemplate/stockTrade.xhtml]
java.io.NotSerializableException: beans.stockOrderBean
WARNING: JSF1087: Unable to generate Facelets error page as the response has already been committed.
SEVERE: javax.faces.FacesException: beans.stockOrderBean
xhtmlcode:
<h:outputText value="Exchange :"/>
<p:selectOneMenu value="#{stockOrderBean.exchange}" style="width: 200px">
<f:selectItem itemLabel="Select Exchange"/>
<f:selectItem itemLabel="NSE" itemValue="nse"/>
<f:selectItem itemLabel="BSE" itemValue="bse"/>
<p:ajax update="sym" listener="#{stockOrderBean.wow}"/>
</p:selectOneMenu>
<h:outputText value="Select ScripSymbol :"/>
<p:selectOneMenu value="#{stockOrderBean.scripID}" style="width: 200px" id="sym">
<f:selectItem itemLabel="Select scrip"/>
<f:selectItems var="scrip" value="#{stockOrderBean.sl}" itemLabel="#{scrip.scripSymbol}" itemValue="#{scrip.scripID}"/>
</p:selectOneMenu>
<p:commandButton value="Get Quote" actionListener="#{stockOrderBean.equity.setQuote}" oncomplete="cd.show()" update=":frmdialog" />
<h:panelGrid columns="2" id="d1" style="width:565px">
<h:outputText value="How would you like to place order"/>
<p:selectOneRadio value="#{stockOrderBean.transType}">
<f:selectItem itemLabel="Market Order" itemValue="MarketOrder"/>
<p:ajax update="frmTrade:d1"/>
<f:selectItem itemLabel="Limit Order" itemValue="LimitOrder"/>
<p:ajax update="frmTrade:d1"/>
</p:selectOneRadio>
<h:outputText value="Trigger Price"/>
<p:inputText value="#{stockOrderBean.triggerPrice}" disabled="#{stockOrderBean.transType == 'LimitOrder'}"/>
<h:outputText value="Limit Price"/>
<p:inputText value="#{stockOrderBean.limitPrice}" disabled="#{stockOrderBean.transType == 'MarketOrder'}"/>
</h:panelGrid>
<h:outputText value="Select your Demate Account"/>
<p:selectOneMenu value="#{stockOrderBean.demateAccount}" style="width: 120px">
<f:selectItem itemLabel="#{stockOrderBean.demateAccount}" itemValue="#{stockOrderBean.demateAccount}"/>
</p:selectOneMenu>
<p:commandButton value="Place New Order" actionListener="#{stockOrderBean.placeOrder}"/>
<p:commandButton value="Reset New Order" type="reset"/>
</h:form>
<p:dialog widgetVar="cd" header="Scrip Quotes Detail" resizable="true">
<h:form id="frmdialog">
<table>
<tr>
<td>
Ask :
</td>
<td>
<b><h:outputText value="#{stockOrderBean.equity.ask}"/></b>
</td>
</table>
</h:form>
</p:dialog>
sockOrderBean code:
#javax.faces.bean.ManagedBean
#javax.faces.bean.ViewScoped
public class stockOrderBean{
#WebServiceRef(wsdlLocation = "WEB-INF/wsdl/localhost_8080/StatelessWebService/StatelessWebService.wsdl")
private StatelessWebService_Service service;
//properties with getter setter
#ManagedProperty(value="#{equtiyBean}")
private equityBean equity = new equityBean();
public void placeOrder(...){
//method not called
}
the same code is working in one system but not on another.what could be the reason and how do i solve it?
Some server configurations need to save HTTP sessions on harddisk or need to transfer them over network to some central datastore, often with the goal to share the session between multiple servers in a cluster, or to minimize excessive memory usage. This in turn requires that all session attributes implement Serializable so that the server could use ObjectOutputStream to convert Java objects to bytes which can then be saved on disk or transferred over network and ObjectInputStream to convert those bytes back to Java objects.
If an object which is stored in the HTTP session does not implement Serializable, then you will get a NotSerializableException with the full qualified class name in the message. You should then fix the class to implement Serializable.
public class StockOrderBean implements Serializable {
// ...
}
In JSF, this applies to all view and session scoped managed beans. Request and application scoped beans doesn't need to implement Serializable. Note that all of the bean properties should also be Serializable. But you will get a clear enough NotSerializableException whenever one is encountered.
Anything which is added to session is Serialized. The error is telling you that your backing bean should probably be Serializable. No idea why it's intermittent though.
Try adding the code below to your web.xml. It will keep session objects on server side.
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>

Why this param is being sent as Null in my Bean?

I am Using JSF 2 and EJB 3.1 to create a form.
I am using this part of the page to get me some data, so I can pass it to my bean using the confirmDialog just below
<p:column headerText="#{bundle.edit}" style="width:10px; overflow:visible;">
<p:rowEditor/>
</p:column>
<p:column headerText="#{bundle.delete}" style="width:10px; overflow:visible;">
<p:commandButton update=":form" oncomplete="confirmation.show()"
image="ui-icon ui-icon-close" title="Delete">
<f:param value="#{user}" name="userAction" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:confirmDialog message="Are you sure? user:#{param['userAction']} " width="500"
header="Confirm" severity="alert" widgetVar="confirmation">
<p:commandButton value="Yes sure" update=":form"
actionListener="#{userController.deleteAction(param['userAction'])}"
oncomplete="confirmation.hide()" />
<p:commandButton value="Not yet" onclick="confirmation.hide()" type="button" />
</p:confirmDialog>
</h:form>
And this is the Bean that should get it
#Named(value = "userController")
#Stateful
#RequestScoped
#TransactionManagement(TransactionManagementType.CONTAINER)
public class UserController implements Serializable {
private User current;
#Inject
private br.com.cflex.itm.dataaccess.UserFacade userFacade;
public UserController() {
}
public void deleteAction(User user) {
userFacade.remove(user);
}
But My bean is only receiving null as User, and in the Dialog I am printing the data so I can see there is a User Object selected there.
What is wrong in passing params like that ?
Why am I getting null in my Bean? Because they are getting lost in the communication between client and server-side...
<p:commandButton action="#{userController.deleteAction(param['userAction'])}" />
The EL of action (and actionListener) is evaluated when the form is been submitted, not when the form is been displayed. Request parameters are request scoped and are not there in the subsequent request of the form submit. You need to pass it along:
<p:commandButton action="#{userController.deleteAction(param['userAction'])}">
<f:param name="userAction" value="#{param['userAction']}" />
</p:commandButton>
The EL of <f:param> is evaluated when the form is been displayed. So it will be there in the generated HTML and JavaScript will take care that it is passed along.
Note that request parameters are of String type. Expecting them to be User won't work at all. Basically, it contains the value of User#toString(). You'd need to take String as action argument and convert it to User yourself. Or better, use <f:viewParam> wherein you can explicitly specify a converter.

jsf table repeats itself

another weird jsf problem. my code looks something like this:
Java Bean:
class Bean {
private ArrayList<OutageTableHeader> outageTableHeaderData;
public ArrayList<OutageTableHeader> getOutageTableHeaderData() {
return outageTableHeaderData;
}
public void setOutageTableHeaderData(ArrayList<OutageTableHeader> value) {
this.outageTableHeaderData = value;
}
public List<OutageRowData> getOutageDataForTable() {
createOutageTableHeader(); // method which populates outageTableHeaderData with data
...
return(); // returns a list of OutageRowData objects, each for every row
}
}
my xhtml file:
...
<h:form>
<rich:dataTable id="outageOverviewTable"
value="#{mapOverviewManager.getOutageDataForTable()}" var="outageRow"
rendered="#{mapOverviewManager.outageDataForTable.size() > 0}"
headerClass="overviewHeader" cellpadding="0" cellspacing="0"
rowClasses="areaRowOdd, areaRowEven" style="width: auto">
<f:facet name="header">
<rich:columnGroup style="background: #ffffff">
<rich:column>
<h:outputText>TEST</h:outputText>
</rich:column>
<c:forEach items="#{mapOverviewManager.outageTableHeaderData}"
var="outHeader">
<rich:column colspan="#{outHeader.colSpan}">
<h:outputText value="#{outHeader.displayName}" />
</rich:column>
</c:forEach>
</rich:columnGroup>
</f:facet>
</rich:dataTable>
</h:form>
mapOverviewManager is my bean. Now I'm confronted with two problems
1) when I initally load the page, only "TEST" appears (the entry that is hard coded)
2) every time I press F5 to reload the page, the table expands itself. That is, exactly 32 entries (always the same) are appended to the end of the table and I don't know why?
This is rather strange because on the same page is a similar table, from which I basically copied the whole structure. Any suggestions?
You did not provide any meaningful data (not the scope of the bean, not even the code outageDataForTable property, not to mention the code that fetches data). But let me play a psychic for a second: the bean is session (or view) scoped, and you fetch the data in your getter?

Passing Parameters With Seam, RichFaces & PopupPanel

I'm trying to get a little application working using Seam 3, RichFaces 4 and hitting a few troubles with passing some parameters around. I've tried a lot of different things but I keep falling at the final hurdle. I'm carrying through a customerId via a request parameter. But when I hit a RichFaces commandButton on a popupPanel, that customerId is no longer available to me.
I'm setting up an application to manage some data. Basically you select a customer from one screen, that will take you to another screen containing "repositories" where you then can create, edit etc. You can get to this second repositories page via the URL:
http://localhost:8080/media-manager/repositories.xhtml?customer=12
I then have a bean picking this value up:
#Named
#RequestScoped
public class RepositoryBean extends AbstractViewBean<Repository> {
// Various properties etc. here
private Long customerId;
public void init() {
log.info("Customer ID is "+ customerId);
}
}
I then set the customer ID via metadata on the repository page and call init:
<f:metadata>
<f:viewParam name="customer" value="#{repositoryBean.customerId}"/>
<f:event type="preRenderView" listener="#{repositoryBean.init}" />
</f:metadata>
This works well at the start. I can display information I need for the customer with the supplied ID. But when I try to create my popupPanel is goes a bit wrong. Here's a simplified version of the code first:
<rich:popupPanel id="repositoryModalPanel" modal="true" resizeable="true">
<f:facet name="header">Title</f:facet>
<f:facet name="controls">
<h:outputLink value="#" onclick="#{rich:component('repositoryModalPanel')}.hide(); return false;">X</h:outputLink>
</f:facet>
<h:form id="modalForm" class="modalForm">
<fieldset>
<ul class="layout form">
<li>
<label for="name" class="required">Name:</label>
<h:inputText id="name" value="#{repositoryBean.instance.name}" required="true">
<!-- rich:validator event="blur" / -->
</h:inputText>
<rich:message for="name" errorClass="error errormessage" />
</li>
<li class="last">
<a4j:commandButton id="create" value="Create" action="#{repositoryBean.saveRepository}" rendered="#{empty repositoryBean.instance.id}"/>
<a4j:commandButton id="save" value="Save" action="#{repositoryBean.saveRepository}" rendered="#{not empty repositoryBean.instance.id}"/>
<a4j:commandButton id="cancel" value="Cancel" action="#{repositoryBean.clearInstance}" immediate="true" />
</li>
</ul>
</fieldset>
</h:form>
Basically, whenever I hit the save commandButton, the init method is called but the customerId member is never populated. Does anyone have any insight into why?
I've read that viewParam is only for GET requests so maybe that's the problem? But if that's the case - what is the other solution? Lots of things I have seen suggested (e.g. using #ManagedProperty) does not seem to be applicable to Seam 3.
RepositoryBean is RequestScoped, and as such will be newly created on each request, especially if you hit the save button.
The straightforward solution is to promote RepositoryBean to be ConversationScoped, and to make it long running if you enter the page.
#Named
#ConversationScoped
public class RepositoryBean extends AbstractViewBean<Repository> {
// Various properties etc. here
#In
Conversation conversation
private Long customerId;
public void init() {
log.info("Customer ID is "+ customerId);
conversation.begin();
}
}
The easieast way for that is to dump the preRenderView and use seam 3 view-action instead.
<f:metadata>
<f:viewParam name="customer" value="#{repositoryBean.customerId}"/>
<s:viewAction action="#{repositoryBean.init}" if="#{conversation.transient}"/>
</f:metadata>

How to invoke a method with Openfaces/JSF without rendering page?

I am trying to invoke a Save method in a bean with Openfaces 3. While Firefox is not rendering the page, Internet Explorer does.
I'm currently using this code lines:
<o:commandLink value="Save" action="#{beanX.save}">
<h:graphicImage url="/images/save_48.png" />
</o:commandLink>
but I was trying o:ajax as well:
<o:commandLink value="Save" action="#{beanX.save}">
<h:graphicImage url="/images/save_48.png" />
<o:ajax event="click" render="#none" />
</o:commandLink>
Any ideas?
I've found a way to deal with using standard JSF components. Any ideas how to solve this issue with o:commandLink?
You can use <f:ajax> and render attribute in jsf2.0
<h:form>
<h:inputText value="#{managedBean.val1}" >
<f:ajax event="keyup" render="result" listener="#{managedBean.someThingToDoListener}"/>
</h:inputText>
<h:inputText value="#{managedBean.val2}" >
<f:ajax event="keyup" render="result" listener="#{managedBean.someThingToDoListener}"/>
</h:inputText>
<h:outputText id="result" value="#{managedBean.result}"/>
</h:form>
#ManagedBean(name = "managedBean")
public class Bean {
private String val1; // getter and setter
private String val2; // getter and setter
private String res; // getter and setter
...
public void someThingToDoListener(AjaxBehaviorEvent event) {
//res = some processing
}
}
Also See
how-to-update-a-value-displayed-in-the-page-without-refreshing
JSF2: Ajax in JSF – using f:ajax tag
Thank you Jigar Joshi. You've given me the key hint. It works with this code lines:
<h:commandLink value="Save">
<h:graphicImage url="/images/save_48.png" />
<f:ajax event="click" render="#none" listener="#{beanX.save}" />
</h:commandLink>
I've been to this website before, I was not thinking in assuming that o:commandLink might not be able to handle this, might be a bug?
Using h:commandLink instead of o:commandLink and f:ajax with the listener attribute solved my problem.

Categories