未调用 JSF Action(一种情况有效,而第二种情况无效)
Posted
技术标签:
【中文标题】未调用 JSF Action(一种情况有效,而第二种情况无效)【英文标题】:JSF Action not called (one case works while the second one does not) 【发布时间】:2015-10-14 20:59:40 【问题描述】:我在使用 p:commandButton 执行 jsf 操作时遇到了奇怪的行为。相应的页面负责一些创建和更新任务。因此,我可以使用空白表单访问该页面,或者继续使用已加载到表单中的一些已保存数据。未按预期工作的按钮会触发保存操作以保留表单信息。
现在这是我的问题:当我继续处理一些已保存的数据并单击“保存”时,一切正常。调用该操作并保留数据或显示验证错误。这是我通过登录 MyPhaseListener.afterPhase() 获得的一些日志语句。我剪掉了一些实际上确认我的数据被保留的日志行。
10:43:53,959 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:53,960 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE RESTORE_VIEW 1
10:43:53,960 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) Method expression of the action being invoked: #tollRegistrationBean.saveRegistration('CUSTOMER_DATA')
10:43:53,960 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:53,961 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:53,961 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE APPLY_REQUEST_VALUES 2
10:43:53,962 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) Method expression of the action being invoked: #tollRegistrationBean.saveRegistration('CUSTOMER_DATA')
10:43:53,962 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:53,963 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:53,964 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE PROCESS_VALIDATIONS 3
10:43:53,964 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) Method expression of the action being invoked: #tollRegistrationBean.saveRegistration('CUSTOMER_DATA')
10:43:53,964 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:53,965 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:53,965 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE UPDATE_MODEL_VALUES 4
10:43:53,965 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) Method expression of the action being invoked: #tollRegistrationBean.saveRegistration('CUSTOMER_DATA')
10:43:53,966 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:54,041 INFO [com.egrima.cockpit.beans.toll.TollRegistrationBean] (http-localhost/127.0.0.1:8080-1) WEB: TOLL_REGISTRATION_SAVE "registrationId:210001-2783,registrationStatus:OPEN"
10:43:54,081 DEBUG [com.egrima.cockpit.beans.toll.TollRegistrationBean] (http-localhost/127.0.0.1:8080-1) Registration saved by user noreply@example.com and customer number 210001
10:43:54,081 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:54,082 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE INVOKE_APPLICATION 5
10:43:54,083 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) Method expression of the action being invoked: #tollRegistrationBean.saveRegistration('CUSTOMER_DATA')
10:43:54,083 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:54,121 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:43:54,121 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE RENDER_RESPONSE 6
10:43:54,121 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) Method expression of the action being invoked: #tollRegistrationBean.saveRegistration('CUSTOMER_DATA')
10:43:54,121 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
现在最重要的部分是当我保存新数据时,没有调用任何操作。因此,目标不是更新现有数据,而是插入新数据,但是对于我的 JPA 层来说,这种差异比对于 JSF bean 更有趣。生命周期正常处理,但没有调用任何操作。
10:51:10,813 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,813 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE RESTORE_VIEW 1
10:51:10,813 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,813 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,813 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE APPLY_REQUEST_VALUES 2
10:51:10,814 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,814 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,814 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE PROCESS_VALIDATIONS 3
10:51:10,814 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,814 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,814 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE UPDATE_MODEL_VALUES 4
10:51:10,814 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,814 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,815 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE INVOKE_APPLICATION 5
10:51:10,815 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,825 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
10:51:10,825 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) AFTER PHASE RENDER_RESPONSE 6
10:51:10,825 INFO [com.egrima.cockpit.server.LifeCycleListener] (http-localhost/127.0.0.1:8080-1) --------------------------------------------------------------------
除了调用动作之外,它看起来非常相似。这就是我无法理解的。我单击完全相同的按钮并调用完全相同的操作。
这是我完整的带有 h:form 的 xhtml 文件。我稍微缩短了它。整个文件包含更多的输入字段(它们都遵循相同的模式)和一些仅对样式目的很重要的附加标签。
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:form id="tollCustomerForm">
<h:panelGrid columns="3" cellpadding="0" styleClass="width-100" columnClasses="width-50 valign-top, width-50 valign-top">
<h:panelGrid columns="2" columnClasses="width-30, width-70 space-right" rendered="#tollRegistrationBean.registration.customerData.company.visible">
<h:panelGroup>
<h:outputLabel for="inputCompany" value="#msg.toll_registration_customerData_company" />
<h:outputLabel value=" #msg.gloabl_required_field_sign" rendered="false" />
</h:panelGroup>
<h:inputText id="inputCompany" value="#tollRegistrationBean.registration.customerData.company.value"
styleClass="#!component.valid ? 'errorInputText' : 'dkv-inputText'" readonly="true" disabled="#tollRegistrationBean.registrationSent"
label="#msg.toll_registration_accordion_tab_customer_data - #msg.toll_registration_customerData_company" required="false" />
</h:panelGrid>
<h:panelGrid columns="2" columnClasses="width-30, width-70 space-right" rendered="#tollRegistrationBean.registration.customerData.addressAddition.visible">
<h:panelGroup>
<h:outputLabel for="inputCountry" value="#msg.toll_registration_customerData_country" />
<h:outputLabel value=" #msg.gloabl_required_field_sign" rendered="false" />
</h:panelGroup>
<h:inputText id="inputCountry" value="#tollRegistrationBean.getCountryName(tollRegistrationBean.registration.customerData.country.value)"
styleClass="#!component.valid ? 'errorInputText' : 'dkv-inputText'" readonly="true" disabled="#tollRegistrationBean.registrationSent"
label="#msg.toll_registration_accordion_tab_customer_data - #msg.toll_registration_customerData_country" required="false" />
</h:panelGrid>
<h:panelGrid columns="2" columnClasses="space-left width-30, width-70" rendered="#customerBean.renderCustomernumbers">
<h:panelGroup>
<h:outputLabel for="inputCustomerNumber" value="#msg.toll_registration_customerData_customerNumber" />
<h:outputLabel value=" #msg.gloabl_required_field_sign" rendered="false" />
</h:panelGroup>
<h:inputText id="inputCustomerNumber" value="#customerBean.customernumber"
styleClass="#!component.valid ? 'errorInputText' : 'dkv-inputText'" readonly="true" disabled="#tollRegistrationBean.registrationSent"
label="#msg.toll_registration_accordion_tab_customer_data - #msg.toll_registration_customerData_customerNumber" required="false" />
</h:panelGrid>
<h:panelGrid columns="2" columnClasses="space-left width-30, width-70" rendered="#tollRegistrationBean.registration.customerData.email.visible">
<h:panelGroup>
<h:outputLabel for="inputEmail" value="#msg.toll_registration_customerData_email" />
<h:outputLabel value=" #msg.gloabl_required_field_sign" rendered="false" />
</h:panelGroup>
<h:inputText id="inputEmail" value="#tollRegistrationBean.registration.customerData.email.value"
styleClass="#!component.valid ? 'errorInputText' : 'dkv-inputText'" readonly="true" disabled="#tollRegistrationBean.registrationSent"
label="#msg.toll_registration_accordion_tab_customer_data - #msg.toll_registration_customerData_email" required="false" />
</h:panelGrid>
</h:panelGrid>
<!-- ########## THE STRANGE SAVE BUTTON ########## -->
<p:commandButton value="#msg.toll_registration_accordion_save_step_button" id="saveRegBtn" update=":tollAccordion :tollSelectionForm:globalMessages :tollSelectionForm:registrationProgressBar"
action="#tollRegistrationBean.saveRegistration('CUSTOMER_DATA')" disabled="#tollRegistrationBean.registrationSent" styleClass="dkv-button" >
<p:resetInput target=":tollAccordion:tollCustomerForm" />
</p:commandButton>
<!-- ########## THE STRANGE SAVE BUTTON ########## -->
<!-- preValidation method only executed, if submit button is pressed (not called, if save-button is clicked) -->
<h:panelGroup rendered="#param['tollAccordion:tollCustomerForm:saveAndNextStepRegBtn']!=null">
<f:event listener="#tollRegistrationBean.listenNextAccordionStep" type="preValidate" />
<f:attribute name="currentAccordionStep" value="CUSTOMER_DATA" />
</h:panelGroup>
</h:form>
</ui:composition>
这个 ui:composition 包含在另一个带有布局信息的 xhtml 文件中。这个布局模板相当不起眼,它不包含 h:form,因此没有嵌套表单。
和我的(缩短的)jsf bean
@Component
@Scope("view")
public class TollRegistrationBean implements Serializable
...
@PostConstruct
public void init()
// get registrationId by param and load registration
RequestContext context = RequestContext.getCurrentInstance();
String registrationId = (String)context.getCallbackParams().get(TollRegistrationMainBean.CALLBACK_PARAM_SELECTED_REGISTRATION_ID);
if (registrationId != null && !registrationId.isEmpty())
registration = tollPersistingService.loadRegistrationAndCheckFields(registrationId);
if (registration != null)
createAccordionOrder();
selectedTolls = registration.getTollTypes();
// update saved customer data, read from DB, with data from crm
tollCustomerBean.loadCustomerDataFromCRM(registration);
activeIndex = 0;
registrationSent = false;
public void saveRegistration(String currentAccordionStep)
log.info("TollRegistrationBean.saveRegistration()");
try
tollPersistingService.saveRegistration(registration, customerBean.getCustomernumber());
activeIndex = accordionOrder.indexOf(currentAccordionStep);
registration.getStepByStepName(StepName.valueOf(currentAccordionStep)).setCssAccordionIcon("");
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, MessageUtils.getMessage("toll_registration_info_saved_successfully"), ""));
String userEmail = UserUtils.getCurrentUser().getEmailAddress();
log.database(AdvancedLoggerUtils.Actions.TOLL_REGISTRATION_SAVE.name(), registration.toDatabaseLogString(), userEmail,
AdvancedLoggerUtils.System.WEB.name());
log.debug("Registration saved by user " + userEmail + " and customer number " + customerBean.getCustomernumber());
catch (Exception e)
log.error(e.getMessage(), e);
我正在使用 JSF 2.2、Primefaces 5.2 和 Spring 4.1.4.RELEASE。
有没有人遇到过相同或类似的问题?对于任何帮助或提示,我将不胜感激。我有点坚持这个。
感谢和问候 塞巴斯蒂安
【问题讨论】:
你正在使用 Spring...为什么不将它添加到标签中? 您能否将整个表单附加到您的帖子中? 我更新了spring信息和上面的tag(感谢提示),下面贴出了我的xhtml文件。 【参考方案1】:早上好,塞巴斯蒂安,
如果 p:remoteCommand 仍在运行,则无法提交表单。 你必须把它放在一个单独的表格中......
最好的问候
【讨论】:
你怎么知道 OP 正在使用 remoteCommand?问题中的任何地方都没有说明(无论如何我都可以看到)。是否有一些文档说明您在此处获得的此信息作为答案?以上是关于未调用 JSF Action(一种情况有效,而第二种情况无效)的主要内容,如果未能解决你的问题,请参考以下文章
如果关联组件未呈现,是不是可以调用 JSF Bean 的 Setter?
JSF2 commandButton 操作未在更新的片段中调用