代码之家  ›  专栏  ›  技术社区  ›  Jacob Schoen

向冰面屏幕添加自动完成组件时出错

  •  0
  • Jacob Schoen  · 技术社区  · 15 年前

    我正在尝试创建一个非常直接的屏幕,它有一个文本字段和自动完成功能。我一直在关注IceFaces网站上的例子 here . 无论我尝试什么,我都会不断地得到这个错误:

    java.lang.ClassCastException: java.lang.String cannot be cast to javax.faces.model.SelectItem
            at com.icesoft.faces.renderkit.dom_html_basic.MenuRenderer.countSelectOptionsRecursive(MenuRenderer.java:444)
            at com.icesoft.faces.renderkit.dom_html_basic.MenuRenderer.renderSelect(MenuRenderer.java:370)
            at com.icesoft.faces.renderkit.dom_html_basic.MenuRenderer.encodeEnd(MenuRenderer.java:119)
            at com.icesoft.faces.component.ext.renderkit.MenuRenderer.encodeEnd(MenuRenderer.java:51)
            at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:836)
            at com.icesoft.faces.component.util.CustomComponentUtils.renderChild(CustomComponentUtils.java:343)
            at com.icesoft.faces.component.util.CustomComponentUtils.renderChildren(CustomComponentUtils.java:325)
            at com.icesoft.faces.component.panellayout.PanelLayoutRenderer.encodeChildren(PanelLayoutRenderer.java:75)
            at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:812)
            at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:517)
            at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
            at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
            at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
            at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
            at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
            at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
            at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
            at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:481)
            at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:153)
            at org.icefaces.netbeans.rave.web.ui.appbase.faces.ViewHandlerImpl.renderView(ViewHandlerImpl.java:296)
            at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:106)
            at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
            at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:144)
            at com.icesoft.faces.webapp.http.core.JsfLifecycleExecutor.apply(JsfLifecycleExecutor.java:19)
            at com.icesoft.faces.context.View$2$1.respond(View.java:48)
            at com.icesoft.faces.webapp.http.servlet.GlassFishAdaptingServlet$GlassFishRequestResponse.respondWith(GlassFishAdaptingServlet.java:159)
            at com.icesoft.faces.context.View$2.serve(View.java:76)
            at com.icesoft.faces.context.View.servePage(View.java:139)
            at com.icesoft.faces.webapp.http.core.SingleViewServer.service(SingleViewServer.java:52)
            at com.icesoft.faces.webapp.http.common.ServerProxy.service(ServerProxy.java:11)
            at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet$4.service(MainSessionBoundServlet.java:114)
            at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
            at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet.service(MainSessionBoundServlet.java:160)
            at com.icesoft.faces.webapp.http.servlet.SessionDispatcher$1.service(SessionDispatcher.java:42)
            at com.icesoft.faces.webapp.http.servlet.GlassFishAdaptingServlet.service(GlassFishAdaptingServlet.java:60)
            at com.icesoft.faces.webapp.http.servlet.EnvironmentAdaptingServlet.service(EnvironmentAdaptingServlet.java:63)
            at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:62)
            at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
            at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:153)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
            at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:290)
            at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
            at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
            at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
            at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
            at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272)
            at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637)
            at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568)
            at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813)
            at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
            at com.sun.enterprise.web.connector.grizzly.ssl.SSLReadTask.process(SSLReadTask.java:440)
            at com.sun.enterprise.web.connector.grizzly.ssl.SSLReadTask.doTask(SSLReadTask.java:228)
            at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
            at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
    

    堆栈跟踪从未直接指向我的任何代码,因此我在跟踪此代码时遇到问题。我确信这是我做错了什么。按照上面网站上的auto completes示例,我有一个dictionary类(称为autocompletedictionary)和bean类(称为autocompletebean)。jsp中组件的部分如下所示:

    <ice:selectInputText id="acModelNumber" rows="10" width="216" style="left: 240px; top: 124px; position: absolute" value="#{autoCompleteBean.selectedStringValue1}" valueChangeListener="#{autoCompleteBean.selectInputValueChanged}">
         <f:selectItems id="acModelNumberItems" value="#{autoCompleteBean.stringMatchPossibilities}"/>
    </ice:selectInputText>
    

    和autocompletedictionary.java

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import javax.faces.model.SelectItem;
    
    public class AutoCompleteDictionary {
    
        // initialized flag, only occures once ber deployment.
        private static boolean initialized;
    
        // list of Strings
        private static ArrayList stringDictionary;
    
        /**
         * Creates a new instnace of StringDictionary.
         */
        public AutoCompleteDictionary() {
    
            try {
                MessageLog.info(this,"AutoCompleteDictionary initialized");
                // initialized the bean, load xml database.
                synchronized (this) {
                    init();
                }
    
            } catch (Exception e) {
                 MessageLog.error(this, "Error Initializing AutoCompleteDictionary", e);
            }
        }
        /**
         * Comparator utility for sorting Strings.
         */
        private static final Comparator LABEL_COMPARATOR = new Comparator() {
    
            // compare method for string entries.
            public int compare(Object o1, Object o2) {
                SelectItem selectItem1 = (SelectItem) o1;
                SelectItem selectItem2 = (SelectItem) o2;
                // compare ignoring case, give the user a more automated feel when typing
                return selectItem1.getLabel().compareToIgnoreCase(selectItem2.getLabel());
            }
        };
    
        /**
         * Gets the stringDictionary of strings.
         *
         * @return stringDictionary list in sorted by string name, ascending.
         */
        public List getDictionary() {
            return stringDictionary;
        }
    
        /**
         * Generates a short list of cities that match the given searchWord.  The
         * length of the list is specified by the maxMatches attribute.
         *
         * @param searchWord string name to search for
         * @param maxMatches max number of possibilities to return
         * @return list of SelectItem objects which contain potential string names.
         */
        public ArrayList generateStringMatches(String searchWord, int maxMatches) {
    
            ArrayList matchList = new ArrayList(maxMatches);
    
            // ensure the autocomplete search word is present
            if ((searchWord == null) || (searchWord.trim().length() == 0)) {
                return matchList;
            }
    
            try {
                SelectItem searchItem = new SelectItem("", searchWord);
                int insert = Collections.binarySearch(
                        stringDictionary,
                        searchItem,
                        LABEL_COMPARATOR);
    
                // less then zero if we have a partial match
                if (insert < 0) {
                    insert = Math.abs(insert) - 1;
                } else {
                    // If there are duplicates in a list, ensure we start from the first one
                    if (insert != stringDictionary.size() && LABEL_COMPARATOR.compare(searchItem, stringDictionary.get(insert)) == 0) {
                        while (insert > 0 && LABEL_COMPARATOR.compare(searchItem, stringDictionary.get(insert - 1)) == 0) {
                            insert = insert - 1;
                        }
                    }
                }
    
                for (int i = 0; i < maxMatches; i++) {
                    // quit the match list creation if the index is larger than
                    // max entries in the stringDictionary if we have added maxMatches.
                    if ((insert + i) >= stringDictionary.size() ||
                            i >= maxMatches) {
                        break;
                    }
                    matchList.add(stringDictionary.get(insert + i));
                }
            } catch (Throwable e) {
                MessageLog.error(this, "Error finding Matches", e);
            }
            // assign new matchList
            return matchList;
        }
    
        /**
         * Hits the database to load the list of Model Numbers.
         */
        private static void init() throws IOException {
    
            if (!initialized) {
    
                initialized = true;
    
                List<String> temp = //get list of strings via a db call;
    
                stringDictionary = new ArrayList(temp.size());
                String tmpString;
                for (int i = 0, max = temp.size(); i < max; i++) {
                    tmpString =  temp.get(i);
                    if (tmpString != null && !tmpString.equals("")) {
                        stringDictionary.add(new SelectItem(tmpString, tmpString));
                    }
                }
                temp.clear();
    
                Collections.sort(stringDictionary, LABEL_COMPARATOR);
            }
    
        }
    }
    

    和autocompletebean.java

    import com.icesoft.faces.component.selectinputtext.SelectInputText;
    import javax.faces.event.ValueChangeEvent;
    import javax.faces.model.SelectItem;
    import javax.faces.model.SelectItemGroup;
    
    
    public class AutoCompleteBean extends BaseBean {
    
        // string dictionary
        private AutoCompleteDictionary stringDictionary;
    
        // list of possible string matches for a given string dictionary lookup
        private SelectItemGroup stringMatchPossibilities;
    
        // number of string possibilities to show
        private static int stringListLength = 15;
    
        // value associatd with first selectInput Component
        private String selectedStringValue1 = "";
        // value associatd with first selectInput Component
        private String selectedStringValue2 = "";
    
        // selected String information, assigned when user uses mouse or enter key
        // to select a String.
        private String selectedString;
    
        public AutoCompleteBean() {
            selectedString = "";
        }
    
        /**
         * <p>Called by the selectInputText component at set intervals.  By using
         * the change event we can can get the newly typed work and do a look up in
         * the string dictionary.  The list of possible strings calculatd from the string
         * dictionary is assigned back to the component for display.</p>
         * <p>If the component selected a value then we find the respective string
         * information for dispaly purposes.
         *
         * @param event jsf value change event.
         */
        public void selectInputValueChanged(ValueChangeEvent event) {
    
            if (event.getComponent() instanceof SelectInputText) {
    
                // get the number of displayable records from the component
                SelectInputText autoComplete =
                        (SelectInputText) event.getComponent();
                // get the new value typed by component user.
                String newWord = (String) event.getNewValue();
    
                stringMatchPossibilities = new SelectItemGroup();
                stringMatchPossibilities.setSelectItems((SelectItem[])(stringDictionary.generateStringMatches(newWord, stringListLength)).toArray());
    
                // if there is a selected item then find the string object of the
                // same name
                if (autoComplete.getSelectedItem() != null) {
                    selectedString = (String) autoComplete.getSelectedItem().getValue();
                    // fire effect to draw attention
                    valueChangeEffect.setFired(false);
                }
                // if there was no selection we still want to see if a proper
                // string was typed and update our selectedString instance.
                else{
                    String tmp = getFindStringMatch(newWord);
                    if (tmp != null){
                        selectedString = tmp;
                         // fire effect to draw attention
                        valueChangeEffect.setFired(false);
                    }
                }
    
            }
        }
    
        /**
         * Utility method for finding detailed string information from the list of
         * possibile strings.
         *
         * @param stringName string to search on.
         * @return found string object if any, null otherwise.
         */
        private String getFindStringMatch(String stringName) {
            SelectItem[] temp = stringMatchPossibilities.getSelectItems();
            if (stringMatchPossibilities != null) {
                SelectItem string;
                for(int i = 0, max = temp.length; i < max; i++){
                    string = temp[i];
                    if (string.getLabel().compareToIgnoreCase(stringName) == 0) {
                        return (String) string.getValue();
                    }
                }
            }
            return null;
        }
    
        public void setStringDictionary(AutoCompleteDictionary stringDictionary) {
            this.stringDictionary = stringDictionary;
        }
    
        public SelectItemGroup getStringMatchPossibilities() {
            return stringMatchPossibilities;
        }
    
        public String getSelectedString() {
            return selectedString;
        }
    
        public void setSelectedString(String selectedString) {
            this.selectedString = selectedString;
        }
    
        public String getSelectedStringValue1() {
            return selectedStringValue1;
        }
    
        public void setSelectedStringValue1(String selectedStringValue1) {
            this.selectedStringValue1 = selectedStringValue1;
        }
    
        public String getSelectedStringValue2() {
            return selectedStringValue2;
        }
    
        public void setSelectedStringValue2(String selectedStringValue2) {
            this.selectedStringValue2 = selectedStringValue2;
        }
    
        public int getStringListLength() {
            return stringListLength;
        }
    
    }
    

    以及我在facesconfig.xml中添加的内容

    <managed-bean>
        <managed-bean-name>autoCompleteBean</managed-bean-name>
        <managed-bean-class>/*the package*/.AutoCompleteBean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>
    <managed-bean>
        <managed-bean-name>autoCompleteDictionary</managed-bean-name>
        <managed-bean-class>/*the package*/.AutoCompleteDictionary</managed-bean-class>
        <managed-bean-scope>application</managed-bean-scope>
    </managed-bean>
    

    我知道这是很多信息,但有没有人有任何线索或可能看到我做错了什么?

    1 回复  |  直到 13 年前
        1
  •  0
  •   Serge Bogatyrev    15 年前

    我们不需要阅读文档就可以预测这种方法

    public List getCityMatchPossibilities() { ... }
    

    在这里使用:

    <f:selectItems id="AutoCmpTxtItms" 
                   value="#{selectInputText.cityMatchPossibilities}"/>
    

    但你的方法并不简单:

    public SelectItemGroup getStringMatchPossibilities() { ... }