0

私のアプリケーションでは、都市 (A) と郵便番号 (B) の間に関係があります。

だから私は2つの SelectOneMenu を持っています.1つ目はAを表し、2つ目は選択されたAのBを表し、これらはajax経由で更新されます。

私はこれらの 2 つのメニューを複数回使用しているため、セッション Bean の既存の変数に A 値と B 値が割り当てられている限り、通常は正常に機能するカスタム タグを作成しました。

しかし、タグ コンポーネントを使用して動作していない Bean に新しい関係オブジェクトを渡したい場合があります。

ロジック セッション Bean の add メソッドに引数として渡したい新しいリクエスト スコープの AToB オブジェクトのプロパティ A と B が null です。

*追記事項

  1. 既存のセッション Bean 変数でタグ コンポーネントを使用すると機能します。
  2. タグ コンポーネントを使用して新しいリクエスト Bean ベースの関係オブジェクトを追加しても機能しません。
  3. 選択された A は常に (ケース 1 と 2 の場合) ajax 変更イベントを使用して正しく Bean に渡されます。
  4. SelectOneMenu のコンバーターは常に機能します。(デバッグモードでテスト済み)
  5. タグ コンポーネントを使用すると、JSF はセッターを呼び出して新しい AToB オブジェクトの A と B を設定し、デバッグ モードでテストされることはありません。
  6. primefaces の代わりに jsf default h:commandButton を使用すると、同じエラーが発生します。
  7. タグ コンポーネントを使用しなくても完全に機能します。

環境:

モハラ 2.14 グラスフィッシュ
3.01

コンストラクターとゲッターとセッターを削除してクラスを簡素化しました。

DTO、ポジョ:

public Class A{}

public Class B{}

public Class AToB
{
    private A a;
    private B b;
}

セッション Bean:

public Class Bean
{
    private List<A> as;
    private List<B> bs;

    private AConverter aConverter;
    private BConverter bConverter;

    //updates bs list
    public void updateBsByA(AjaxBehaviorEvent event) {}

    //does something with the given AToB
    public void add(AToB aToB)
}

顔-config.xml:

<managed-bean>
    <managed-bean-name>beanLogic</managed-bean-name>
    <managed-bean-class>package.Bean</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
    <description>new AToB Object I want to add at database</description>
    <managed-bean-name>newAToB</managed-bean-name>
    <managed-bean-class>package.Bean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

abSelect タグ ファイル:

<ui:composition
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui"
    xmlns:abcd="http://store24.de/jsf/admin">
    <h:selectOneMenu value="#{tagA}" converter="#{beanLogic.aConverter}">
        <f:selectItems value="#{beanLogic.as}"/>
        <p:ajax event="change" listener="#{beanLogic.updateBsByA}" update="selectB"/>
    </h:selectOneMenu>
        <h:selectOneMenu id="selectB" value="#{tagB}" converter="#{beanLogic.bConverter}">
        <f:selectItems value="#{beanLogic.bs}"/>
    </h:selectOneMenu>
</ui:composition>

abcd.taglib.xml

<?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://abcd.com/jsf</namespace>
    <tag>
        <tag-name>abSelect</tag-name>
        <source>tags/abSelect.xhtml</source>
        <attribute>
            <display-name>a</display-name>
            <name>tagA</name>
            <required>true</required>
            <type>package.A</type>
        </attribute>
        <attribute>
            <display-name>a</display-name>
            <name>tagB</name>
            <required>true</required>
            <type>package.B</type>
        </attribute>
    </tag>
</facelet-taglib>

呼び出しサイト:

<abcd:abSelect a="#{newAToB.a} b="#{newAToB.b}"/>
<p:commandButton value="add" action="#{beanLogic.add(newAToB)}"/>

代わりに、タグ コンポーネントなしで新しい AToB を追加すると機能します (上記 #2 を参照)。

<h:selectOneMenu value="#{newAToB.a}" converter="#{beanLogic.aConverter}">
    <f:selectItems value="#{beanLogic.as}"/>
    <p:ajax event="change" listener="#{beanLogic.updateBsByA}" update="selectB"/>
</h:selectOneMenu>
    <h:selectOneMenu id="selectB" value="#{newAToB.b}" converter="#{beanLogic.bConverter}">
    <f:selectItems value="#{beanLogic.bs}"/>
</h:selectOneMenu>
<p:commandButton value="add" action="#{beanLogic.add(newAToB)}"/>
4

1 に答える 1

0

本当にAToBクラスが必要ですか? できませんprivate Aprivate B b;セッションスコープのBeanになりますか?コードを再作成する際に私が見つけた主な問題は、スクープされた AToB の要求が、使用するたびに再System.out.println()作成されることです。コンストラクターに追加するだけで確認できます。なぜそれが起こっているのかわかりません。しかし、私は JSF 依存性注入を使用して、おそらく必要なことを行います (AToB をセッション Bean に注入します)。

おそらくコンバーターがありません(コンバーターなしでは機能しません)-に変更p:commandButtonh:commandButtonて、私の意味を確認してください。Primefaces のボタンがエラーをスローしない理由はわかりませんが、これは以前に見たことがあります。

string を使用して selectMany で A と B を提示し、処理の直前にデコードして再作成すると簡単です。

それが私にとってうまくいくものです:

web.xml

  ...
  <!-- registering my custom tag -->
    <context-param>
        <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
        <param-value>/WEB-INF/mytags.taglib.xml</param-value>
    </context-param>

mytags.taglim.xml

<?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://mytags.com/jsf</namespace>
    <tag>
        <tag-name>abSelect</tag-name>
        <source>tags/mytags/abselect.xhtml</source>
        <attribute>
            <display-name>a</display-name>
            <name>tagA</name>
            <required>true</required>
            <type>mytagstest.A</type>
        </attribute>
        <attribute>
            <display-name>a</display-name>
            <name>tagB</name>
            <required>true</required>
            <type>mytagstest.B</type>
        </attribute>
    </tag>
</facelet-taglib>

顔-confix.xml

...
<!-- Converters -->
<converter>
    <converter-id>aConverter</converter-id>
    <converter-class>mytagstest.AConverter</converter-class>
</converter>
<converter>
    <converter-id>bConverter</converter-id>
    <converter-class>mytagstest.BConverter</converter-class>
</converter>

abselect.xml

<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
>
<h:selectOneMenu value="#{tagA}">  <!--  {aBBean.a} or {tagA} -->
    <f:converter converterId="aConverter" />
    <f:selectItems value="#{aBBean.as}"/> 
    <!--I dont know why you are tyring to update sth in  aBBean, new value from menu is used to update tagA -->
    <f:ajax event="change" listener="#{aBBean.updateBsByA}" execute="@form"/>
</h:selectOneMenu>
<h:selectOneMenu id="selectB" value="#{tagB}"> <!--  {aBBean.b} or {tagB} -->
    <f:converter converterId="bConverter" />
    <f:selectItems value="#{aBBean.bs}"/>
    <f:ajax event="change" listener="#{aBBean.updateBsByA}" execute="@form"/>
</h:selectOneMenu>

A: #{aBBean.a} B: #{aBBean.b}

AToB が本当に必要ない場合は、タグ内の属性をスキップして、ユーザーの選択をセッション Bean に保存できることに注意してください。これはおそらくはるかにきれいでしょう。

A.java (equals と hashCode メソッドに注意)

package mytagstest;

import java.io.Serializable;

public class A  implements Serializable{

    private String name ="";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }



    public A() {
    }


    A(String n) {
      this.name = n;
    }

    @Override
    public String toString() {
        return "A{" + "name=" + name + '}';
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final A other = (A) obj;
        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 19 * hash + (this.name != null ? this.name.hashCode() : 0);
        return hash;
    }



}

このクラスのコンバーター (p:commandButton を h:commandButton に置き換えると、コンバーターの作成時にエラーが発生することがわかります)。

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;


public class AConverter implements Converter {



    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        // Convert the unique String representation of an object to the actual object.
        return new A(value); //Dont need to create new
    }

    public String getAsString(FacesContext context, UIComponent component, Object value) {
        // Convert the Foo object to its unique String representation.
        return ((A) value).getName();
    }

}

クラスBとBConverter見た目はほぼ同じ。

AToB.java

@ManagedBean
@RequestScoped
public class AToB implements Serializable {

    private A a;
    private B b;

    public AToB() {
        System.out.println("Creating AToB");
    }

    public A getA() {
        System.out.println("Get a");
        return a;
    }

    public void setA(A a) {
        System.out.println("set b");
        this.a = a;
    }

    public B getB() {
        System.out.println("get b");
        return b;
    }

    public void setB(B b) {
        System.out.println("set b");
        this.b = b;
    }
}

ABBEan (セッション スコープ Bean、両方のケースのメソッドがあります - AToB を使用する場合と使用しない場合)

   @ManagedBean
    @SessionScoped
    public class ABBean implements Serializable {

        private List<A> as = new ArrayList<A>();
        private List<B> bs = new ArrayList<B>();
        private A a;
        private B b;

        public A getA() {
            System.out.println("Get a");
            return a;
        }

        public void setA(A a) {
            System.out.println("set b");
            this.a = a;
        }

        public B getB() {
            System.out.println("get b");
            return b;
        }

        public void setB(B b) {
            System.out.println("set b");
            this.b = b;
        }

        public void updateAB() {
            System.out.println("Selected A and B are:");
            System.out.println(a + " " + b);
        }

        public ABBean() {
            System.out.println("Creating ABBean");
            A a1 = new A("a1");
            B b1 = new B("b1");
            this.a = a1;
            this.b = b1;

            as.add(a1);
            as.add(new A("a2"));
            bs.add(b1);
            bs.add(new B("b2"));
        }

        //updates bs list
        public void updateBsByA(AjaxBehaviorEvent event) {
            System.out.println("updateBsByA");
            System.out.println("Selected A and B are:");
            System.out.println(a + " " + b);
        }

        public List<A> getAs() {
            return as;
        }

        public void setAs(List<A> as) {
            this.as = as;
        }

        public List<B> getBs() {
            return bs;
        }

        public void setBs(List<B> bs) {
            this.bs = bs;
        }

        //does something with the given AToB
        public void add(AToB aToB) {
            System.out.println("AToB added! - aToB");
            System.out.println(aToB.getA() + " " + aToB.getB());

        }

        public void add(A a, B b) {
            System.out.println("AToB added! - A a, B b");
            System.out.println(a + " " + b);

        }
    }

利用方法:

<h:form>  
  <mt:abSelect  tagA="#{aBBean.a}" tagB="#{aBBean.b}"/>
  <p:commandButton   value="add2works" action="#{aBBean.updateAB}"/> <!-- works -->
</h:form>

また

  <h:form>  
  <mt:abSelect  tagA="#{aToB.a}" tagB="#{aToB.b}"/>
    <p:commandButton  value="add7" action="#{aBBean.add(aToB)}"/>
 </h:form>
于 2012-03-10T18:19:16.117 に答える