【问题标题】:rich:calendar and "The class 'java.lang.String' does not have the property ..." error丰富:日历和“类'java.lang.String'没有属性......”错误
【发布时间】:2012-01-09 20:15:51
【问题描述】:

我有以下情况:

界面

public interface Ranged{
public Object getRangeStart();
public Object getRangeEnd();

public void setRangeStart(Object rangeStart);
public void setRangeEnd(Object rangeEnd);

public void setRange(boolean isRange);
public boolean getRange();}

实现类:

public class CreationDateRange implements Ranged, Serializable{
private static final long   serialVersionUID    = SerialVersionUID.getSerialVersionUID();

public DateRange()
{
    super();
}

private Date    dateFrom;
private Date    dateTo;
private boolean isRange = false;

public Object getRangeStart()
{
    return (Date)dateFrom;
}

public Object getRangeEnd()
{
    return (Date)dateTo;
}

public void setRangeStart( Object from )
{
    this.dateFrom = (Date)from;
}

public void setRangeEnd( Object to )
{
    this.dateTo = (Date)to;
}

public void setRange( boolean isRange )
{
    this.isRange = isRange;
}

public boolean getRange()
{
    return isRange;
}}

型号:

private Object  updateDate  = new DateRange();

private Object  creationDate    = new DateRange();

public void setUpdateDate( Object updateDate )
{
    this.updateDate = updateDate;
}

public Object getUpdateDate()
{
    return updateDate;
}

public void setCreationDate( Object creationDate )
{
    this.creationDate = creationDate;
}

public Object getCreationDate()
{
    return creationDate;
}

jsf:

<f:viewParam name="creationDate" value="#{doiListController.model.creationDate}"/>
<f:viewParam name="updateDate" value="#{doiListController.model.updateDate}"/>
...
<td style="font-size: 5pt; border: 0; min-width:60px">
  <rich:calendar value="#{listModel.creationDate.rangeStart}"
        datePattern="yyyy-MM-dd" enableManualInput="true"
        rendered="#{listModel.creationDate.range}">
    <f:convertDateTime pattern="yyyy-mm-dd" />
  </rich:calendar>
</td>

错误:

>[exec] javax.faces.component.UpdateModelException: javax.el.PropertyNotFoundException: /view/doi/doiListView.xhtml @90,59 value="#{listModel.creationDate.rangeStart}": The cla
ss 'java.lang.String' does not have the property 'rangeStart'.
     [exec]     at javax.faces.component.UIInput.updateModel(UIInput.java:853)
     [exec]     at javax.faces.component.UIInput.processUpdates(UIInput.java:735)
     [exec]     at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
     [exec]     at javax.faces.component.UIForm.processUpdates(UIForm.java:281)
     [exec]     at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
     [exec]     at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1231)
     [exec]     at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
     [exec]     at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
     [exec]     at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
     [exec]     at javax.faces.webapp.FacesServlet.service(FacesServlet.java:409)
     [exec]     at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1534)
     [exec]     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
     [exec]     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
     [exec]     at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
     [exec]     at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
     [exec]     at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
     [exec]     at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
     [exec]     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
     [exec]     at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:326)
     [exec]     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:227)
     [exec]     at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:170)
     [exec]     at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822)
     [exec]     at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719)
     [exec]     at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013)
     [exec]     at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
     [exec]     at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
     [exec]     at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
     [exec]     at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
     [exec]     at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
     [exec]     at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
     [exec]     at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
     [exec]     at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
     [exec]     at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
     [exec]     at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
     [exec]     at java.lang.Thread.run(Thread.java:619)
     [exec] Caused by: javax.el.PropertyNotFoundException: /view/doi/doiListView.xhtml @90,59 value="#{listModel.creationDate.rangeStart}": The class 'java.lang.String' does not ha
ve the property 'rangeStart'.
     [exec]     at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:133)
     [exec]     at javax.faces.component.UIInput.updateModel(UIInput.java:818)
     [exec]     ... 34 more

有人可以帮我说说我错过了什么吗?

【问题讨论】:

    标签: java jsf-2 richfaces


    【解决方案1】:

    我也面临同样的问题。我通过像这样为 dataTable 添加惰性属性找到了解决方案。

     <p:dataTable lazy="true" var="itemOrder" value="#{orderBean.orderList}">
    

    但我不明白为什么。

    【讨论】:

      【解决方案2】:

      如前所述,您应该在模型字段中引入类型(最值得注意的是 updateDate 和 creationDate)。

      JSF 通过将任何字符串值转换为每个字段中指定的正确类型来更新模型。假设您有一个复杂的对象,那么 JSF 会将其存储在会话缓存中(或将其序列化,具体取决于您的 faces-config.xml)并将其保存为表单中的隐藏属性。

      当您之后提交表单时,它会尝试将此值转换回正确的类型。由于该字段的类型为Object,因此可以保持原有的String表示形式,无需转换即可立即设置该字段。如果您将类型限制为 Ranged,它将尝试转换对象,如果这不起作用,则会失败并显示正确的错误消息。

      【讨论】:

      • JSF/EL 并没有隐含地这样做。只有当您显式地 引用视图中的嵌套属性(如在 OP 的情况下为 value="#{listModel.creationDate}")时,它才会这样做。 JSF 只会在视图或会话范围内将 parent 托管 bean 存储在“会话缓存”(如您所说)中。
      【解决方案3】:

      异常和堆栈跟踪表明#{listModel.creationDate}实际上在表单提交请求的更新模型值阶段是String

      例如,如果您的视图中的某些内容事先以 String 作为参数调用了 listMode.setCreationDate(),则可能会发生这种情况。例如,&lt;f:viewParam&gt;&lt;h:inputHidden&gt;Converter-for-class 或任何其他返回 String 而不是所需对象类型的东西。

      在 setter 方法上放置一个断点并在堆栈中跟踪根本原因。或者,您也可以将 Object 类型替换为 Ranged 类型或更具体的类型,这样 JSF 可能会抛出/显示通常更不言自明的转换异常/错误。

      【讨论】:

      • 我用 Ranged 替换了 Object,现在我收到以下错误:“转换错误设置值 'ch.ethz.id.wai.doi.DateRange@8e36c0' for 'null Converter'”。无论如何,我将 Object 设置为类型,因为日期可以是一个范围或一个普通的“特定日期”。将 Object 作为类型,我可以对这两种情况使用相同的字段,并在稍后在业务逻辑中进行区分......告诉我是否如果我添加所有代码而不仅仅是片段会更有帮助...
      • 我根据 Doug 的建议更新了上面的代码,并添加了一些相关的 f:viewParam。也许会有所帮助...(我回到了 Object,因为上述原因我想拥有它)
      • 好的,您在设置String 的视图中肯定有错误的#{listModel.creationDate} 引用。删除它,您似乎根本不需要它。请阅读第 2 段和/或在 setter 方法中设置断点。
      【解决方案4】:

      我找到了这个帖子:http://forum.springsource.org/archive/index.php/t-25143.html

      这表明 JSF 可能正在使用您的设置器(接受 Object)将值设置为字符串。

      你为什么讨厌打字安全?

      你应该让你的字段类型化——UpdateDateRangeCreationDateRange 或者至少只是Ranged(为什么你有两个类来实现Ranged?这不只是两个相同类型的两个实例吗?不同的领域?)

      【讨论】:

      • JSF/EL 不会无缘无故地调用嵌套属性的设置器。它只为 EL 表达式的“端点”调用它。所以视图中一定有其他东西触发了 setter 调用并将错误的值传递给它。
      • 我同意 - 并赞成你的回答 - 我的观点是他允许将此字段设置为任何内容,同时对该字段包含的内容进行假设。
      猜你喜欢
      • 1970-01-01
      • 2011-07-26
      • 2015-03-12
      • 2013-01-05
      • 1970-01-01
      • 2011-12-20
      • 2012-03-29
      • 2013-11-01
      • 1970-01-01
      相关资源
      最近更新 更多