为什么表单提交不起作用?

时间:2010-01-12 15:17:16

标签: java jsf

我有下一个表格:

<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

似乎所有阶段都运转正常,但事实并非如此。我有点困惑。

3 个答案:

答案 0 :(得分:3)

当JSF表单提交失败时,您需要确保以下内容:

  1. UICommand个组件必须嵌套在UIForm组件中。

    <h:form>
        <h:commandButton value="submit" action="#{bean.submit}" />
    </h:form>
    
  2. 您不能将多个 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>
    
  3. 不应该发生任何验证/转换错误(使用h:messages来完成所有操作)。

    <h:form>
        <h:commandButton value="submit" action="#{bean.submit}" />
        <h:messages />
    </h:form>
    
  4. 如果UICommand组件嵌套在UIData组件中(例如h:dataTable),请确保完全相同的DataModel(value属性后面的对象)保留。最简单的测试方法是将bean放在会话范围内。如果这样可以解决问题,那么您需要查看数据加载逻辑。

  5. 组件的rendereddisabled属性以及所有父组件不应进行负面评估。最简单的测试方法是将bean放在会话范围内。如果这样可以解决问题,那么您需要查看对此负责的代码。

  6. 请确保没有PhaseListener或任何EventListener更改了请求生命周期以跳过调用操作阶段。

  7. 请确保同一请求链中没有Filter / Servlet以某种方式阻止了FacesServlet的请求。

  8. 关于你的实际问题;你没有得到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/>通常在这种情况下有用,因为你看错了。