voyent
Messages posted by: Newlukai  XML
Profile for Newlukai -> Messages posted by Newlukai [65] Go to Page: 1, 2, 3, 4, 5 Next 
Author Message
I debugged into the ICEfaces and JSF API code in order to get a clue on this. I noticed that all ice:selectOneMenus in the form are re-instantiated between the apply request values and the render response phase as soon as the user scrolls through the entities. So they get their value from the current displayed entity.
All except for one. The one with the value and component binding stays the same object during the whole life cycle. Unfortunately I can't find out when and why this re-instantiation should happen but doesn't.

Additionally, I tested an h:inputTextarea with combined value and component binding and there was the same problem.

Is it a general issue with JSF that one can't use value and component binding at the same time or didn't I implement it the right way?

Thanks in advance
Jens
Hi there,

currently I try to find a way to get an ice:selectInputText to update the value of an ice:selectOneMenu. Why should I do such a thing? Because the user wants to have a comfortable way to select something from the ice:selectOneMenu.

The scenario is as follows: The user has a page to edit an entity or to be more specific, he has a page to edit one entity out of a list of entities. This page allows him to scroll/flick through this list of entities and editing the current one.
One attribute of those entities is represented by an ice:selectOneMenu where the user can choose an entry.
Now I had to add an ice:selectInputText accompanying this ice:selectOneMenu. This ice:selectInputText should set the value of the ice:selectOneMenu according to the user's input. E. g. if he enters "ba" and the first match is "banana", the ice:selectOneMenu should be set to "Banana".

The only way I could imagine to implement such a behaviour was to use a component binding and bind the ice:selectOneMenu to the backing bean of the ice:selectInputText:

Code:
<h:panelGroup>
   <ice:setEventPhase events="ValueChangeEvent" phase="INVOKE_APPLICATION">
     <ice:selectInputText id="devUsrID_AC"
                          rows="#{userAutoComplete.listLength}"
                          value="#{userAutoComplete.enteredUser}"
                          valueChangeListener="#{userAutoComplete.selectInputValueChanged}"
                          listVar="user"
                          listValue="#{userAutoComplete.matches}">
 
       <f:facet name="selectInputText">
         <ice:outputText value="#{user.ID} - #{user.name}"/>
       </f:facet>
     </ice:selectInputText>
   </ice:setEventPhase>
 
   <ice:setEventPhase events="ValueChangeEvent" phase="INVOKE_APPLICATION">
     <ice:selectOneMenu value="#{testaction.devUsrID}" binding="#{userAutoComplete.binding}" id="devUsrID" converter="view.converter.UserConverter" valueChangeListener="#{userAutoComplete.selectInputValueChanged}" partialSubmit="true">
       <s:selectItems value="#{mainSupplier.developers}" var="developer" label="#{developer.ID} - #{developer.name}" id="devUsrIDs" />
     </ice:selectOneMenu>
   </ice:setEventPhase>
 </h:panelGroup>


As you might guess, testaction stands for the current entity and userAutoComplete is the backing bean of the ice:selectInputText. Here is some code of this bean:

Code:
@AutoCreate
 @Stateful
 @Scope(ScopeType.SESSION)
 @Name("userAutoComplete")
 @Role(name = "userAutoComplete2", scope = ScopeType.SESSION)
 public class UserAutoComplete implements IUserAutoComplete, Serializable {
   private static final long serialVersionUID = 5406906545256206754L;
 
   private static int listLength = 20;
 
 
   @In
   private transient IUserSelector userSelector;
 
 
   private transient UIComponent binding;
 
   private String enteredUser;
   private List<SelectItem> matches;
 
 
   public void selectInputValueChanged(ValueChangeEvent event) {
     if (event.getComponent() instanceof SelectInputText) {
       SelectInputText autoComplete = (SelectInputText) event.getComponent();
 
       String newWord = (String) event.getNewValue();
 
       matches = generateMatches(newWord);
 
       User selectedUser = null;
       if (autoComplete.getSelectedItem() != null) {
         selectedUser = findUserMatch(autoComplete.getSelectedItem().getLabel());
       } else {
         selectedUser = findUserMatch(autoComplete.getValue().toString());
       }
 
       if (selectedUser != null && binding instanceof ValueHolder) {
         ((ValueHolder) binding).setValue(selectedUser);
       }
     } else {
       if (!(event.getNewValue() instanceof User)) {
         return;
       }
 
       User newUser = (User) event.getNewValue();
       enteredUser = newUser.getID();
     }
   }
   
   //some more getters/setters and private helper methods
 }


Every time the listener is invoked, whether from the ice:selectInputText or the ice:selectOneMenu, it sets a new value for the respective component. This is done by using the component binding or setting its own attribute.

All of this works fine as long as the user just edits the selected entity without scrolling/flicking to another one. Or with other words: The user enters a "b" in the ice:selectInputText on the first entity, which results in setting "banana" for the ice:selectOneMenu. Then he switches to the next entity which has an attribute of "apple" instead of "banana", the ice:selectInputText and the ice:selectOneMenu have their values still set to "banana". This would be OK and right for the ice:selectInputText. But in case of the ice:selectOneMenu I expect the value set to the attribute of the current displayed entity.
I think this behaviour is a result of the fact that I use value binding and component binding for the ice:selectOneMenu and ICEfaces confuses about the question which one to use. But I don't know a better idea on how to implement such a feature. I use the component binding because this backing bean userAutoComplete is used on more pages and the referenced entity attribute is not the same for every use.

What do you think about this? How could I handle this?

Thanks in advance
Jens
I don't use a progress bar, so I don't know if I could "disable progress upload related updates".

But I tried "progressRender=false" and it doesn't work.
Hi,

I just updated to ICEfaces 1.8.0 and use it in my application together with Seam 2.1.1 on a JBoss AS 5.0.1. The app really runs very smooth and I'm very enthusiastic about the increase in performance.

But I have a problem, and I think it's a bug. I include (via Facelets) two popupPanels on a page. One of them contains a inputFile. The other one shows some protocols. The normal use cases are like this: the user clicks on a Protocol button and a popup shows some protocols. Since the popup is modal the only thing the user can do now is to click on the Close button to hdie the popup. The other use case is the same with the other popup. The user clicks on a Up-/Download button and a popup is shown where he can upload a file or download previously uploaded files. This popup is modal, too. So he just can get rid of the popup by closing it.

The problem now is that after uploading a file (recall that only one of those popups can be shown), the protocol popup comes up. Or worse, it shows up, is closed, shows up again and is closed again for several times. All of this happening while the Up-/Download popup still is opened.
Does somebody know what I'm doing wrong or if it's a bug?

Here is the code of the including page:
Code:
<ui:define name="content">
   <s:div styleClass="formBox">
     <ice:form id="editDeveloper">
       <ui:include src="inc/messages.xhtml" />
       
       <s:div styleClass="buttonLine">
         <ice:commandButton image="img/icon_buttonLine_protocol.gif" styleClass="graphical" actionListener="#{protocolProvider.showProtocolDialog}" title="#{YTrack_msgs.tooltip_showProtocol}" immediate="true" />
         <ice:commandButton image="img/icon_buttonLine_attach.gif" styleClass="graphical" actionListener="#{editDeveloper.showUpDownloadDialog}" title="#{YTrack_msgs.tooltip_upDownload}" immediate="true" />
         <h:outputText value="(#{editDeveloper.countOfAttachedFiles})" converter="javax.faces.Long" rendered="#{editDeveloper.countOfAttachedFiles > 0}" styleClass="fileCounter" />
         
         <!-- some other buttons here -->
       </s:div>
       
       <s:div styleClass="clearButtonLineFloat" />
       
       <h:panelGrid cellpadding="0" cellspacing="0" border="0" columns="5" rowClasses="tableRowHeader, tableRowContent" styleClass="testaction">    
         <h:outputText value="#{YTrack_msgs.label_testaction_ID}" />
         <h:outputText value="#{YTrack_msgs.label_testaction_TDate}" />
                 
         <h:outputText value="#{testaction.ID}" />
         <h:outputText value="#{testaction.TDate}">
           <f:convertDateTime type="date" dateStyle="medium"/>
         </h:outputText>
       </h:panelGrid>
             
       <!-- further panelGrids -->
   
       <ui:include src="inc/popup_quickfix.xhtml" />
             
       <ui:include src="inc/popup_protocol.xhtml" />
     
       <ui:include src="inc/popup_upDownload.xhtml">
         <ui:param name="fileProvider" value="#{editDeveloper}" />
       </ui:include>
     </ice:form>
   </s:div>
 </ui:define>

As you probably might have guessed, "editDeveloper" is the backing bean of this page.

Here is the included popup_protocol.xhtml:
Code:
<ui:composition 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"
   xmlns:s="http://jboss.com/products/seam/taglib"
   xmlns:ice="http://www.icesoft.com/icefaces/component">
 
   <ice:panelPopup modal="true"
     rendered="#{protocolProvider.showProtocolDialog}"
     visible="#{protocolProvider.showProtocolDialog}"
     autoCentre="true"
     style="width: 760px; height: 550px;">
     
     <f:facet name="header">
       <ice:panelGroup>
         <ice:outputText value="#{YTrack_msgs.popuptitle_protocol}"
           styleClass="popupTitle" />
         <ice:commandButton image="img/icon_popup_close.gif"
           id="protocolPopupClose"
           actionListener="#{protocolProvider.closeProtocolDialog}"
           styleClass="popupButton"
           style="background: transparent; width: 16px;"
                     immediate="true" />
       </ice:panelGroup>
     </f:facet>
 
     <f:facet name="body">
       <s:div style="width: 100%; height: 550px; overflow: scroll;">
         <ice:panelGrid columns="1" cellpadding="0" cellspacing="0" border="0">
           <ice:outputText value="#{YTrack_msgs.protocol_noProtocols}" rendered="#{empty protocolProvider.protocols}" />
           
           <ice:dataTable value="#{protocolProvider.protocols}"
             var="protocolWrapper" styleClass="testactionList"
             rowClasses="tableRowEven, tableRowOdd"
             rendered="#{not empty protocolProvider.protocols}">
             <!-- all the columns displaying the properties of "protocolWrapper" -->
           </ice:dataTable>
         </ice:panelGrid>
       </s:div>
     </f:facet>
   </ice:panelPopup>
 </ui:composition>

"protocolProvider" is a bean which gives access to the protocols of the current entity.

And this is the included popup_upDownload.xhtml:
Code:
<ui:composition 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"
   xmlns:s="http://jboss.com/products/seam/taglib"
   xmlns:ice="http://www.icesoft.com/icefaces/component">
 
   <ice:panelPopup modal="true"
     rendered="#{fileProvider.showUpDownloadDialog}"
     visible="#{fileProvider.showUpDownloadDialog}"
     style="width: 700px;"
     autoCentre="true">
     <f:facet name="header">
       <ice:panelGroup>
         <ice:outputText value="#{YTrack_msgs.popuptitle_upDownload}"
           styleClass="popupTitle" />
         <ice:commandButton image="img/icon_popup_close.gif"
           id="upDownloadPopupClose"
           actionListener="#{fileProvider.closeUpDownloadDialog}"
           partialSubmit="true"
                     styleClass="popupButton"
           style="background: transparent; width: 16px;"
                     immediate="true" />
       </ice:panelGroup>
     </f:facet>
 
     <f:facet name="body">
       <ice:panelGrid columns="1" cellpadding="0" cellspacing="0" border="0">
         <h:dataTable value="#{fileProvider.attachedFiles}"
           var="attachedFile"
           rendered="#{!empty fileProvider.attachedFiles}"
           styleClass="testactionList" rowClasses="tableRowEven, tableRowOdd"
           style="text-align: center;">
           
           <h:column>
             <f:facet name="header">
               <h:outputText value="#{YTrack_msgs.label_upDownload_filename}" />
             </f:facet>
             <h:outputText value="#{attachedFile.name}" />
           </h:column>
           
           <h:column>
             <f:facet name="header">
               <h:outputText value="#{YTrack_msgs.label_upDownload_view}" />
             </f:facet>
             <ice:commandButton image="img/icon_upDownload_view.gif"
               styleClass="graphical" partialSubmit="true"
               action="#{fileProvider.viewFile(attachedFile)}"
               style="width: 16px;" />
           </h:column>
           
           <h:column>
             <f:facet name="header">
               <h:outputText value="#{YTrack_msgs.label_upDownload_download}" />
             </f:facet>
             <ice:commandButton image="img/icon_upDownload_download.gif"
               styleClass="graphical"
               action="#{fileProvider.downloadFile(attachedFile)}"
               style="width: 16px;" />
           </h:column>
           
           <h:column rendered="#{preventChanges ? false : true}">
             <f:facet name="header">
               <h:outputText value="#{YTrack_msgs.label_upDownload_remove}" />
             </f:facet>
             <ice:commandButton image="img/icon_upDownload_remove.gif"
               styleClass="graphical" partialSubmit="true"
               action="#{fileProvider.removeFile(attachedFile)}"
               style="width: 16px;" />
           </h:column>
         </h:dataTable>
         
         <ice:inputFile id="upload"
           actionListener="#{fileProvider.upload}"
           submitOnUpload="postUpload"
           label="#{YTrack_msgs.label_upDownload_upload}"
           style="margin-top: 30px;"
           rendered="#{preventChanges ? false : true}" />
         </ice:panelGrid>
     </f:facet>
   </ice:panelPopup>
 </ui:composition>

Note that "fileProvider" is not the name of a backing bean, it's a parameter which is set to the backing bean "editDeveloper" in the including page.

Thanks for your help
Newlukai
Here is a related post with an elegant solution.
Here you find the JIRA issue.
Hi,

I don't know if this is a known issue: When I click on "Upload" in my application without having specified the file to upload, the component rerenders and the upload button loses its label.
Should I open an issue in JIRA?

Regards
Newlukai
Any news on this? It's the second issue that isn't fixed in 1.7.1.
Any news on this? With version 1.7.1 the onblur isn't rendered.
I'll check this. It's a great hint. Thanks for that.

But with this "fix" addresses the fact that in order to render the menu those classes check for every single item if it's the selected one. But how do these classes get this information? They ask the UIComponent itself for every single item which the selected values are.
Firstly it would be more elegant to ask for the selected values only once for a menu, not n times (where n stands for the amount of items in this menu). Secondly you'll mostly find EL expressions in the value attribute of menus. And these expressions have to be resolved. That means that for every menu item the same EL expression is evaluated. Mostly this expression addresses a property of a bean and this bean has to be found. NamingContext is asked and a JNDI call is done.

I know that this behaviour isn't the only fact that reduces the performance of an application. I know that I have to check my code. But since I have large lists, this "fix" saved almost one second out of three. Now I'll check how to reduce the other two seconds ;)
And if the aspect of performance doesn't convince, perhaps you agree that this approach of asking the UIComponent every time for the selected values isn't elegant. OK, my fix isn't very elegant, too. But it just was a test to see what happens.

EDIT: All the beans providing those lists are session scope. The bigger lists contain dynamic data. There are only two or three lists that could be made "static" in session scope, but those lists are the smaller ones.

EDIT2: I found another improvement, this time it's a smaller one. menuRenderer contains a method renderSelect. In this method the size attribute is to be rendered. To render this attirbute all items in this menu are iterated and evaluated in order to count them. It's not necessary to evaluate all items in order to count them. But this one goes a step further: the size attribute always is rendered with value "1". It doesn't matter how many items are in this menu, the size always is "1".
The change of this doesn't improve the performance very much since all the items are already evaluated, but it's an unnecessary iteration.

I want to let you know that all this shouldn't be seen as a complaint from an annoyed customer ;). ICEfaces is great and I want to help to improve it.
And the last file.
Today I profiled my application again with ICEfaces 1.7.1. I don't know why, but it seems that anybody was interested in my proposal.

On several pages in my application there are multiple selectOneMenus rendered and they have many entries. While the menu is rendered MenuRenderer checks every entry if it belongs to the selected ones. The implementation of this check is time consuming since it asks the UIComponent for the selected values again and again, for every single entry. This request for the selected values uses JNDI. In my case one bean is queried over 400 times! After some code changes I got just about 70 requests for this bean. This simple change saved one second in rendering the page.

And once again I offer you my changes. Do I still have to sign this agreement? What are the consequences when I sign it?
OK. I'll test it.

I'm using Session scope.

EDIT: OK. "Disabling" the popup seems to work for me. But the problem is that this isn't a nice workaround since the page shows a lot of dropdowns and input fields. Additionally I want to use this inputFile code in several pages so I ui:include it. And the bean, where to get the file list from is provided by a ui:param. Perhaps it is tested with a "tabbed pane"?

EDIT2: Tabbed pane doesn't work ...
I've exactly the same problem. I'm using Seam 2.0.1.GA. Actually I thought this issue would be gone with ICEfaces 1.7.1 and this "submitOnUpload" attribute.
But today I tested it again and it doesn't really work. One time it works as it should and you see an updated file list, the other time it doesn't work and the list doesn't get updated. Since this behaviour can change within the same page this is really weird.
My application displays the inputFile component in a popup. And while you have this popup opened it occurs that after one file was uploaded the list gets updated and after the next file was uploaded the list doesn't get updated.

@jguglielmin: Can you please explain this a little bit more? Thank you very much.

EDIT: atm I have a look about my project since I start another one. And so I saw that I still have a file war\WEB-INF\icefaces_component.tld. Is this file still needed? I remember that I added this in the early stages of my project (Seam 1.2 and ICEfaces 1.5.3 I think).
Thank you for your advice. You're right, such a big popup is odd. I'll try to implement your workaround.

But since this is not a solution for the behaviour that chrishantha describes, the devs should have a look on this.
 
Profile for Newlukai -> Messages posted by Newlukai [65] Go to Page: 1, 2, 3, 4, 5 Next 
Go to:   
Powered by JForum 2.1.7ice © JForum Team