代码之家  ›  专栏  ›  技术社区  ›  Markos Fragkakis

jboss seam:在scopetype.page中,我得到:java.lang.IllegalStateException:没有活动的对话上下文

  •  2
  • Markos Fragkakis  · 技术社区  · 15 年前

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

    第一次进入页面时,我会将此附加到我的url中: ?会话ID=97 . 页面工作正常,当我更改datatable页面时,不会创建now组件。

    一两分钟后,在极其随机的时间,我得到一个例外,说没有上下文。我的代码或导航文件中没有使用@create。

    所以,我有两个问题:

    • 为什么我在我的url中得到这个后缀?为什么要开始谈话?
    • 为什么会有例外?组件的作用域为页。如果我收到异常,它不应该与对话相关。正确的?或者是会话异常指的是临时会话?

    干杯!

    更新I:

    这个项目是一个耳朵。

    这是一页:

    <!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>
    

    更新二:

    stacktrace是 here

    2 回复  |  直到 15 年前
        1
  •  4
  •   Arthur Ronald    15 年前

    好吧,让我看看

    第一次进入页面时,我会将此附加到我的url中: ?会话ID=97

    好啊。正如塞姆在行动手册中所说

    默认情况下,seam创建一个临时会话来服务于当前请求。临时谈话 已初始化 紧接着 还原视图 jsf生命周期的阶段和 被摧毁 呈现响应 相位。

    一两分钟后,在极其随机的时间,我得到一个例外,说没有上下文。

    每个会话都有自己的超时时间,它 默认为全局超时设置

    /WEB-INF/components.xml
    
    <core:manager conversation-timeout="1000000"/>
    

    或页面特定

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

    其价值 以毫秒为单位指定 . 但是 必须超过 web.xml中定义的会话超时

    /WEB-INF/web.xml
    
    <!--specified in minutes-->
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    

    也许这能解释为什么你会有例外。

    但是如果您真的想知道是否有长时间运行的会话,seam会存储一个内置的会话范围组件,名为 会话 . 所以 在你的托管bean中 ,请执行以下操作,以了解您是否进行了长期对话

    org.jboss.seam.core.Conversation conversation = (Conversation) Component.getInstance("conversation");
    
    System.out.println(conversation.isLongRunning());
    

    如果你看到 ,在某种程度上,你已经开始了一段长时间的对话。你甚至可以在你的页面里看到

    #{conversation.longRunning}
    

    我希望它能对你有用。

        2
  •  0
  •   Alex Rockwell    15 年前

    尝试使组件范围的对话而不是页面。听起来你想做的事情比页面范围更大,页面范围只包含一个请求的上下文。

    我不知道你为什么把conversationid参数附加到你的url中。然而,seam中的所有通信都发生在会话的内部。如果页的作用域为,则会话为临时会话。要将会话提升为长时间运行的会话,您需要一个begin注释或在pages.xml中启动会话。

    我认为seambooking示例应用程序有一些示例代码,应该与您正在尝试的代码类似。