I am using an ajax box which will fetch the list of object based the string provided in the box as follows:
<p:inputText id="zid" placeholder="Search" value="#{resourceListView.wanted}">
<p:ajax event="keyup" update=":form:abc"
listener="#{resourceListView.SearchResources}" />
</p:inputText>
SearchResources will fetch the objects based on the value of input box as follows:
public void SearchResources(String wanted) {
this.resources=resourceServiceImpl.listResources(wanted);
}
I was running the query in the DAO which was meant to return the object based on the search. But it didn't return anything. So I sysout the query and the query comes out as follows:
SELECT * FROM test.resourcemaster where Resource_ZID like '%javax.faces.event.AjaxBehaviorEvent[source=org.primefaces.component.inputtext.InputText#79d635]%' OR Employee_ID like '%javax.faces.event.AjaxBehaviorEvent[source=org.primefaces.component.inputtext.InputText#79d635]%' OR First_Name like '%javax.faces.event.AjaxBehaviorEvent[source=org.primefaces.component.inputtext.InputText#79d635]%' OR Last_Name like '%javax.faces.event.AjaxBehaviorEvent[source=org.primefaces.component.inputtext.InputText#79d635]%'
the query was supposed to be searching on the 'wanted'
Could anyone explain what is the problem.
Your SearchResources() method accepts one parameter, which you don't supply from page. That's why AjaxBehaviorEvent is passed to it (event.toString(), to be more precise), which is the default if you don't specify parameters in method call.
Try changing the ajax listener to listener="#{resourceListView.SearchResources(resourceListView.wanted)}"
Or, simply remove the parameter from the method, and use bean wariable wanted
public void SearchResources() {
this.resources = resourceServiceImpl.listResources(this.getWanted());
}
Related
I have a managed bean as my View in which I have a method called List<ArrayList> getImages() where I query the database and get a List of entities which is returned by the method. All well and good.
My problem is that when I try to iterate over this List from with JSF using either <c:forEach or ui:repeat e.g. <c:forEach var="image" items="#{viewBean.images}"> the server, Tomee throws and exception java.lang.UnsupportedOperationException: Result lists are read-only. and I'm not even doing anything with the values at this point.
If I just return the ArrayList with simple objects, no problem. I understand it must be something to do with the fact the object is an entity therefore tied to the database but I'm not sure the correct way, or best practice, to return the what I need to the JSP page.
Thanks.
Jason.
Edit. Below is method used for retrieving objects from db for iteration in JSF.
public List<ProfileImage> getProfileImageList() {
profileImageList = facade.findAllByProfileId(1L);
while (profileImageList.size() < 4) {
// Add placeholders to bring the list size to 4
ProfileImage placeHolder = new ProfileImage();
placeHolder.setProfileId(1L);
profileImageList.add(placeHolder);
}
return Collections.unmodifiableList(profileImageList);
}
JSF snippet below : Note, I am not doing anything with the value of var for now
<ui:repeat value="${imageUploadView.profileImageList}" var="profileImage">
<p:commandButton id="imageBtn_1" value="Picture 1" type="button" />
<p:overlayPanel id="imagePanel_1" for="imageBtn_1" hideEffect="fade" >
<ui:include src="/WEB-INF/xhtml/includes/profile_imageupload.xhtml" />
</p:overlayPanel>
</ui:repeat>
The following error is generated
javax.el.ELException: Error reading 'profileImageList' on type com.goobang.view.ImageUploadView
viewId=/profile/create_profile.xhtml
location=/Users/xxxxxxxxx/Documents/NetBeansProjects/testmaven/target/testmaven-1.0-SNAPSHOT/profile/create_profile.xhtml
phaseId=RENDER_RESPONSE(6)
Caused by:
java.lang.UnsupportedOperationException - Result lists are read-only.
at org.apache.openjpa.lib.rop.AbstractResultList.readOnly(AbstractResultList.java:44)
/profile/create_profile.xhtml at line 16 and column 87 value="${imageUploadView.profileImageList}"
I have solved it. The exception is thrown because I am modifying the list after assigning it to the result set. If I simply return the result set all is fine. So to achieve what I intended in getProfileImageList() I created a new ArrayList from the original, as suggested by tt_emrah, and then modify that before returning it.
public List<ProfileImage> getProfileImageList() {
profileImageList = new ArrayList(facade.findAllByProfileId(1L));
while (profileImageList.size() < 4) { // Add placeholders to bring the list size to 4
ProfileImage placeHolder = new ProfileImage();
placeHolder.setProfileId(1L);
profileImageList.add(placeHolder);
}
return profileImageList;
}
I use in my project a p:autoComplete with multiSelection = true and forceSelection = false. I use it to add "tags" to my object.
This works indeed very good and is very useful.
Now I got a question and I hope it is possible to solve it.
Example
Tags stored in database: test, example
If I type test, or example, autocomplete makes a suggestion.
Now i would like to type:
primefaces
which is not found in db. Now I want to push this value from my autocomplete into the database.
How can I do that?
Regards
LStrike
OK, I made up a solution, which works fine for me.
Primefaces autocomplete:
<p:autoComplete id="mulitAutoSchlagWorte"
value="#{entityHandler.entity.tags}"
completeMethod="#{entityListHandler.completeAreaWithCreation}"
var="_tag"
itemLabel="#{_tag.value}"
itemValue="#{_tag}"
multiple="true"
size="300"
converter="#{entityConverter}">
</p:autoComplete>
List Handler, which also creates a new Tag:
public List<Tag> completeAreaWithCreation(String query) {
List<Tag> returnList = this.entityManager.createNamedQuery(Tag.NAMED_QUERY_GET_TAGS_BY_LIKE, Tag.class).setParameter("tag", query.toLowerCase().trim() + "%").getResultList();
if(returnList.size() == 0){
if(query.endsWith(" ")){
entityHandler.create();
entityHandler.getEntity().value(query.trim());
entityHandler.save();
}
returnList = completeAreaWithCreation(query.trim());
}
return returnList;
}
I am stuck with an issue on valueChangeListener. I am using JSF 1.2 on Weblogic 6.0.
I have a page, where on top of the page there are 2 radio buttons with name as Name1 and Name2. When Name1 is clicked, the Name1 details(there are about 30 fields) is displayed below the radio buttons and when Name2 is clicked, Name2 details is displayed. Now the user can updated the clicked named details. e.g. the user clicks on Name1 and changes the address field and then clicks on Name2 and changes the age of Name2. When the user clicks back Name1, the address should be shown updated with the new value and again when the user clicks on Name2, the age should be updated.
I have used valueChangeListener to tackle it because I need the old and new value of the changed event. The problem is, as the valueChangeListener is invoked at the end of the VALIDATION phase, I am not getting the updated address of the Name1 field in the valueChangeListener method. Can someone help me out to get any workaround ?
as the valueChangeListener is invoked at the end of the VALIDATION phase, I am not getting the updated address of the Name1 field in the valueChangeListener method
Queue the event to the INVOKE_ACTION phase so that it acts like as an action(listener) method.
public void valueChangeListenerMethod(ValueChangeEvent event) {
if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
event.setPhaseId(PhaseId.INVOKE_APPLICATION);
event.queue();
return;
}
// Do your original job here.
// It will only be entered when current phase ID is INVOKE_APPLICATION.
}
As INVOKE_ACTION phase runs after UPDATE_MODEL_VALUES, the updated model values will be just available "the usual way".
(Extension to BalusC answer)
As noted in my comment to BalusC answer, here the support method with usage example:
public static boolean moveToEndOfUpdateModel(FacesEvent event) {
if (event.getPhaseId() == null || event.getPhaseId().getOrdinal() < PhaseId.UPDATE_MODEL_VALUES.getOrdinal()) {
// see UIViewRoot.processUpdates(): first components.processUpdates(), then broadcastEvents()
event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
event.queue();
return true;
}
return false;
}
(And to repeat the reason for the relevant change by me:
The event is put at the end of the queue, so if you have a valueChangeEvent together with an action-method the event will be executed after the action-method - typically not what you want.)
In the listener method I use it like this:
public void myValueChangeMethod(ValueChangeEvent vce) {
if (JSFUtils.moveToEndOfUpdateModel(vce)) return;
// ... perform my actions here, with access to already updated bean values ...
}
And for JSF 2+ you can better use <f:ajax listener="..."> - if you are not forced to use a component lib not supporting this (like the old Trinidad).
Here is what I am trying to do.
I want the data from jsf page1 to be available in jsf page2 which is a popup window opened by page1.
Both have separate managed beans.
I tried using sessions but it resulted in null pointers.
I somehow managed to get the data in page2 using window.opener() in javascript.
Now I want this data to be available in the processAction() method of FacesPortlet.
Tried using request.getParameter, request.getAttributes, all in vain.
After a lot of research I somehow managed to send some hard coded data in processAction() method. But I am unable to send the value from page1.
Here is how I am sending the hardcoded value.
<form name="uploadbaseline" method="post"
enctype="multipart/form-data" action="<portlet:actionURL><portlet:param name = "page" value = "someval"/></portlet:actionURL>">
This is followed by the other fields inside the form.
I get the value in processAction() method like this
System.out.println("valuefrompage1"+request.getParameter("page"));
This returns "someval".
Now I try to assign the value from page1 using javascript using the following code.
var val = window.opener.document.getElementById("BaseLine:EngineModel").value;
var actionval = "<portlet:actionURL><portlet:param name='page' value=" + val.value + "/></portlet:actionURL>";
document.uploadbaseline.action = actionval.value;
document.uploadbaseline.submit();
This returns the value "+ val.value +" as it is and not the actual value in the "val" variable.
Please guide me in the right direction.
Keenly looking forward to your replies.
Thanks.
Found the solution finally.
The problem lies in the enctype attribute of my form.
This prevents me from accessing the page fields using the regular request.getParameter.
This needs to be handled in a different way.
Here is how.
for (Iterator requestItems = upload.parseRequest(request).iterator(); requestItems.hasNext();) {
item = (FileItem) requestItems.next(); // Get each item in the request
if (!item.isFormField()) {
//handle the file data
} else {
System.out.println((String)item.getString());
}
}
I need to automatically set the value of my inputCalendar element to the current date yet still allow the user to click on the popup calendar to change the value if they wish. The code I am using is found below.
<t:inputCalendar id="dashDelivStartDateCal" monthYearRowClass="yearMonthHeader" weekRowClass="weekHeader" popupButtonStyleClass="standard_bold" currentDayCellClass="currentDayCell" value="#{orderStatusBacking.dashDelivStartDate}" renderAsPopup="true" popupDateFormat="MM/dd/yyyy" helpText="MM/DD/YYYY">
<h:message for="dashDelivStartDateCal" showDetail="true"></h:message>
</t:inputCalendar>
Thanks in advance for the help.
Just initialize the value behind value="#{orderStatusBacking.dashDelivStartDate}" with current date instead of (default) null. You can do this in the constructor of the bean.
public class OrderStatusBacking {
private Date dashDelivStartDate;
public OrderStatusBacking() {
dashDelivStartDate = new Date();
}
// ...
}