简体   繁体   中英

java.lang.ClassCastException: java.util.Collections$UnmodifiableMap cannot be cast to Param

I'm trying to write converter to my selectonemenu where I wan't to select object. My object ("Param") class looks like this:

public class Param {
private Integer id;
private String name;

public Param(Integer id, String name){
    this.id = id;
    this.name = name;
}

public Integer getId(){
    return this.id;
}
public String getName(){
    return this.name;
}

@Override
public boolean equals(Object object) {
    return (object instanceof Param) && (id != null) 
         ? id.equals(((Param) object).getId()) 
         : (object == this);
}

@Override
public int hashCode() {
    return (id != null)
        ? (this.getClass().hashCode() + id.hashCode())
        : super.hashCode();
}

}

Bean:

@ManagedBean
@SessionScoped
public class MainBean {
private List<Param> params;
private Param selectedParam;


public List<Param> getParams(){
    return this.params;
}
public Param getSelectedParam(){
    return this.selectedParam;
}
public void setSelectedParam(Param param){
    this.selectedParam = param;
}


public MainBean(){
    //filling params - works good
}

}

Converter (I know ther should be null checks and stuff):

@FacesConverter(value = "paramConverter", forClass = Param.class)
public class ParamConverter implements Converter {
private List<Param> getParams(){
    ExternalContext tmpEC;
    Map sMap;
    tmpEC = FacesContext.getCurrentInstance().getExternalContext();
    sMap = tmpEC.getSessionMap();
    MainBean mainBean = (MainBean) sMap.get("mainBean");
    return mainBean.getParams();
}

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value)
{
    Integer id = Integer.valueOf(value);
    List<Param> params = this.getParams();
    Param param = null;
    for(int i=0; i < params.size(); i++){
        if(id == params.get(i).getId()){
            param = params.get(i);
            break;
        }
    }
    return param;
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value)
{
    Param param = (Param)value;
    return String.valueOf(param.getId());
}

}

SelectOneMenu:

<h:selectOneMenu value="#{mainBean.selectedParam}">
<f:converter converterId="paramConverter" />
<f:selectItems value="#{mainBean.params}"
var="param" 
itemValue="#{param}" 
itemLabel="#{param.name}" 
/>
</h:selectOneMenu>

Tomcat output:

HTTP Status 500 - java.util.Collections$UnmodifiableMap cannot be cast to Param

--------------------------------------------------------------------------------

type Exception report

message java.util.Collections$UnmodifiableMap cannot be cast to Param

description The server encountered an internal error that prevented it from fulfilling this request.

exception 

javax.servlet.ServletException: java.util.Collections$UnmodifiableMap cannot be cast to Param
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:659)


root cause 

java.lang.ClassCastException: java.util.Collections$UnmodifiableMap cannot be cast to Param
    ParamConverter.getAsString(ParamConverter.java:40)
    com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getFormattedValue(HtmlBasicRenderer.java:521)
    com.sun.faces.renderkit.html_basic.MenuRenderer.renderOption(MenuRenderer.java:534)
    com.sun.faces.renderkit.html_basic.MenuRenderer.renderOptions(MenuRenderer.java:794)
    com.sun.faces.renderkit.html_basic.MenuRenderer.renderSelect(MenuRenderer.java:847)
    com.sun.faces.renderkit.html_basic.MenuRenderer.encodeEnd(MenuRenderer.java:297)
    javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)
    javax.faces.component.UIComponent.encodeAll(UIComponent.java:1903)
    javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
    javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:889)
    com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:304)
    com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:115)
    javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:889)
    javax.faces.component.UIComponent.encodeAll(UIComponent.java:1896)
    javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
    javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:889)
    javax.faces.component.UIComponent.encodeAll(UIComponent.java:1896)
    javax.faces.component.UIComponent.encodeAll(UIComponent.java:1899)
    javax.faces.component.UIComponent.encodeAll(UIComponent.java:1899)
    com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:451)
    com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
    com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)

I gues that getAsString method gets UnmodifiableMap object as value, but it should be Param object, am I right?

Please help me

Ps. Sorry about my english if I did some mistakes ;P

The problem is here in the var attribute.

<f:selectItems value="#{mainBean.params}"
    var="param" 
    itemValue="#{param}" 
    itemLabel="#{param.name}" 
/>

The #{param} is a reserved EL variable referring the ServletRequest#getParameterMap() which is of type Map<String, String[]> and indeed an unmodifiable map.

You shouldn't be using reserved EL variable names for own variables. Rename it to something else, eg _param or so.

<f:selectItems value="#{mainBean.params}"
    var="_param" 
    itemValue="#{_param}" 
    itemLabel="#{_param.name}" 
/>

Your converter, albeit a bit clumsy and not entirely robust, is totally fine.

Here check that working code and try to find a mistake yourself. It will make you remember it harded:)

                                <h:selectOneMenu rendered="#{categoryConverterBean.rendered}" class="subcategory" id="subcategory" converter="#{subcategoryConverterBean}" value="#{auctionBean.subCategory}">  

                                    <f:selectItems 
                                        value="#{categoryListBean.subcategory}" 
                                        var="subcategory"
                                        itemLabel="#{subcategory.subName}" 
                                        itemValue="#{subcategory}" 
                                        />
                                </h:selectOneMenu>

auctionBean (nothing special):

public Subcategory getSubCategory() {
    return subCategory;
}

public void setSubCategory(Subcategory subCategory) {
    this.subCategory = subCategory;
}

subcategoryConverter:

@ManagedBean(name = "subcategoryConverterBean") 
@FacesConverter(value = "subcategoryConverter")
public class SubcategoryConverter implements Converter {

    @PersistenceContext()
    private transient EntityManager em;

    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) {
        // TODO Auto-generated method stub
            System.out.println("wybrales: " + value);
        Query query = em.createQuery("SELECT c FROM Subcategory c WHERE c.subId=?1");
        query.setParameter("1", Integer.parseInt(value));

        return query.getSingleResult();
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {
        // TODO Auto-generated method stub
        return ((String) String.valueOf(((Subcategory) value).getSubId()));
    }

}

and finally categoryListBean:

@ManagedBean
public class CategoryListBean {

    private List<CategoryBean> category;
    private List<SubcategoryBean> subcategory;

    @EJB
    CategoryEAO service;

    public List<CategoryBean> getCategory() {
        category = service.getCategories();
        return category;
    }

    public void setCategory(List<CategoryBean> category) {
        this.category = category;
    }

    public List<SubcategoryBean> getSubcategory() {
        subcategory = service.getSubcategories();
        return subcategory;
    }

    public void setSubcategory(List<SubcategoryBean> subcategory) {
        this.subcategory = subcategory;
    }
}

I would focus on your getAsObject method because it looks like you dont get Param object as you think you do

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM