【问题标题】:Passing Parameters With Seam, RichFaces & PopupPanel使用 Seam、RichFaces 和 PopupPanel 传递参数
【发布时间】:2011-06-29 15:43:03
【问题描述】:

我正在尝试使用 Seam 3、RichFaces 4 让一个小应用程序工作,并在传递一些参数时遇到了一些麻烦。我尝试了很多不同的事情,但我一直在最后的障碍上跌倒。我正在通过请求参数传递一个 customerId。但是当我在 popupPanel 上点击 RichFaces commandButton 时,我不再可以使用该 customerId。

我正在设置一个应用程序来管理一些数据。基本上,您从一个屏幕中选择一个客户,这会将您带到另一个包含“存储库”的屏幕,然后您可以在其中创建、编辑等。您可以通过 URL 访问第二个存储库页面:

http://localhost:8080/media-manager/repositories.xhtml?customer=12

然后我有一个 bean 拾取这个值:

@Named
@RequestScoped
public class RepositoryBean extends AbstractViewBean<Repository> {
    // Various properties etc. here

    private Long customerId;

    public void init() {
        log.info("Customer ID is "+ customerId);
    }
}

然后我通过存储库页面上的元数据设置客户 ID 并调用 init:

<f:metadata>
  <f:viewParam name="customer" value="#{repositoryBean.customerId}"/>
  <f:event type="preRenderView" listener="#{repositoryBean.init}" />
</f:metadata>

这在开始时效果很好。我可以使用提供的 ID 为客户显示我需要的信息。但是当我尝试创建我的 popupPanel 时出现了一些问题。这是代码的简化版本:

<rich:popupPanel id="repositoryModalPanel" modal="true" resizeable="true">
  <f:facet name="header">Title</f:facet>
  <f:facet name="controls">
    <h:outputLink value="#" onclick="#{rich:component('repositoryModalPanel')}.hide(); return false;">X</h:outputLink>
  </f:facet>
  <h:form id="modalForm" class="modalForm">
    <fieldset>
    <ul class="layout form">
      <li>
        <label for="name" class="required">Name:</label>
        <h:inputText id="name" value="#{repositoryBean.instance.name}" required="true">
          <!-- rich:validator event="blur" / -->
        </h:inputText>
        <rich:message for="name" errorClass="error errormessage" />
      </li>
      <li class="last">
        <a4j:commandButton id="create" value="Create" action="#{repositoryBean.saveRepository}" rendered="#{empty repositoryBean.instance.id}"/>
        <a4j:commandButton id="save" value="Save" action="#{repositoryBean.saveRepository}" rendered="#{not empty repositoryBean.instance.id}"/>
        <a4j:commandButton id="cancel" value="Cancel" action="#{repositoryBean.clearInstance}" immediate="true" />
      </li>
    </ul>
  </fieldset>
</h:form>

基本上,每当我点击保存命令按钮时,都会调用 init 方法,但不会填充 customerId 成员。有谁知道为什么?

我已经读到 viewParam 仅适用于 GET 请求,所以这可能是问题所在?但如果是这样的话 - 其他解决方案是什么?我看到的很多建议(例如使用@ManagedProperty)似乎不适用于Seam 3。

【问题讨论】:

    标签: java jsf-2 seam cdi seam3


    【解决方案1】:

    RepositoryBean 是 RequestScoped,因此将在每个请求上新创建,尤其是在您点击保存按钮时。

    直接的解决方案是将RepositoryBean 提升为ConversationScoped,并在您进入该页面时使其长时间运行。

    @Named
    @ConversationScoped
    public class RepositoryBean extends AbstractViewBean<Repository> {
        // Various properties etc. here
    
        @In
        Conversation conversation
    
        private Long customerId;
    
        public void init() {
            log.info("Customer ID is "+ customerId);
            conversation.begin();
        }
    }
    

    最简单的方法是转储 preRenderView 并改用 seam 3 view-action。

    <f:metadata>
      <f:viewParam name="customer" value="#{repositoryBean.customerId}"/>
      <s:viewAction action="#{repositoryBean.init}" if="#{conversation.transient}"/>
    </f:metadata>
    

    【讨论】:

    • 这确实有效,但通过偏好,我想避免仅将对话用于单个页面。你知道有什么方法可以坚持使用 requestscope 吗?
    • 当然,您可以将参数作为 GET 显式传递,而无需考虑整个 init() 机制。但是 - 除非有你没有提到的要求 - 在这种情况下避免谈话感觉绝对错误。不要忘记,将会话从瞬时提升到长期运行的整个概念在设计时完全考虑到了这个用例......当然,您不必担心任何性能下降/ 增加内存消耗这样的事情......
    猜你喜欢
    • 2023-03-27
    • 2011-06-16
    • 2012-08-15
    • 1970-01-01
    • 2015-11-12
    • 2023-04-05
    • 2013-09-29
    • 1970-01-01
    • 2013-03-15
    相关资源
    最近更新 更多