title: Error adding auto-complete component to ICEFaces screen
body: <p>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 <a href="http://component-showcase.icefaces.org/component-showcase/showcase.iface?rvn=3" rel="nofollow noreferrer">here</a>.  No matter what I try I keep getting this error:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>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:</p>
  
  <pre><code>&lt;ice:selectInputText id="acModelNumber" rows="10" width="216" style="left: 240px; top: 124px; position: absolute" value="#{autoCompleteBean.selectedStringValue1}" valueChangeListener="#{autoCompleteBean.selectInputValueChanged}"&gt;
       &lt;f:selectItems id="acModelNumberItems" value="#{autoCompleteBean.stringMatchPossibilities}"/&gt;
  &lt;/ice:selectInputText&gt;
  </code></pre>
  
  <p>And AutoCompleteDictionary.java</p>
  
  <pre><code>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 &lt; 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() &amp;&amp; LABEL_COMPARATOR.compare(searchItem, stringDictionary.get(insert)) == 0) {
                      while (insert &gt; 0 &amp;&amp; LABEL_COMPARATOR.compare(searchItem, stringDictionary.get(insert - 1)) == 0) {
                          insert = insert - 1;
                      }
                  }
              }
  
              for (int i = 0; i &lt; 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) &gt;= stringDictionary.size() ||
                          i &gt;= 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&lt;String&gt; temp = //get list of strings via a db call;
  
              stringDictionary = new ArrayList(temp.size());
              String tmpString;
              for (int i = 0, max = temp.size(); i &lt; max; i++) {
                  tmpString =  temp.get(i);
                  if (tmpString != null &amp;&amp; !tmpString.equals("")) {
                      stringDictionary.add(new SelectItem(tmpString, tmpString));
                  }
              }
              temp.clear();
  
              Collections.sort(stringDictionary, LABEL_COMPARATOR);
          }
  
      }
  }
  </code></pre>
  
  <p>And AutoCompleteBean.java</p>
  
  <pre><code>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 = "";
      }
  
      /**
       * &lt;p&gt;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.&lt;/p&gt;
       * &lt;p&gt;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 &lt; 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;
      }
  
  }
  </code></pre>
  
  <p>And what I added to my facesConfig.xml</p>
  
  <pre><code>&lt;managed-bean&gt;
      &lt;managed-bean-name&gt;autoCompleteBean&lt;/managed-bean-name&gt;
      &lt;managed-bean-class&gt;/*the package*/.AutoCompleteBean&lt;/managed-bean-class&gt;
      &lt;managed-bean-scope&gt;request&lt;/managed-bean-scope&gt;
  &lt;/managed-bean&gt;
  &lt;managed-bean&gt;
      &lt;managed-bean-name&gt;autoCompleteDictionary&lt;/managed-bean-name&gt;
      &lt;managed-bean-class&gt;/*the package*/.AutoCompleteDictionary&lt;/managed-bean-class&gt;
      &lt;managed-bean-scope&gt;application&lt;/managed-bean-scope&gt;
  &lt;/managed-bean&gt;
  </code></pre>
  
  <p>I know this is a lot of information, but does anyone have any pointers or might see what I am doing wrong?</p>