如何为XMLGregorianCalendar创建JSF转换器

时间:2013-12-01 17:20:16

标签: jsf soap jsf-2 richfaces

我使用JSF和RichFaces为我的SOAP Web服务创建了一个客户端。以下是我的观点:

<h:form>
    <h:panelGrid id="panel" width="80%" columns="2" columnClasses="col1,col2">
        <rich:panel>
            <h:outputLabel value="Application Name  " />
            <h:selectOneMenu value="#{userComplaintBean.appName}">
                <f:selectItem itemValue="1" itemLabel="Select" />
                <f:selectItem itemValue="App1" itemLabel="App1" />
                <f:selectItem itemValue="App2" itemLabel="App2" />
                <f:selectItem itemValue="App3" itemLabel="App3" />
                <f:selectItem itemValue="App4" itemLabel="App4" />
                <f:selectItem itemValue="App5" itemLabel="App5" />
            </h:selectOneMenu>
            <br />
            <h:outputLabel value="Complaint Description " />
            <h:inputTextarea value="#{userComplaintBean.complaintDesc}" />
            <br />
            <h:outputLabel value="Date Expected  "/>
            <rich:calendar datePattern="yyyy/MM/dd" />
            <br/>
            <h:commandButton value="submit" action="#{userComplaintBean.save()}" />
        </rich:panel>
    </h:panelGrid>
</h:form>

以下是我的托管bean:

@ManagedBean(name = "userComplaintBean")
@RequestScoped
public class UserComplaintBean {
    UserComplaintVO userComplaintVO;
    UserComplaintWS userComplaintWS;
    UserComplaintWSImplService userComplaintWSImplService;

    private int id;
    private String appName;
    private String complaintDate;
    private String complaintDesc;
    private Date tentativeDate;

    public XMLGregorianCalendar getComplaintDate() throws DatatypeConfigurationException {
        XMLGregorianCalendar xgc = null;
        GregorianCalendar gc;
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        complaintDate = dateFormat.format(date);
        gc = (GregorianCalendar) GregorianCalendar.getInstance();
        gc.setTime(date);
        xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
        return xgc;
    }

    public void setComplaintDate(String complaintDate) {
        this.complaintDate = complaintDate;
    }

    /*
    public XMLGregorianCalendar getTentativeDate() throws DatatypeConfigurationException {
        XMLGregorianCalendar xgc = null;
        GregorianCalendar gc;
        String td;
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        
        td = dateFormat.format(tentativeDate);
        gc = (GregorianCalendar) GregorianCalendar.getInstance();
        gc.setTime(tentativeDate);
        xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
        return xgc;
    }

    public void setTentativeDate(Date tentativeDate) {
        this.tentativeDate = tentativeDate;
    }
    */

    public String save() throws DatatypeConfigurationException {
        userComplaintWSImplService = new UserComplaintWSImplService();
        userComplaintWS = userComplaintWSImplService.getUserComplaintWSImplPort();
        UserComplaintVO userComplaintVO = new UserComplaintVO();
        userComplaintVO.setAppName(getAppName());
        userComplaintVO.setComplaintDate(getComplaintDate());
        userComplaintVO.setComplaintDesc(getComplaintDesc());
        //userComplaintVO.setTentativeDate(getTentativeDate());
        userComplaintWS.userComplaintMethod(userComplaintVO);
        System.out.println("Complaint Saved...");
        return "Success";
    }
}

此处我从complaintDate开始<rich:calendar>,我需要将其转换为XMLGregorianCalendar格式,而我无法执行此操作。

如何进行上述转换?

2 个答案:

答案 0 :(得分:5)

你基本上犯了一个重大的设计错误。您不应该将特定于SOAP的模型混合到特定于JSF的模型中。 <rich:calendar>需要java.util.Date。您应该以这样的方式设计模型,以便准确提供视图所期望的内容。之后,您应该在处理JSF表单提交期间的业务服务方法中执行特定于SOAP的模型转换,作为SOAP请求的准备。

因此,理想情况下你应该使用:

private Date copmlaintDate; // +getter+setter

<rich:calendar value="#{userComplaintBean.complaintDate}" />

然后在save()方法

GregorianCalendar gc = new GregorianCalendar();
gc.setTime(complaintDate);
XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);

但是如果你出于某些原因真的有一个硬头,那么你总是可以按照以下方式破解它,因为你的环境支持EL 2.2(你的动作方法语法证实了这种情况):

private XMLGregorianCalendar copmlaintDate; // +getter (no setter necessary!)

<rich:calendar value="#{userComplaintBean.complaintDate.toGregorianCalendar().time}" />

否则,您总是可以添加一个新的getter,返回具体的java.util.Calendar实例:

public Calendar getComplaintDateAsCalendar() {
    return complaintDate.toGregorianCalendar();
}

<rich:calendar value="#{userComplaintBean.complaintDateAsCalendar.time}" />

答案 1 :(得分:1)

虽然我不完全理解使用XMLGregorianCalendar来保留日期实例而不是旧的java.util.Date的原因,但是要创建自己的@FacesConverter这将为您做出理想的转变。另外,要注意在你现在正在做的getter方法中进行业务逻辑/执行可能冗长的计算。实现这一目标的方法之一是扩展JSF内置DateTimeConverter

接下来提供启动Converter示例:

@FacesConverter("XMLGregorianCalendarConverter")
public class XMLGregorianCalendarConverter extends DateTimeConverter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if(value == null || value.equals("")) {
            return null;
        }
        Date date = super.getAsObject(context, component, value);
        GregorianCalendar gc = new GregorianCalendar();
        cg.setTime(date);
        XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
        if(xgc == null) {
            throw new ConverterException(new FacesMessage("Error converting to XMLGregorianCalendar."));
        }
        return xgc;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (!(value instanceof XMLGregorianCalendar) || (value == null)) {
            return null;
        }
        Date date = ((XMLGregorianCalendar)value).toGregorianCalendar().getTime();
        return super.getAsString(context, component, date);
    }

}