我有下一个表格:
<h:form>
<h:selectManyListbox value="#{reports.selectedCategories}"
converter="#{categoryConverter}">
<f:selectItems value="#{reports.categories}"/>
</h:selectManyListbox>
<h:commandButton value="Submit" action="#{reports.action}" />
</h:form>
我使用自定义转换器将Category转换为字符串,反之亦然:
public class CategoryConverter implements Converter {
@Autowired
private CategoryService categoryService;
public Object getAsObject(FacesContext context, UIComponent component, String value) {
System.out.println ("CONVERTER: GET AS OBJECT");
return categoryService.findByName (value);
}
public String getAsString(FacesContext context, UIComponent component, Object value) {
System.out.println ("CONVERTER: GET AS STRING");
return ((Category) value).getName ();
}
}
最后我的支持bean代码:
public class ReportsController {
private Category[] selectedCategories;
public void setSelectedCategories (Category[] categories) {
System.out.println ("SET CATEGORIES");
this.selectedCategories = categories;
}
public Category[] getSelectedCategories () {
System.out.println ("GET CATEGORIES");
return selectedCategories;
}
public void action () {
System.err.println ("ACTION");
}
....
//methods for accessing data
}
当我启动我的应用程序时,我看到正确的列表框包含2个项目和一个“提交”按钮。但是当我按提交时没有任何反应。我看到的唯一输出是:
GET CATEGORIES
CONVERTER: GET AS STRING
CONVERTER: GET AS STRING
既没有调用setSelectedCategories()也没有调用action()方法。我不明白为什么。有什么建议吗?
UPD:问题更加愚蠢:当我评论与Category类相关的所有内容(即我的selectManyListbox,我的转换器,所有相关的setter和getter)并且只留下方法操作时,它仍然没有被调用。<h:form>
<h:commandButton value="Submit" action="#{reports.action}" />
</h:form>
UPD2:这是相位监听器的输出
START PHASE RESTORE_VIEW 1
END PHASE RESTORE_VIEW 1
START PHASE APPLY_REQUEST_VALUES 2
END PHASE APPLY_REQUEST_VALUES 2
START PHASE PROCESS_VALIDATIONS 3
END PHASE PROCESS_VALIDATIONS 3
START PHASE UPDATE_MODEL_VALUES 4
END PHASE UPDATE_MODEL_VALUES 4
START PHASE INVOKE_APPLICATION 5
END PHASE INVOKE_APPLICATION 5
START PHASE RENDER_RESPONSE 6
GET STR
END PHASE RENDER_RESPONSE 6
似乎所有阶段都运转正常,但事实并非如此。我有点困惑。
答案 0 :(得分:3)
当JSF表单提交失败时,您需要确保以下内容:
UICommand
个组件必须嵌套在UIForm
组件中。
<h:form>
<h:commandButton value="submit" action="#{bean.submit}" />
</h:form>
您不能将多个 UIForm
组件嵌套在一起,这是HTML规范所禁止的。注意包含的页面/子视图,这些帐户在组件树中!如果jsp:include
已经在h:form
内,您需要从包含页面中删除h:form
!
<h:form>
<h:form>
<h:commandButton value="this will not work" action="#{bean.fail}" />
</h:form>
</h:form>
不应该发生任何验证/转换错误(使用h:messages
来完成所有操作)。
<h:form>
<h:commandButton value="submit" action="#{bean.submit}" />
<h:messages />
</h:form>
如果UICommand
组件嵌套在UIData
组件中(例如h:dataTable
),请确保完全相同的DataModel(value
属性后面的对象)保留。最简单的测试方法是将bean放在会话范围内。如果这样可以解决问题,那么您需要查看数据加载逻辑。
组件的rendered
和disabled
属性以及所有父组件不应进行负面评估。最简单的测试方法是将bean放在会话范围内。如果这样可以解决问题,那么您需要查看对此负责的代码。
请确保没有PhaseListener
或任何EventListener
更改了请求生命周期以跳过调用操作阶段。
请确保同一请求链中没有Filter
/ Servlet
以某种方式阻止了FacesServlet
的请求。
关于你的实际问题;你没有得到PropertyNotFoundException
或类似的,而你的PhaseListener
已经很好地执行了所有适当的生命周期阶段,所以我认为你的问题实际上是由 2引起的。嵌套表格。
答案 1 :(得分:2)
当JSF表单“不起作用”时,这通常表明某些内容(通常是组件,验证器或转换器)已指示生命周期某些输入无效且应停止处理和重新生成渲染视图。这可以防止垃圾数据进入您的模型,并阻止您的业务逻辑对无效输入采取行动。
alt text http://java.sun.com/javaee/5/docs/tutorial/backup/update3/doc/images/jsfIntro-lifecycle.gif Figure from JEE5 Tuorial
这将取决于您的视图配置以及您插入其中的任何代码的逻辑。作为Slartibartfast says,向视图添加<h:messages />
标记通常会告知您哪些组件触发了此响应。在调试期间配置PhaseListener通常很有用,可以告诉您在请求期间完成了哪些阶段。
public void action () {
System.err.println ("ACTION");
}
此action方法应返回String
:
public String action () {
System.err.println ("ACTION");
return null;
}
某些实现容忍void
返回类型,但它违反了规范。必须将action
属性绑定到the spec中定义的应用程序操作:
申请行动
...
- 该方法必须公开。
- 该方法必须不带参数。
- 该方法必须返回Object。
动作方法将被调用 默认的ActionListener 实施,如中所述 第7.1.1节“ActionListener 物业“上面。它的责任是 执行所需的应用程序 动作,然后返回一个逻辑 “结果”(表示为字符串) 一个可以使用的 NavigationHandler以便 确定应该是哪个视图 接下来呈现。
答案 2 :(得分:1)
因为在“converter”下你应该提供faces-config.xml中定义的转换器名称:
<converter>
<converter-id>myConverter</converter-id>
<converter-class>com.example.converters.MyConverter</converter-class>
</converter>
表格中也有<h:messages/>
通常在这种情况下有用,因为你看错了。