Вам действительно нужен класс 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>