jsf передает новый объект bean отношения запроса в сессионный компонент, не работающий с использованием пользовательского тега - PullRequest
0 голосов
/ 03 марта 2012

В моем приложении у меня есть связь между городами (A) и почтовыми индексами (B).

Итак, у меня есть два SelectOneMenu, где первый представляет A, а второй представляет B выбранных A, которые обновляются.via ajax.

Поскольку я использую эти два меню несколько раз, я написал для них пользовательский тег, который обычно отлично работает, пока значения A и B назначаются существующим переменным в моем сессионном компоненте.

Но есть случай, когда я хочу передать новый объект отношения моему бину, который не работает с использованием компонента тега.

Свойства A и B объекта AToB в области нового запроса, которые я хочу передать в качестве аргумента методу add моего логического сеанса, являются нулевыми!

* Дополнительные примечания

  1. Использование компонента тега с существующими переменными сессионного компонента работает.
  2. Использование компонента тега для добавления нового объекта отношения на основе бина запроса не работает.
  3. Выбранный A всегда (в случаях 1 и 2) правильно передается компоненту с помощью события изменения ajax.
  4. Преобразователи для SelectOneMenu всегда работают.(Проверено в режиме отладки)
  5. Использование компонента тега JSF никогда не вызывает установщиков для установки A и B нового объекта AToB, протестированного в режиме отладки.
  6. Использованиеjsf по умолчанию h: commandButton вместо простых символов выдает ту же ошибку.
  7. Отлично работает без использования компонента тега!

Среда:

Мохарра 2.14
GlassFish 3.01

Я упростил классы, удаляя конструкторы и методы получения и установки.

DTO, Pojo:

public Class A{}

public Class B{}

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

Сессионный компонент:

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)
}

face-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)}"/>

1 Ответ

0 голосов
/ 10 марта 2012

Вам действительно нужен класс AToB?Не могу private A а;и private B b; быть в сессионном компоненте?Основная проблема, которую я обнаружил при воссоздании вашего кода, заключается в том, что запрос, закачиваемый AToB, воссоздает каждый раз, когда я хотел его использовать - просто добавьте System.out.println() в его конструктор, чтобы увидеть его.Я не знаю, почему это происходит.Но я бы использовал внедрение зависимостей JSF, чтобы делать то, что вы, вероятно, хотите (вставить AToB в сессионный компонент).

Возможно, вам не хватает конвертеров (не работающих без них) - измените p:commandButton на h:commandButton, чтобы увидетьчто я имею в виду.Я не знаю, почему кнопки Primefaces не выдают никаких ошибок, но я видел это раньше.

Было бы проще, если бы вы использовали строку для представления A и B в selectMany, а затем декодировали и воссоздали ееобработка.

Вот что у меня работает:

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>

Face-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, вы можете просто пропустить атрибуты в вашем теге и сохранить свой выбор пользователя в своем сессионном компоненте.Это было бы, вероятно, намного чище.

A.java (уведомление равно и метод 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-объект Sessioned 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>
...