2013-04-17 41 views
0

我有以下JSF形式:selectOneMenu用于与转换器 - java.io.NotSerializableException错误

... 
<p:column> 
    <h:outputText value="Image Id:" style="font-weight:bold; padding-right:10px" /> 
</p:column> 
<p:column> 
    <h:outputText value="#{syncCenterBean.selectedCRImageData.imId}" /> 
</p:column> 
</p:row>      
....      
<p:row> 
<p:column> 
    <h:outputText value="Image Type" style="font-weight:bold; padding-right:10px" /> 
</p:column> 
<p:column> 
    <p:selectOneMenu id="imtype" value="#{syncCenterBean.cRImageType}" converter="#{imageTypeConvert}"> 
     <f:selectItem itemLabel="Select One" itemValue="" /> 
     <f:selectItems value="#{syncCenterBean.cRImageTypeList}" var="cRImageType" itemValue="#{cRImageType.imTypeId}" itemLabel="#{cRImageType.imTypeName}" /> 
    </p:selectOneMenu> 
</p:column> 
</p:row> 
... 

所有这些都在当选择了数据表中的行加载的对话框。我有这是两个相关的Hibernate实体如下:

CRImageData

@Entity 
@Table(name = "imageviewer_crimagedata") 
public class CRImageData implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    @Column(name = "ImId") 
    private Long imId; 

    @Column(name = "ImName") 
    private String imName; 

    @Column(name = "ImTypeId") 
    private Long imTypeId; 

    @Column(name = "ImPatientId") 
    private String imPatientId; 

    @Column(name = "ImStatus") 
    private String imStatus; 

    @Column(name = "imFormat") 
    private String imFormat; 

    @ManyToOne 
    @JoinColumn(name="ImTypeId",insertable=false,updatable=false) 
    private CRImageType cRImageType; 

和CRImageType

@Entity 
@Table(name = "imageviewer_crimagetype") 
public class CRImageType implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    @Column(name = "ImTypeId") 
    private Long imTypeId; 

    @Column(name = "ImTypeName") 
    private String imTypeName; 

    @Column(name = "ImTypeDescription") 
    private String imTypeDescription; 

    @ManyToMany(cascade = {CascadeType.ALL}) 
    @JoinTable(name="imageviewer_imtype_variable", 
    joinColumns={@JoinColumn(name="ImTypeId")}, 
    inverseJoinColumns={@JoinColumn(name="VarId")}) 
    private Set<CRVariable> crvariables = new HashSet<CRVariable>(); 

    @OneToMany(mappedBy="cRImageType") 
    private Set<CRImageData> cRImageData; 

我使用的selectOneMenu用于下列转换器:

@ViewScoped 
@ManagedBean(name = "imageTypeConvert") 
@FacesConverter(forClass=CRImageType.class,value="imageTypeConvert") 
public class ImageTypeConvert implements Converter { 

    @ManagedProperty(value="#{syncCenterBean}") 
    private SyncCenterBean syncCenterBean; 
    FacesContext context = FacesContext.getCurrentInstance(); 
    SyncCenterBean mybean = (SyncCenterBean) context.getExternalContext().getSessionMap().get("syncCenterBean"); 

    @Override 
    public Object getAsObject(FacesContext context, UIComponent component, String value{ 
     Long imTypeId = Long.parseLong(value.trim()); 
     List<CRImageType> cRImageTypeList = mybean.getcRImageTypeList(); 
     for (CRImageType cRImageType:cRImageTypeList) { 
      if(cRImageType.getImTypeId().compareTo(imTypeId)==0){ 
      return cRImageType; 
     } 
     } 
     return null;  
    } 

    @Override 
    public String getAsString(FacesContext context, UIComponent component, Object value) { 
     System.out.println("!!!!!! (2) Into getAsString"); 
     return Long.toString(((CRImageType) value).getImTypeId()); 
    } 

    public SyncCenterBean getSyncCenterBean() { 
     return syncCenterBean; 
    } 

    public void setSyncCenterBean(SyncCenterBean syncCenterBean) { 
     this.syncCenterBean = syncCenterBean; 
    } 

} 

最后我的BackBean:

@ManagedBean(name = "syncCenterBean") 
@ViewScoped 
public class SyncCenterBean implements Serializable { 
    @PostConstruct 
    public void init(){ 
      cRImageTypeList = getImageTypesDB(); 
      cRImageType = new CRImageType();  

      cRImageDataList = populateImageOnlyToDataWarehouseList(getImageDataSOAP()); 

      cRImageDataListLocal = getImageDataDB(); 
    } 
    ... 

但是当我尝试加载datatabe我得到以下错误:

javax.portlet.faces.BridgeException: javax.faces.FacesException:   com.forth.actions.ImageTypeConvert 
at com.liferay.faces.bridge.BridgePhaseRenderImpl.execute(BridgePhaseRenderImpl.java:98) 
at com.liferay.faces.bridge.BridgeImpl.doFacesRequest(BridgeImpl.java:99) 
... 
Caused by: java.io.NotSerializableException: com.forth.actions.ImageTypeConvert 
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156) 
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
at java.util.HashMap.writeObject(HashMap.java:1001) 

任何想法我已经做错了吗?

+0

检查是否所有对正在被序列化的最终对象的其他对象的传递引用是否是可序列化的! – NINCOMPOOP

+0

检查,他们是和有独特的ID ... – thanili

回答

4

视图范围化bean必须是可序列化的,因为它们存储在HTTP会话中,而HTTP会话又可以以序列化形式存储在磁盘文件系统中,而不是作为内存中的常规Java对象引用存储,或通过网络传输以共享服务器群集中的会话。

要么使ImageTypeConvert请求作用域bean,而不是一个视图范围的bean,所以它不需要被序列化:

@RequestScoped 
@ManagedBean 
public class ImageTypeConvert implements Converter { 

或者让它实现串行:

@ViewScoped 
@ManagedBean 
public class ImageTypeConvert implements Converter, Serializable { 

顺便提一下,你已经遇到了严重的设计问题:永远不要将FacesContext作为类的实例变量。这不是线程安全的。将这些contextmybean声明移到方法块内部。

另请注意,我删除了@FacesConverter注释,因为如果您通过#{imageTypeConvert}将它用作受管bean,它仍然不会被使用。另外请注意,我基本上重复了默认值,因此我删除了托管bean的name