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?