Seam的缺陷及觖决办法

环境:

Richfaces 4.3.3.Final

Seam 2.3.1.Final

JBOSS  AS 7.1.1.Final



a4j commandButton 和 commandLink 的disable 刷新问题导致 a:param 无效

Q 如果之前的一个a4j commandButton或 commandLink 是disable状态的.再a4j请求要求刷新这个button时那么button下面的所有参数将不会刷新,也就是说你在刷一个disabe的commandButton 下的a:param那么param的值不会更新,当你再点击这个按钮时将不是你想要的值.

A:没啥办法,用onclick判断下return false;吧.等seam解决吧


文件上传: rich:fileUpload 和 s:fileUpload冲突

    Q:

     使用s:fileUpload要在seam的组件描述符中设置web:multipart-filter 的disabled设为False; 并设置Form 的 enctype="multipart/form-data"

     而 rich:fileUpload 要在seam的组件描述符中设置 web:multipart-filter 的disabled设为True;并设置 web:ajax4jsf-filter , 这就冲突了!

   A:

    只能使用一种上传方式,要么s:fileUpload 要么  rich:fileUpload但这样并不完美,

  待实验:

     不知道如果 rich:fileUpload  的Form 不设置enctype="multipart/form-data" 并把web:multipart-filter 的disabled设为False可以不.

      另外有没有办法使用 url-pattern 把两种请求分开处理,这就需要使用其中的一种不发送.seam的请求..

现在我仅使用   rich:fileUpload  我的配置:

    <web:multipart-filter create-temp-files="true" max-request-size="1000000" disabled="true" url-pattern="*.seam"/>


    <web:ajax4jsf-filter force-parser="true" enable-cache="false" url-pattern="*.seam"/>



数据分页,过滤,查询,排序 使用 AJAX 页面参数

Q:

    Seam-gen生成的数据分页,过滤,排序 都是普通请求的,并且使用页面参数来保存数据状态,

A

     如果数据量不大可以使用RICHFACES的分页,过滤,排序 .

     要使用数据库分页

     页面描述符中的页面参数在AJAX请求也是有效的.只要修改下原来的模板页就可以使数据的分页,过滤,查询都成为AJAX请求的了,并且也可使用页面参数来保存数据状态,

我的修改

sort.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:s="http://jboss.org/schema/seam/taglib"
                xmlns:a="http://richfaces.org/a4j">

    <!--
        params:
            propertyPath: Query order str
            propertyLabel: title
            entityList: inherited to EntityQuery
    -->

    <a:commandLink styleClass="columnHeader" render="dataListResult,#{render}"
                   execute="@this" immediate="true"
                   value="#{propertyLabel} #{entityList.orderColumn == propertyPath ? (entityList.orderDirection == 'desc' ? messages.down : messages.up) : ''}">
        <a:attachQueue requestDelay="0"/>
        <f:param name="sort" value="#{propertyPath}"/>
        <f:param name="dir" value="#{entityList.orderColumn == propertyPath and entityList.orderDirection == 'asc' ? 'desc' : 'asc'}"/>
    </a:commandLink>


</ui:composition>

DataScroller.xhtm  只实现了上一页和下一页,待实现页码选择

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:s="http://jboss.org/schema/seam/taglib"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:a="http://richfaces.org/a4j"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:rich="http://richfaces.org/rich" xmlns:h="http://java.sun.com/jsf/html">
    <!--
       params:
           render: render fo request
           entityList: entityQuery oper
    -->

    <span class="rf-ds">
            <a:commandButton immediate="true" execute="@this"
                             action="#{entityList.first}"
                             render="dataListResult,#{render}"
                             styleClass="rf-ds-btn rf-ds-btn-fastrwd"
                             disabled="#{not entityList.previousExists}"
                             value="#{messages.left}#{messages.left}">
                <a:attachQueue requestDelay="0"/>
            </a:commandButton>
                              <!-- entityList.previousExists" -->
            <a:commandButton immediate="true" execute="@this"
                             render="dataListResult,#{render}"
                             action="#{entityList.previous}"
                             disabled="#{not entityList.previousExists}"
                             styleClass="rf-ds-btn rf-ds-btn-prev"
                             value="#{messages.left}">
                <a:attachQueue requestDelay="0"/>
            </a:commandButton>


            <a:commandButton immediate="true" execute="@this"
                             render="dataListResult,#{render}"
                             styleClass="rf-ds-btn rf-ds-btn-prev"
                             action="#{entityList.next}"
                             disabled="#{not entityList.nextExists}"
                             value="#{messages.right}">
                <a:attachQueue requestDelay="0"/>
            </a:commandButton>

            <a:commandButton immediate="true" execute="@this"
                             render="dataListResult,#{render}"
                             styleClass="rf-ds-btn rf-ds-btn-fastrwd"
                             disabled="#{not entityList.nextExists}"
                             action="#{entityList.last}"
                             value="#{messages.right}#{messages.right}">
                <a:attachQueue requestDelay="0"/>
            </a:commandButton>

    </span>
</ui:composition>

排序使用:

<rich:column>
                <f:facet name="header">
                    <ui:include src="/layout/a4jSort.xhtml">
                        <ui:param name="entityList" value="#{personList}"/>
                        <ui:param name="propertyLabel" value="#{messages.person_field_name}"/>
                        <ui:param name="propertyPath" value="person.name"/>
                    </ui:include>
                </f:facet>
                <h:outputText value="#{_person.name}"/>
            </rich:column>

过滤使用:

<h:form styleClass="edit">
    <rich:collapsiblePanel header="#{messages.search_conditions}" switchType="client">
        <s:decorate template="/layout/display.xhtml">
            <ui:define name="label">#{messages.person_field_credentialsNO}</ui:define>
            <h:inputText value="#{personList.person.credentialsNumber}"/>
        </s:decorate>
        <s:decorate template="/layout/display.xhtml">
            <ui:define name="label">#{messages.person_field_name}</ui:define>
            <h:inputText value="#{personList.person.name}"/>
        </s:decorate>

        <s:decorate template="/layout/display.xhtml">
            <ui:define name="label">#{messages.search_match}</ui:define>
            <h:selectOneRadio id="logic" value="#{personList.restrictionLogicOperator}"
                              styleClass="radio">
                <f:selectItem itemLabel="#{messages.search_match_and}" itemValue="and"/>
                <f:selectItem itemLabel="#{messages.search_match_or}" itemValue="or"/>
            </h:selectOneRadio>
        </s:decorate>

    </rich:collapsiblePanel>

    <div class="actionButtons">
        <a:outputPanel id="searchButton">
            <a:commandButton value="#{messages.search}"
                             execute="@form" render="dataListResult">
                <a:attachQueue requestDelay="0"/>
            </a:commandButton>
        </a:outputPanel>
        <s:button id="reset" value="#{messages.reset}" includePageParams="false"/>
    </div>
</h:form>

分页使用:

           <f:facet name="footer">
                <a:outputPanel rendered="#{not empty personList.resultList}">
                    <ui:include src="/layout/pageA4jNavigation.xhtml">
                        <ui:param name="entityList" value="#{personList}"/>
                    </ui:include>
                </a:outputPanel>
            </f:facet>

用于保存状态的页面参数:

    <param name="firstResult" value="#{personList.firstResult}"/>
    <param name="sort" value="#{personList.orderColumn}"/>
    <param name="dir" value="#{personList.orderDirection}"/>
    <param name="logic" value="#{personList.restrictionLogicOperator}"/>

    <param name="name" value="#{personList.person.name}"/>
    <param name="credentialsNumber" value="#{personList.person.credentialsNumber}"/>

待实验:

richfaces的extendedDataTable可以通过设置clientRows来使用AJAX动态加载分页数据,但是数据要在一个LIST中,是否可以实现一个LIST来动态的从数据库中查询分页数据


数据AJAX验证 刷新问题

Q:

seam提供了一个模板来验证数据 但是如果你的保存,修改,取消是AJAX请求的话,用例子中的方法会有刷新问题,表现为虽然你使用Render来刷的输入框,但是输入框仍然为上一次的值

A:

   要解决这个需要把a:ajax的  bypassUpdates="true" 去掉,也就是使用默认值false,并在保存的AJAX请求时刷新下所有的输入框,如果你很介意这个的话也可是使用Richfaces的验证来替换Seam的数据验证,但是要多写些代码 rich:messages的for 和 rich:vaild 另外还要去掉errors变红的css因为刷新区域不一样.


另外无论是Seam的验证还是Richfaces的验证,都可以进行JPA验证 ,验证消息的国际化文件是 ValidationMessages.properties 键值:

javax.validation.constraints.AssertFalse.message = must be false
javax.validation.constraints.AssertTrue.message  = must be true
javax.validation.constraints.DecimalMax.message  = must be less than or equal to {value}
javax.validation.constraints.DecimalMin.message  = must be greater than or equal to {value}
javax.validation.constraints.Digits.message      = numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected)
javax.validation.constraints.Future.message      = must be in the future
javax.validation.constraints.Max.message         = must be less than or equal to {value}
javax.validation.constraints.Min.message         = must be greater than or equal to {value}
javax.validation.constraints.NotNull.message     = 不允许为空
javax.validation.constraints.Null.message        = must be null
javax.validation.constraints.Past.message        = must be in the past
javax.validation.constraints.Pattern.message     = must match "{regexp}"
javax.validation.constraints.Size.message        = 长度必须在 {min} 和 {max} 之间

org.hibernate.validator.constraints.CreditCardNumber.message = invalid credit card number
org.hibernate.validator.constraints.Email.message            = not a well-formed email address
org.hibernate.validator.constraints.Length.message           = length must be between {min} and {max}
org.hibernate.validator.constraints.NotBlank.message         = may not be empty
org.hibernate.validator.constraints.NotEmpty.message         = may not be empty
org.hibernate.validator.constraints.Range.message            = must be between {min} and {max}
org.hibernate.validator.constraints.SafeHtml.message         = may have unsafe html content
org.hibernate.validator.constraints.ScriptAssert.message     = script expression "{script}" didn't evaluate to true
org.hibernate.validator.constraints.URL.message              = must be a valid URL

   

对话ID不能传递

   Q:

   ajax 刷新位置的不同可能会引发对话ID不能被正确存储到jsf树的根上,导致下一次操作时无法取得对话ID

A:有几种情况各不相同

1.刷新FORM内的一个区域, 那么将无法正确存储对话ID,区域中的链接或按钮将无法取得对话ID

2.刷新区域内有一个FORM或直接刷新FORM,那么可以正确存储对话ID

3.刷新区域没有没有嵌套在一个FORM中,这个又比较复杂 , 正常情况下 如果一个链接或按钮没有Form的话是无法进行提交操作的,但是Richfaces4的A:commandLink和a:commladbutton如果不在一个FORM中,但是在其它地方有FORM的话也可以进行提交操作 而这种情况下如果你的页面中没有JSTL 标签库 的话对话ID也是可以正常存储的 但也有也又不行,这取



使用 JSTL 标签库引起对话ID不能自动传递 

   Q:

   默认情况下Seam会把对话ID放在JSF组件树中进行传递.但是如果你的页面中使用的JSTL的标签,即c:set c:if 等 那么这个对话ID将无法传递(不知道为什么!)

 A:

    使用别的标签来替代JSTL


AJAX请求中处理 persist , update的返回值

Q:

 Richfaces的DataTable的Demo中有一个Editing的例子是使用#{facesContext.maximumSeverity==null} 来判断是否关闭panel的.但是这种方法无法判断消息的等级.

A:通过Seam的HOME中 persist , update的返回值来决定是否要关闭Panel,和是否结束对话

先要扩展下EntityHome:

package com.dgsoft.common;

import com.dgsoft.house.property.model.Developer;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Transactional;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.framework.EntityHome;
import org.jboss.seam.log.Log;

/**
 * Created with IntelliJ IDEA.
 * User: cooperlee
 * Date: 5/8/13
 * Time: 9:51 AM
 */
public class EntityHomeAdapter<E> extends EntityHome<E> {

    @Logger
    protected Log log;

    private String lastState = "";

    @BypassInterceptors
    public String getLastState() {
        return lastState;
    }

    protected boolean verifyUpdateAvailable() {
        return true;
    }

    protected boolean verifyPersistAvailable() {
        return true;
    }

    protected boolean verifyRemoveAvailable() {
        return true;
    }

    @Transactional
    @End
    public String updateEnd() {
        return this.update();
    }

    @Transactional
    @End
    public String persistEnd() {
        return this.persist();
    }

    @Transactional
    @End
    public String removeEnd() {
        return this.remove();
    }

    @Override
    public void create() {
        super.create();
        lastState = "";
    }

    @Override
    public String update() {
        lastState = "";
        if (verifyUpdateAvailable()) {
            lastState = super.update();
        }
        return lastState;
    }

    @Override
    public String persist() {
        lastState = "";
        if (verifyPersistAvailable())
            lastState = super.persist();
        return lastState;
    }

    @Override
    public String remove() {
        lastState = "";
        if (verifyRemoveAvailable())
            lastState = super.remove();
        return lastState;
    }

    @Override
    public E find() {
        lastState = "";
        return super.find();
    }

    @Override
    protected E loadInstance() {
        lastState = "";
        return super.loadInstance();
    }

    @Override
    protected E createInstance() {
        lastState = "";
        return super.createInstance();
    }

    public void refresh(){
        if (isIdDefined() && isManaged()){
            getEntityManager().refresh(getInstance());
        }
    }

}

在保存和更新的AJAX提交按钮上加上:


<a:commandButton execute="@form"
                                 render="developerListTable,developerEditPanel_inputs,developerEditPanel_title"
                                 value="#{messages.save}" action="#{developerHome.persistEnd}"
                                 rendered="#{!developerHome.managed}"
                                 data="#{developerHome.lastState}"
                                 oncomplete="if (event.data == 'persisted'){#{rich:component('developerEditPanel')}.hide();}">
                    <a:attachQueue requestDelay="0"/>
                </a:commandButton>



   



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值