2011-01-03 16 views
1

最近、システムをJSF 1.2からJSF 2.0にアップグレードし、すべての作業を進めています。しかし、データテーブルやそれに類するコンポーネントの内部で使用される場合、バリデータに問題が発生しています。基本的に、問題は、バリデータがデータテーブルによって設定された変数を使用できないことです。JSF 2バリデーターはdataTableの "var"を使用できません

VALIDATOR:

package test; 

import javax.faces.application.FacesMessage; 
import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 
import javax.faces.validator.FacesValidator; 
import javax.faces.validator.Validator; 
import javax.faces.validator.ValidatorException; 

@FacesValidator("test.TestValidator") 
public class TestValidator implements Validator { 

    private Integer length; 

    public TestValidator() { 
     super(); 
    } 

    @Override 
    public void validate(FacesContext context, 
      UIComponent component, Object value) throws ValidatorException { 

     String text = (String) value; 
     if (text == null || text.trim().length() == 0) { 
      return; 
     } 

     if (length != null && text != null && length.intValue() < text.length()) { 
      String message = "The text is too long. It was " + text.length() + 
        ", but only " + length + " characters are allowed."; 
      FacesMessage fm = new FacesMessage(
        FacesMessage.SEVERITY_ERROR, message, null); 
      throw new ValidatorException(fm); 
     } 
    } 

    public Integer getLength() { 
     return length; 
    } 

    public void setLength(Integer length) { 
     this.length = length; 
    } 
} 

のtaglib:

<?xml version="1.0" encoding="UTF-8"?> 
    <facelet-taglib 
     xmlns="http://java.sun.com/xml/ns/javaee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd" 
     version="2.0"> 
     <namespace>http://industry-supply.dk/test</namespace> 
     <tag> 
      <tag-name>testValidator</tag-name> 
      <validator> 
       <validator-id>test.TestValidator</validator-id> 
      </validator> 
      <attribute> 
       <name>length</name> 
       <required>true</required> 
       <type>java.lang.Integer</type> 
      </attribute> 
     </tag> 
    </facelet-taglib> 

管理Bean:

package test; 

import javax.faces.bean.ManagedBean; 
import javax.faces.bean.RequestScoped; 

@ManagedBean(name = "testBean") 
@RequestScoped 
public class TestBean { 

    public TestBean() { 
    } 

    public String[] getKey() { 
     return new String[]{ 
        "0", 
        "1", 
        "2", 
        "3" 
       }; 
    } 

    public String[] getValue() { 
     return new String[]{ 
        "This is a text and it's too long.", 
        "This is a text and it's too long.", 
        "This is a text and it's too long.", 
        "This is a text and it's too long." 
       }; 
    } 
} 

JSF:

ここ

は一例です
<?xml version='1.0' encoding='UTF-8' ?> 
<!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:h="http://java.sun.com/jsf/html" 
     xmlns:test="http://industry-supply.dk/test"> 
    <h:head> 
     <title>Facelet Title</title> 
    </h:head> 
    <h:body> 
     <h:form> 
      <h:dataTable value="#{testBean.key}" var="k"> 
       <h:column> 
        <h:message for="val"/> 
        <h:inputText id="val" value="#{testBean.value[k]}"> 
         <test:testValidator length="#{testBean.key[k]}"/> 
        </h:inputText> 
       </h:column> 
      </h:dataTable> 
      <h:commandButton value="Submit"/> 
     </h:form> 
    </h:body> 
</html> 

プロジェクトを実行すると、4つの入力フィールドとコマンドボタンが表示されます。各入力フィールドには33文字の長いテキストが含まれています。 「送信」をクリックすると、「テキストが長すぎます.33文字でしたが、0文字しか使用できません」というエラーメッセージが表示されます。行/フィールドごとに表示されます。これは間違っています。「test:testValidator length = "#{testBean.key [k]}"」は、最初の行の長さを0に、2行目を1、3行目を2、4行目を3に指定しています。したがって、最後の行では、エラーメッセージに「テキストが長すぎます.33文字でしたが、3文字しか使用できません。」

問題は、バリデータがJSFファイルのdataTableコンポーネントのk変数にアクセスできないようです。これはJSF 1.2でも機能しましたが、JSF 2.0では動作しません。私たちは今問題に時間を費やし、本当に助けを必要としています。誰でもアイデア?

+0

私は多分、私はもう少し問題を指定する必要があります感じています。バリデータの長さは、リクエストの開始時に式#{testBean.key [k]}から解決された整数で設定されているようですが、後でリクエストでdataTableが反復するとき、式は再び解決されません。長さを再度設定します。 kはdataTables反復の間だけセットされるので、これは長さが要求全体を通してヌルのままであることを意味します。完璧なソリューションは、式が反復ごとに1回解決される可能性がありますが、これを強制する方法はわかりません。 –

+0

私は私の答えを書いていたときに私はこのコメントを見ませんでしたが、 'ValueExpressions'についての私の発言を見てください。バリデーターで式を評価する必要があります( 'FacesContext'から' ELContext'を得ることができます)。 – McDowell

答えて

0

あなたのバリデータにはバグがあり、以前の実装では幸運なことになったと思います。 documentationから

... Validatorクラスは、構成プロパティ値保存されたビューで復元を持っているしたい場合、実装はまた StateHolderを実装する必要があります。

POST操作中にビューが復元されると、長さ状態は存在しなくなる可能性があります。

私はバリにValueExpressionsで何が起こるか覚えていない - コンポーネントとは異なり、バリデータは、それらを保持するためにbinding mapsを持たない傾向があるあなた自身のValidatorHandlerか何かを作成する必要があります - 。私はこの部分を見ていませんAPIの詳細について説明します。

+0

私はStateHolderとPartialStateHolderを実装しようとしました。それは何の違いもないようです。私が見ているように、問題はJSPからFaceletsに切り替わり、コンポーネント、コンバーター、バリデーターをタグファイルがなくなるように変更していることです。以前は、ValueExpressionsを使用してコンポーネントを設定するタグファイルがありました。しかし、Faceletsでは、タグファイルはもうありません。代わりに、コンポーネント/コンバータ/バリデータは直接設定され、解決された式で設定されます。表現そのものではありません。これは、式を再解決できないことを意味します。 –

+0

私はあなたが示唆するように、ValidatorHandlerの使用を検討しようと考えています。私は結果を投稿する予定ですが、その間にさらに多くの提案ができます。 –

+0

@BjørnStenfeldt - あなたのソリューションを投稿していただきありがとうございます。私はまだクラス契約に従ってStateHolderを実装します。私はあなたの意見がセッションRAMに保持されていると推測しています。状態保存メカニズムを変更した場合、クラスが壊れる可能性があります。しかし、これはあなたにとって危険ではないかもしれません。 – McDowell

1

さて、すべてが今働いているようです。 McDowellが提案したように、私はカスタムValidatorHandlerを作成しました。ここに私の変更は以下のとおりです。

のtaglib:

<handler-class>test.CustomValidatorHandler</handler-class> 

VALIDATOR:

package test; 

import javax.el.ValueExpression; 
import javax.faces.application.FacesMessage; 
import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 
import javax.faces.validator.FacesValidator; 
import javax.faces.validator.Validator; 
import javax.faces.validator.ValidatorException; 

@FacesValidator("test.TestValidator") 
public class TestValidator implements Validator { 

    public TestValidator() { 
     super(); 
    } 

    @Override 
    public void validate(FacesContext context, 
      UIComponent component, Object value) throws ValidatorException { 

     String text = (String) value; 
     if (text == null || text.trim().length() == 0) { 
      return; 
     } 

     Integer length = getLengthValue(); 

     if (length != null && text != null && length.intValue() < text.length()) { 
      String message = "The text is too long. It was " + text.length() + 
        ", but only " + length + " characters are allowed."; 
      FacesMessage fm = new FacesMessage(
        FacesMessage.SEVERITY_ERROR, message, null); 
      throw new ValidatorException(fm); 
     } 
    } 

    private ValueExpression lengthExpression; 

    public ValueExpression getLength() { 
     return lengthExpression; 
    } 

    public void setLength(ValueExpression length) { 
     this.lengthExpression = length; 
    } 

    public Integer getLengthValue() { 
     Integer length = null; 
     if (lengthExpression != null) { 
      length = (Integer) lengthExpression.getValue(
        FacesContext.getCurrentInstance().getELContext()); 
     } 
     return length; 
    } 
} 

VALIDATORのHANDLER:

package test; 

import javax.el.ValueExpression; 
import javax.faces.context.FacesContext; 
import javax.faces.view.facelets.FaceletContext; 
import javax.faces.view.facelets.ValidatorConfig; 
import javax.faces.view.facelets.ValidatorHandler; 

public class CustomValidatorHandler extends ValidatorHandler { 

    private ValueExpression lengthExpression; 

    public CustomValidatorHandler(ValidatorConfig config) { 
     super(config); 
     FacesContext facesContext = FacesContext.getCurrentInstance(); 
     FaceletContext faceletContext = (FaceletContext) facesContext.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY); 
     lengthExpression = config.getTag().getAttributes().get("length").getValueExpression(faceletContext, Integer.class); 
    } 

    @Override 
    public void setAttributes(FaceletContext ctx, Object instance) { 
//  super.setAttributes(ctx, instance); 
     if (instance instanceof TestValidator) { 
      TestValidator validator = (TestValidator) instance; 
      validator.setLength(lengthExpression); 
     } 
    } 
} 
関連する問題