0

我有以下JSF表格:

...
<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();
    }
   ...

但是当我尝试加载数据表时,出现以下错误:

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)

有什么想法我一直在做错吗?

4

1 回答 1

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注释,因为如果您将其用作托管 bean,则它从未被使用过#{imageTypeConvert}。另请注意,我删除了name托管 bean,因为您基本上是在重复默认值。

于 2013-04-17T12:30:44.183 回答