views:

891

answers:

1

I am trying to create a pretty straight forward screen that has a text field with auto-complete functionality. I have been following the examples found on the ICEFaces website here. No matter what I try I keep getting this error:

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)

The stack trace never points to any of my code directly so I am having trouble tracking this down. I am sure it is something I am doing wrong. Following the example from the website above for Auto-completes I have a Dictionary class (called AutoCompleteDictionary) and Bean Class (called AutoCompleteBean). The section in the jsp for the component looks like:

<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>

And 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);
        }

    }
}

And 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;
    }

}

And what I added to my 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>

I know this is a lot of information, but does anyone have any pointers or might see what I am doing wrong?

A: 

We do not need read to documentation to predict how this method

public List getCityMatchPossibilities() { ... }

is used here:

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

But your method is not so simple:

public SelectItemGroup getStringMatchPossibilities() { ... }
serge_bg
Sorry, that was something else I had tried. Originally it did just return a List object. when that did not work, I tried SelectItemGroup. Any suggestions?
jschoen