java - JBoss Seam : In ScopeType. PAGE 我得到 : java. lang.IllegalStateException:没有 Activity 的对话上下文

标签 java jsf seam

我有一个页面范围的组件,它有一个带有数据的实例变量列表,我将其显示在数据表中。该数据表具有分页、排序和过滤功能。

第一次进入该页面时,我会将其附加到我的 URL 中:?conversationId=97。该页面工作正常,当我更改数据表页面时,现在不会创建组件。

一两分钟后,在完全随机的时间,我收到一个异常,说没有上下文。我没有在我的代码或导航文件中使用@Create。

所以,我有两个问题:

  • 为什么我的网址中会出现此后缀?为什么开始对话?
  • 为什么会出现异常?该组件的作用域为 PAGE。如果我收到异常,它不应该与对话相关。正确的?或者该对话是异常(exception),指的是临时对话?

干杯!

更新一:

该项目是一个 Ear。

这是页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">

<body>
<ui:composition template="/WEB-INF/facelets/templates/template.xhtml">


<ui:define name="content">

    <!--  This method returns focus on the filter -->
    <script type="text/javascript">

    function submitByEnter(event){
        if (event.keyCode == 13) {
            if (event.preventDefault) {
                // Firefox
                event.preventDefault(); 
            } else {
                // IE 
                event.returnValue = false; 
            }
            document.getElementById("refreshButton").click();
        } 
    }

    </script>

    <h:form prependId="false">

        <h:commandButton action="Back" value="Back to home page" />
        <br />

        <p><h:outputText
            value="Applicants and Products (experimentation page)"
            class="page_title" /></p>


        <h:commandButton
            action="#{applicantProductListBean.showCreateApplicant}"
            value="Create Applicant" id="createApplicantButton">
        </h:commandButton>

        <a4j:commandButton value="Refresh" id="refreshButton"
            action="#{applicantProductListBean.refreshData}"
            image="/images/icons/refresh48x48.gif"
            reRender="compositeTable, compositeScroller">
<!--                <f:setPropertyActionListener-->
<!--                    target="# {pageScrollerBean.applicantProductListPage}" value="1" />-->
        </a4j:commandButton>

        <rich:toolTip for="createApplicantButton" value="Create Applicant" />

        <rich:dataTable styleClass="composite2DataTable" id="compositeTable"
            rows="1" columnClasses="col"
            value="#{applicantProductListBean.dataModel}" var="pageAppList">
            <f:facet name="header">
                <rich:columnGroup>
                    <rich:column colspan="3">
                        <h:outputText styleClass="headerText" value="Applicants" />
                    </rich:column>
                    <rich:column colspan="3">
                        <h:outputText styleClass="headerText" value="Products" />
                    </rich:column>
                    <rich:column breakBefore="true">
                        <h:outputText styleClass="headerText" value="Applicant Name" />



                        <a4j:commandButton id="sortingApplicantNameButton"
                            action="#{applicantProductListBean.toggleSorting('applicantName')}"
                            image="/images/icons/sorting/#{sortingFilteringBean.applicantProductListSorting.sortingValues['applicantName']}.gif"
                            reRender="sortingApplicantNameButton, sortingApplicantEmailButton, compositeTable, compositeScroller">
<!--                                    <f:setPropertyActionListener-->
<!--                                    target="#{pageScrollerBean.applicantProductListPage}" value="1" />-->
                        </a4j:commandButton>




                        <br />
                        <h:inputText
                            value="#{sortingFilteringBean.applicantProductListFiltering.filteringValues['applicantName']}"
                            id="applicantNameFilterValue"
                            onkeypress="return submitByEnter(event)">
                        </h:inputText>
                    </rich:column>
                    <rich:column>
                        <h:outputText styleClass="headerText" value="Applicant Email" />
                        <a4j:commandButton id="sortingApplicantEmailButton"
                            action="#{applicantProductListBean.toggleSorting('applicantEmail')}"
                            image="/images/icons/sorting/#{sortingFilteringBean.applicantProductListSorting.sortingValues['applicantEmail']}.gif"
                            reRender="sortingApplicantNameButton, sortingApplicantEmailButton, compositeTable, compositeScroller">
<!--                                 <f:setPropertyActionListener-->
<!--                                    target="#{pageScrollerBean.applicantProductListPage}" value="1" />-->
                        </a4j:commandButton>
                        <br />
                        <h:inputText
                            value="#{sortingFilteringBean.applicantProductListFiltering.filteringValues['applicantEmail']}"
                            id="applicantEmailFilterValue"
                            onkeypress="return submitByEnter(event)">
                        </h:inputText>
                    </rich:column>
                    <rich:column>
                        <h:outputText styleClass="headerText" value="Applicant Actions" />
                    </rich:column>
                    <rich:column>
                        <h:outputText styleClass="headerText" value="Product Name" />

                        <a4j:commandButton id="sortingProductNameButton"
                            action="#{applicantProductListBean.toggleSorting('productName')}"
                            immediate="true"
                            image="/images/icons/sorting/#{sortingFilteringBean.applicantProductListSorting.sortingValues['productName']}.gif"
                            reRender="sortingProductNameButton, compositeTable, compositeScroller">
                        </a4j:commandButton>



                        <br />
                        <h:inputText
                            value="#{sortingFilteringBean.applicantProductListFiltering.filteringValues['productName']}"
                            id="productNameFilterValue"
                            onkeypress="return submitByEnter(event)">
                        </h:inputText>
                    </rich:column>
                    <rich:column>
                        <h:outputText styleClass="headerText" value="Product Email" />
                        <br />
                        <h:inputText
                            value="#{sortingFilteringBean.applicantProductListFiltering.filteringValues['productEmail']}"
                            id="productEmailFilterValue"
                            onkeypress="return submitByEnter(event)">
                        </h:inputText>
                    </rich:column>
                    <rich:column>
                        <h:outputText styleClass="headerText" value="Product Actions" />
                    </rich:column>
                </rich:columnGroup>
            </f:facet>
            <rich:subTable rowClasses="odd_applicant_row, even_applicant_row"
                value="#{pageAppList}" var="app">
                <rich:column
                    styleClass=" internal_cell
                    composite2TextContainingColumn"
                    valign="top">
                    <h:outputText value="#{app.name}" />
                </rich:column>

                <rich:column
                    styleClass="internal_cell composite2TextContainingColumn"
                    valign="top">
                    <h:outputText value="#{app.receiptEmail}" />
                </rich:column>

                <rich:column valign="top" styleClass="buttonsColumn">
                    <h:commandButton
                        action="#{applicantProductListBean.showUpdateApplicant(app)}"
                        image="/images/icons/edit.jpg">
                    </h:commandButton>
                    <!--                    <rich:toolTip for="editApplicantButton" value="Edit Applicant" />-->
                    <h:commandButton
                        action="#{applicantProductListBean.showDeleteApplicant(app)}"
                        image="/images/icons/delete.png">
                    </h:commandButton>
                    <!--                    <rich:toolTip for="deleteApplicantButton" value="Delete Applicant" />-->
                </rich:column>



                <rich:column colspan="3">
                    <table class="productsTableTable">
                        <tbody>
                            <tr>
                                <td class="createProductButtonTableCell"><h:commandButton
                                    action="#{applicantProductListBean.showCreateProduct(app)}"
                                    value="Create Product">
                                </h:commandButton>     
<!--                    <rich:toolTip for="createProductButton" value="Create Product" />-->
                                </td>
                            </tr>
                            <tr>
                                <td><rich:dataTable value="#{app.products}" var="prod"
                                    rowClasses="odd_product_row, even_product_row">
                                    <rich:column
                                        styleClass="internal_cell composite2TextContainingColumn">
                                        <h:outputText value="#{prod.inventedName}" />
                                    </rich:column>

                                    <rich:column
                                        styleClass="internal_cell composite2TextContainingColumn">
                                        <h:outputText value="#{prod.receiptEmail}" />
                                    </rich:column>

                                    <rich:column styleClass="buttonsColumn">
                                        <h:commandButton
                                            action="#{applicantProductListBean.showUpdateProduct(prod)}"
                                            image="/images/icons/edit.jpg">
                                        </h:commandButton>
                                           <!--                         <rich:toolTip for="editProductButton" value="Edit Product" />-->
                                        <h:commandButton
                                            action="#{applicantProductListBean.showDeleteProduct(prod)}"
                                            image="/images/icons/delete.png">
                                            <f:setPropertyActionListener target="#{productBean.product}"
                                                value="#{prod}" />
                                        </h:commandButton>
                                          <!--                          <rich:toolTip for="deleteProductButton" value="Delete Product" />-->
                                    </rich:column>
                                </rich:dataTable></td>
                            </tr>
                        </tbody>
                    </table>
                </rich:column>
            </rich:subTable>
            <f:facet name="footer">
                <h:panelGrid columns="1" styleClass="applicantProductListFooter">
                    <h:outputText value="#{msgs.no_results}" rendered="#{(empty applicantProductListBean.dataModel) || (applicantProductListBean.dataModel.rowCount==0)}"/>

                    <rich:datascroller align="center" for="compositeTable"
                        page="#{pageScrollerBean.applicantProductListPage}"
                        id="compositeScroller" reRender="compositeTable"
                        renderIfSinglePage="false" fastControls="hide">
                        <f:facet name="first">
                            <h:outputText value="#{msgs.first}" styleClass="scrollerCell" />
                        </f:facet>
                        <f:facet name="first_disabled">
                            <h:outputText value="#{msgs.first}" styleClass="scrollerCell" />
                        </f:facet>
                        <f:facet name="last">
                            <h:outputText value="#{msgs.last}" styleClass="scrollerCell" />
                        </f:facet>
                        <f:facet name="last_disabled">
                            <h:outputText value="#{msgs.last}" styleClass="scrollerCell" />
                        </f:facet>
                        <f:facet name="next">
                            <h:outputText value="#{msgs.next}" styleClass="scrollerCell" />
                        </f:facet>
                        <f:facet name="next_disabled">
                            <h:outputText value="#{msgs.next}" styleClass="scrollerCell" />
                        </f:facet>
                        <f:facet name="previous">
                            <h:outputText value="#{msgs.previous}" styleClass="scrollerCell" />
                        </f:facet>
                        <f:facet name="previous_disabled">
                            <h:outputText value="#{msgs.previous}" styleClass="scrollerCell" />
                        </f:facet>
                    </rich:datascroller>
                </h:panelGrid>

            </f:facet>
        </rich:dataTable>



    </h:form>
</ui:define>

这是支持 bean:

@Name("applicantProductListBean")
@Scope(ScopeType.PAGE)
public class ApplicantProductListBean extends
    BasePagedSortableFilterableListBean {

/**
 * Public field for ad-hoc injection to work.
 */
@EJB(name = "FacadeService")
public ApplicantFacadeService applicantFacadeService;
@Logger
private static Log logger;
private final int pageSize = 10;
@Out(scope = ScopeType.CONVERSATION, required = false)
Applicant currentApplicant;
@Out(scope = ScopeType.CONVERSATION, required = false)
Product product;

@Create
public void onCreate() {
    System.out.println("Create");
}

@Override
protected DataModel initDataModel(int pageSize) {

    // get filtering and sorting from session
    sorting = getSorting();
    filtering = getFiltering();
    // System.out.println("Initializing a Composite3DataModel");
    // System.out.println("Pagesize: " + pageSize);
    // System.out.println("Filtering: " + filtering.getFilteringValues());
    // System.out.println("Sorting: " + sorting.getSortingValues());
    return new Composite3DataModel(1, sorting, filtering);
}

// Navigation methods
/**
 * Navigation-returning method, returns the action to follow after pressing
 * the "Create Applicant" button
 * 
 * @return the action to be taken
 */
public Navigation.ApplicantProductList showCreateApplicant() {

    return Navigation.ApplicantProductList.SHOW_CREATE_APPLICANT;
}

/**
 * Navigation-returning method, returns the action to follow after pressing
 * the "Edit Applicant" button
 * 
 * @return the action to be taken
 */
public Navigation.ApplicantProductList showUpdateApplicant(
        Applicant applicant) {
    this.currentApplicant = applicant;
    return Navigation.ApplicantProductList.SHOW_UPDATE_APPLICANT;
}

/**
 * Navigation-returning method, returns the action to follow after pressing
 * the "Delete Applicant" button
 * 
 * @return the action to be taken
 */
public Navigation.ApplicantProductList showDeleteApplicant(
        Applicant applicant) {
    this.currentApplicant = applicant;
    return Navigation.ApplicantProductList.SHOW_DELETE_APPLICANT;
}

/**
 * Navigation-returning method, returns the action to follow after pressing
 * the "Create Product" button
 * 
 * @return the action to be taken
 */
public Navigation.ApplicantProductList showCreateProduct(Applicant app) {

    this.product = new Product();
    this.product.setApplicant(app);
    return Navigation.ApplicantProductList.SHOW_CREATE_PRODUCT;
}

/**
 * Navigation-returning method, returns the action to follow after pressing
 * the "Edit Product" button
 * 
 * @return the action to be taken
 */
public Navigation.ApplicantProductList showUpdateProduct(Product prod) {
    this.product = prod;
    return Navigation.ApplicantProductList.SHOW_UPDATE_PRODUCT;
}

/**
 * Navigation-returning method, returns the action to follow after pressing
 * the "Delete Product" button
 * 
 * @return the action to be taken
 */
public Navigation.ApplicantProductList showDeleteProduct(Product prod) {
    this.product = prod;
    return Navigation.ApplicantProductList.SHOW_DELETE_PRODUCT;
}

/**
 * */
@Override
public Sorting getSorting() {

    if (sorting == null) {
        return (getSortingFilteringBeanFromSession()
                .getApplicantProductListSorting());
    }
    return sorting;
}

/**
 * 
 */
@Override
public void setSorting(Sorting sorting) {

    getSortingFilteringBeanFromSession().setApplicantProductListSorting(
            sorting);
}

/**
 * 
 */
@Override
public Filtering getFiltering() {

    if (filtering == null) {
        return (getSortingFilteringBeanFromSession()
                .getApplicantProductListFiltering());
    }
    return filtering;
}

/**
 * 
 */
@Override
public void setFiltering(Filtering filtering) {

    getSortingFilteringBeanFromSession().setApplicantProductListFiltering(
            filtering);
}

/**
 * @return the currentApplicant
 */
public Applicant getCurrentApplicant() {
    return currentApplicant;
}

/**
 * @param currentApplicant
 *            the currentApplicant to set
 */
public void setCurrentApplicant(Applicant applicant) {
    this.currentApplicant = applicant;
}

/**
 * The model for this page
 * 
 */
private class Composite3DataModel extends
        PagedSortableFilterableDataModel<List<Applicant>> {

    public Composite3DataModel(int pageSize, Sorting sorting,
            Filtering filtering) {

        super(pageSize, sorting, filtering);
    }

    @Override
    protected DataPage<List<Applicant>> fetchPage(int fakeStartRow,
            int fakePageSize) {

//          if (logger.isTraceEnabled()) {
            System.out.println("Getting page with fakeStartRow: " + fakeStartRow
                    + " and fakePageSize " + fakePageSize);
//          }
        // to find the page size multiply the startRow and the fakePageSize
        // (which is 1) to the actual page size
        int startRow = fakeStartRow
                * ApplicantProductListBean.this.pageSize;
        int pageSize = fakePageSize
                * ApplicantProductListBean.this.pageSize;
//          if (logger.isTraceEnabled()) {
            System.out.println("Getting page with startRow: " + startRow
                    + " and pageSize " + pageSize);
//          }
        List<Applicant> pageApplicants = applicantFacadeService
                .findPagedWithCriteria(startRow, pageSize, filtering,
                        sorting);
        // List<Applicant> pageApplicants = applicantFacadeService
        // .findPagedWithDynamicQuery(startRow, pageSize, filtering,
        // sorting, true);
//          if (logger.isTraceEnabled()) {
            System.out.println("Set of applicants: " + pageApplicants.size());
//          }
        List<List<Applicant>> pageApplicantsListContainer = new ArrayList<List<Applicant>>();
        pageApplicantsListContainer.add(pageApplicants);
        DataPage<List<Applicant>> dataPage = new DataPage<List<Applicant>>(
                this.getRowCount(), fakeStartRow,
                pageApplicantsListContainer);
        return dataPage;
    }

    @Override
    protected int getDatasetSize() {

        // int size = getServiceFacade().countWithCriteria(filtering,
        // sorting);
        // int size =
        // applicantFacadeService.countWithDynamicQuery(filtering, sorting,
        // false);
        int size = (int) Math.ceil((double) applicantFacadeService
                .countWithCriteria(filtering, sorting, false)
                / pageSize);
        if (logger.isTraceEnabled()) {
            logger.trace("Got Dataset Size: " + size);
        }
        return size;
    }
}

/**
 * @return the product
 */
public Product getProduct() {
    return product;
}

/**
 * @param product
 *            the product to set
 */
public void setProduct(Product product) {
    this.product = product;
}
}

这是页面文件(请注意,只要我不离开页面,就不会创建任何对话):

<?xml version="1.0" encoding="UTF-8"?>
<page>
<navigation>
    <rule if-outcome="Back">
        <redirect view-id="/index.xhtml" />
    </rule>
    <rule if-outcome="SHOW_CREATE_PRODUCT">
        <begin-conversation join="true" />
        <redirect view-id="/pages/product/createProduct.xhtml" />
    </rule>
    <rule if-outcome="SHOW_UPDATE_PRODUCT">
        <begin-conversation join="true" />
        <redirect view-id="/pages/product/editProduct.xhtml" />
    </rule>
    <rule if-outcome="SHOW_DELETE_PRODUCT">
        <begin-conversation join="true" />
        <redirect view-id="/pages/product/deleteProduct.xhtml" />
    </rule>
    <rule if-outcome="SHOW_CREATE_APPLICANT">
        <begin-conversation join="true" />
        <redirect view-id="/pages/applicant/createApplicant.xhtml" />
    </rule>
    <rule if-outcome="SHOW_UPDATE_APPLICANT">
        <begin-conversation join="true" />
        <redirect view-id="/pages/applicant/editApplicant.xhtml" />
    </rule>
    <rule if-outcome="SHOW_DELETE_APPLICANT">
        <begin-conversation join="true" />
        <redirect view-id="/pages/applicant/deleteApplicant.xhtml" />
    </rule>
</navigation>
</page>

更新二:

堆栈跟踪是 here

最佳答案

好吧,让我们看看

The first time gate into the page, I get this appended in my URL: ?conversationId=97

好的。正如 Seam in Action 书中所述

Seam, by default, creates a Temporary conversation to serve the current request. A Temporary conversation is initialized immediately following restore view phase of the JSF life cycle and is destroyed after the render response phase.

还有

After a minute or two, and at seamingly random time, I get an exception saying that there is no context.

每个对话都可以有自己的超时期限,默认为全局超时设置

/WEB-INF/components.xml

<core:manager conversation-timeout="1000000"/>

或特定于页面

<page view-id="/app.xhtml" timeout="1000000"/>

其值以毫秒为单位指定。但它必须超过 web.xml 中定义的 session 超时

/WEB-INF/web.xml

<!--specified in minutes-->
<session-config>
    <session-timeout>30</session-timeout>
</session-config>

也许这可以解释为什么你会得到异常(exception)。

但是如果您确实想知道是否有长时间运行的对话,Seam 会存储一个名为对话的内置对话范围组件。因此,在托管 bean 内,执行以下操作来了解是否有长时间运行的对话

org.jboss.seam.core.Conversation conversation = (Conversation) Component.getInstance("conversation");

System.out.println(conversation.isLongRunning());

如果您看到true,则说明您已经开始了长时间的对话。您甚至可以看到页面内部

#{conversation.longRunning}

希望对您有用。

关于java - JBoss Seam : In ScopeType. PAGE 我得到 : java. lang.IllegalStateException:没有 Activity 的对话上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2447658/

相关文章:

javascript - 每当您返回使用 javascript 或 jsf 的页面时,如何在 jsp 页面上维护复选框状态,而不将其存储到数据库中

java - Primefaces 5 <p :ajaxExceptionHandler/> java. lang.Exception 处理

java - 将表单提交到外部链接(但在这样做之前进行本地操作)

java - 使用重定向时 Seam 对话突然结束

java - jnlp 中的 jar 资源未由同一证书签名 ETRADE Pro 应用程序 Kubuntu 18.04

java - 从 Hibernate 中的集合中删除项目而不加载实体

jpa - Multi-Tenancy Seam + JPA 应用程序

java - 如果请求超过 1.5 秒,则不会显示 RichFaces 建议框

java - 从 commport 读取不会在 java 上返回完整结果

Java - 通过从文本文件中选择特定数字来创建字符串