PAGE scoped Injection and outjection?
subaochen Jun 19, 2010 9:22 AMHi all,
I have a strange problem: can not inject two components simultaneously. I have tried many times with many kinds of methods to find out why, and searched google and even baidu, but can not work it out. So somebody can give me any hints? For simplicity, I have built a test project, you can just follow the steps below to reproduce my problem:
1 ./seam setup. use hsql,and create-drop database when deploy.
2 ./seam create-project
3 import the project into eclipse
3 I have create two entity bean and their corresponding Home and Entity Class with JBoss toos, the code is as below:
People.java:
@Entity
public class People implements Serializable
{
// seam-gen attributes (you should probably edit these)
private Long id;
private Integer version;
private String name;
// add additional entity attributes
// seam-gen attribute getters/setters with annotations (you probably should edit)
@Id @GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Version
public Integer getVersion() {
return version;
}
private void setVersion(Integer version) {
this.version = version;
}
@Length(max = 20)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People [id=" + id + ", name=" + name + "]";
}
}
Friend.java:
@Entity
public class Friend implements Serializable
{
// seam-gen attributes (you should probably edit these)
private Long id;
private Integer version;
private String name;
// add additional entity attributes
// seam-gen attribute getters/setters with annotations (you probably should edit)
@Id @GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Version
public Integer getVersion() {
return version;
}
private void setVersion(Integer version) {
this.version = version;
}
@Length(max = 20)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Friend [id=" + id + ", name=" + name + "]";
}
}
PeopleList.java:
@Name("peopleList")
public class PeopleList extends EntityQuery<People>
{
@Out(scope=ScopeType.PAGE)
private People selectedUser = new People();
private static final String EJBQL = "select people from People people";
private static final String[] RESTRICTIONS = {
"lower(people.name) like lower(concat(#{PeopleList.people.name},'%'))",};
private People people = new People();
public PeopleList() {
setEjbql(EJBQL);
setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));
setMaxResults(25);
}
public People getPeople() {
return people;
}
public void takeSelection(People selectedUser){
this.selectedUser=selectedUser;
}
}
PeopleHome.java:
@Name("peopleHome")
public class PeopleHome extends EntityHome<People>
{
@In(required = false, scope = ScopeType.PAGE)
private People selectedUser;
@In(required = false, scope = ScopeType.PAGE)
private List<Friend> selectedFriends;
@Logger
private Log log;
@Override @Begin
public void create() {
super.create();
}
public void savePeople(){
info("selected people =" + selectedUser);
info("selected friends=" + selectedFriends);
}
}
FriendList.java:
@Name("friendList")
public class FriendList extends EntityQuery<Friend>
{
private Map<Friend, Boolean> searchedFriends = new HashMap<Friend, Boolean>(0);
@Out(scope = ScopeType.PAGE)
private List<Friend> selectedFriends = new ArrayList<Friend>(0);
private static final String EJBQL = "select friend from Friend friend";
private static final String[] RESTRICTIONS = {
"lower(friend.name) like lower(concat(#{FriendList.friend.name},'%'))",};
private Friend friend = new Friend();
public FriendList() {
setEjbql(EJBQL);
setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));
setMaxResults(25);
}
public Friend getFriend() {
return friend;
}
@Override
public List<Friend> getResultList(){
List<Friend> friends = super.getResultList();
// initialize searchedFriends, set default to FALSE
if (searchedFriends == null)
searchedFriends = new HashMap<Friend, Boolean>(0);
for(Friend f:friends){
searchedFriends.put(f, Boolean.FALSE);
}
return friends;
}
public void selectFriends() {
for (Friend f : getSearchedFriends().keySet()) {
if (getSearchedFriends().get(f) == true){
selectedFriends.add(f);
}
}
}
public void setSearchedFriends(Map<Friend, Boolean> searchedFriends) {
this.searchedFriends = searchedFriends;
}
public Map<Friend, Boolean> getSearchedFriends() {
return searchedFriends;
}
}
FriendHome.java:
@Name("friendHome")
public class FriendHome extends EntityHome<Friend>
{
@RequestParameter Long friendId;
@Override
public Object getId()
{
if (friendId == null)
{
return super.getId();
}
else
{
return friendId;
}
}
@Override @Begin
public void create() {
super.create();
}
}
4 I have create 3 xhtml file as below:
home.xhtml:
<!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.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="layout/template.xhtml">
<ui:define name="body">
<h1>Welcome to Seam!</h1>
<rich:panel>
<h:form>
<h:inputText value="#{selectedUser.name}" id="userSelection"/>
<a:commandLink
value="click to select user"
oncomplete="#{rich:component('findPeople')}.show()"/>
<br/>
<a:commandLink
value="click to select friends"
oncomplete="#{rich:component('findFriend')}.show()"/>
<br/>
<a:outputPanel id="myFriends">
<rich:dataTable
var="_friend"
value="#{selectedFriends.toArray()}"
rendered="#{selectedFriends.size() > 0}">
<f:facet name="header">my friend list</f:facet>
<h:column width="200">
<f:facet name="header">name</f:facet>
<h:outputText value="#{_friend.name}"/>
</h:column>
</rich:dataTable>
</a:outputPanel>
<br/>
<h:commandButton value="Test Button,please check the console after click here" action="#{peopleHome.savePeople}"/>
</h:form>
</rich:panel>
<ui:include src="usersearchpanel.xhtml" >
<ui:param name="rerenderId" value="userSelection"/>
</ui:include>
<ui:include src="friendsearchpanel.xhtml" >
<ui:param name="rerenderId" value="friendSelection"/>
</ui:include>
</ui:define>
</ui:composition>
usersearchpanel.xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:s="http://jboss.com/products/seam/taglib">
<rich:modalPanel id="findPeople" minWidth="300" autosized="true" zindex="2000">
<f:facet name="header">Search People</f:facet>
<f:facet name="controls">
<h:panelGroup>
<h:outputText value="close" styleClass="hidelink" id="hideusersearchlink"/>
<rich:componentControl for="findPeople" attachTo="hideusersearchlink" operation="hide" event="onclick"/>
</h:panelGroup>
</f:facet>
<h:form>
<rich:dataTable
var="_user"
value="#{peopleList.resultList}"
rendered="#{peopleList.resultList.size() > 0}">
<h:column>
<f:facet name="header">name</f:facet>
<h:outputText value="#{_user.name}"/>
</h:column>
<rich:column styleClass="action">
<f:facet name="header">Action</f:facet>
<a:commandLink
value="choose"
reRender="userSelection"
action="#{peopleList.takeSelection(_user)}"
oncomplete="#{rich:component('findPeople')}.hide()"/>
</rich:column>
</rich:dataTable>
</h:form>
</rich:modalPanel>
</ui:composition>
friendsearchpanel.xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:s="http://jboss.com/products/seam/taglib">
<rich:modalPanel id="findFriend" minWidth="300" autosized="true" zindex="2000" >
<f:facet name="header">Search People</f:facet>
<f:facet name="controls">
<h:panelGroup>
<h:outputText value="close" styleClass="hidelink" id="hideFriendlink"/>
<rich:componentControl for="findFriend" attachTo="hideFriendlink" operation="hide" event="onclick"/>
</h:panelGroup>
</f:facet>
<h:form>
<rich:dataTable
var="_user"
value="#{friendList.resultList}"
rendered="#{friendList.resultList.size() > 0}">
<h:column>
<f:facet name="header">choose</f:facet>
<h:selectBooleanCheckbox value="#{searchedFriends[_user]}"/>
</h:column>
<h:column>
<f:facet name="header">name</f:facet>
<h:outputText value="#{_user.name}"/>
</h:column>
</rich:dataTable>
<div class="actionButtons">
<a:commandButton
value="submit"
action="#{friendList.selectFriends}"
reRender="myFriends"
oncomplete="#{rich:component('findFriend')}.hide()"/>
</div>
</h:form>
</rich:modalPanel>
</ui:composition>
5 the import-dev file:
insert into people(name) values('tom');
insert into people(name) values('sam');
insert into friend(name) values('susan');
insert into friend(name) values('jude');
That's all! you can copy above files to the correspoding directories to deploy the test project.
The question is: in the home.xhtml, I first select one person from usersearchpanel.xhtml, and then get two friends from friendsearchpanel.xhtml, but when click the test button which binding to PeopleHome.savePeople method, I get the following output from the console:
INFO [PeopleHome] selected people =People [id=null, name=tom]
INFO [PeopleHome] selected friends=[Friend [id=1, name=susan], Friend [id=2, name=jude]]
That meams, the selected person is lost, and only selected friends are avaliable from savePeople method. So, why selectedUser (outjected in PeopleList.java and injected in PersonHome.java) is lost?
More strangely, if I only select one person(don't click "select friends"), then selectedUser is available from PeopleHome.savePeople method. That is , I can not get selectedUser and selectedFriends both available from PeopleHome.savePeople method.
Anybody would like to help me? Thanks in advance!
Su Baochen
I have a strange problem: can not inject two components simultaneously. I have tried many times with many kinds of methods to find out why, and searched google and even baidu, but can not work it out. So somebody can give me any hints? For simplicity, I have built a test project, you can just follow the steps below to reproduce my problem:
1 ./seam setup. use hsql,and create-drop database when deploy.
2 ./seam create-project
3 import the project into eclipse
3 I have create two entity bean and their corresponding Home and Entity Class with JBoss toos, the code is as below:
People.java:
@Entity
public class People implements Serializable
{
// seam-gen attributes (you should probably edit these)
private Long id;
private Integer version;
private String name;
// add additional entity attributes
// seam-gen attribute getters/setters with annotations (you probably should edit)
@Id @GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Version
public Integer getVersion() {
return version;
}
private void setVersion(Integer version) {
this.version = version;
}
@Length(max = 20)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People [id=" + id + ", name=" + name + "]";
}
}
Friend.java:
@Entity
public class Friend implements Serializable
{
// seam-gen attributes (you should probably edit these)
private Long id;
private Integer version;
private String name;
// add additional entity attributes
// seam-gen attribute getters/setters with annotations (you probably should edit)
@Id @GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Version
public Integer getVersion() {
return version;
}
private void setVersion(Integer version) {
this.version = version;
}
@Length(max = 20)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Friend [id=" + id + ", name=" + name + "]";
}
}
PeopleList.java:
@Name("peopleList")
public class PeopleList extends EntityQuery<People>
{
@Out(scope=ScopeType.PAGE)
private People selectedUser = new People();
private static final String EJBQL = "select people from People people";
private static final String[] RESTRICTIONS = {
"lower(people.name) like lower(concat(#{PeopleList.people.name},'%'))",};
private People people = new People();
public PeopleList() {
setEjbql(EJBQL);
setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));
setMaxResults(25);
}
public People getPeople() {
return people;
}
public void takeSelection(People selectedUser){
this.selectedUser=selectedUser;
}
}
PeopleHome.java:
@Name("peopleHome")
public class PeopleHome extends EntityHome<People>
{
@In(required = false, scope = ScopeType.PAGE)
private People selectedUser;
@In(required = false, scope = ScopeType.PAGE)
private List<Friend> selectedFriends;
@Logger
private Log log;
@Override @Begin
public void create() {
super.create();
}
public void savePeople(){
info("selected people =" + selectedUser);
info("selected friends=" + selectedFriends);
}
}
FriendList.java:
@Name("friendList")
public class FriendList extends EntityQuery<Friend>
{
private Map<Friend, Boolean> searchedFriends = new HashMap<Friend, Boolean>(0);
@Out(scope = ScopeType.PAGE)
private List<Friend> selectedFriends = new ArrayList<Friend>(0);
private static final String EJBQL = "select friend from Friend friend";
private static final String[] RESTRICTIONS = {
"lower(friend.name) like lower(concat(#{FriendList.friend.name},'%'))",};
private Friend friend = new Friend();
public FriendList() {
setEjbql(EJBQL);
setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));
setMaxResults(25);
}
public Friend getFriend() {
return friend;
}
@Override
public List<Friend> getResultList(){
List<Friend> friends = super.getResultList();
// initialize searchedFriends, set default to FALSE
if (searchedFriends == null)
searchedFriends = new HashMap<Friend, Boolean>(0);
for(Friend f:friends){
searchedFriends.put(f, Boolean.FALSE);
}
return friends;
}
public void selectFriends() {
for (Friend f : getSearchedFriends().keySet()) {
if (getSearchedFriends().get(f) == true){
selectedFriends.add(f);
}
}
}
public void setSearchedFriends(Map<Friend, Boolean> searchedFriends) {
this.searchedFriends = searchedFriends;
}
public Map<Friend, Boolean> getSearchedFriends() {
return searchedFriends;
}
}
FriendHome.java:
@Name("friendHome")
public class FriendHome extends EntityHome<Friend>
{
@RequestParameter Long friendId;
@Override
public Object getId()
{
if (friendId == null)
{
return super.getId();
}
else
{
return friendId;
}
}
@Override @Begin
public void create() {
super.create();
}
}
4 I have create 3 xhtml file as below:
home.xhtml:
<!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.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="layout/template.xhtml">
<ui:define name="body">
<h1>Welcome to Seam!</h1>
<rich:panel>
<h:form>
<h:inputText value="#{selectedUser.name}" id="userSelection"/>
<a:commandLink
value="click to select user"
oncomplete="#{rich:component('findPeople')}.show()"/>
<br/>
<a:commandLink
value="click to select friends"
oncomplete="#{rich:component('findFriend')}.show()"/>
<br/>
<a:outputPanel id="myFriends">
<rich:dataTable
var="_friend"
value="#{selectedFriends.toArray()}"
rendered="#{selectedFriends.size() > 0}">
<f:facet name="header">my friend list</f:facet>
<h:column width="200">
<f:facet name="header">name</f:facet>
<h:outputText value="#{_friend.name}"/>
</h:column>
</rich:dataTable>
</a:outputPanel>
<br/>
<h:commandButton value="Test Button,please check the console after click here" action="#{peopleHome.savePeople}"/>
</h:form>
</rich:panel>
<ui:include src="usersearchpanel.xhtml" >
<ui:param name="rerenderId" value="userSelection"/>
</ui:include>
<ui:include src="friendsearchpanel.xhtml" >
<ui:param name="rerenderId" value="friendSelection"/>
</ui:include>
</ui:define>
</ui:composition>
usersearchpanel.xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:s="http://jboss.com/products/seam/taglib">
<rich:modalPanel id="findPeople" minWidth="300" autosized="true" zindex="2000">
<f:facet name="header">Search People</f:facet>
<f:facet name="controls">
<h:panelGroup>
<h:outputText value="close" styleClass="hidelink" id="hideusersearchlink"/>
<rich:componentControl for="findPeople" attachTo="hideusersearchlink" operation="hide" event="onclick"/>
</h:panelGroup>
</f:facet>
<h:form>
<rich:dataTable
var="_user"
value="#{peopleList.resultList}"
rendered="#{peopleList.resultList.size() > 0}">
<h:column>
<f:facet name="header">name</f:facet>
<h:outputText value="#{_user.name}"/>
</h:column>
<rich:column styleClass="action">
<f:facet name="header">Action</f:facet>
<a:commandLink
value="choose"
reRender="userSelection"
action="#{peopleList.takeSelection(_user)}"
oncomplete="#{rich:component('findPeople')}.hide()"/>
</rich:column>
</rich:dataTable>
</h:form>
</rich:modalPanel>
</ui:composition>
friendsearchpanel.xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:s="http://jboss.com/products/seam/taglib">
<rich:modalPanel id="findFriend" minWidth="300" autosized="true" zindex="2000" >
<f:facet name="header">Search People</f:facet>
<f:facet name="controls">
<h:panelGroup>
<h:outputText value="close" styleClass="hidelink" id="hideFriendlink"/>
<rich:componentControl for="findFriend" attachTo="hideFriendlink" operation="hide" event="onclick"/>
</h:panelGroup>
</f:facet>
<h:form>
<rich:dataTable
var="_user"
value="#{friendList.resultList}"
rendered="#{friendList.resultList.size() > 0}">
<h:column>
<f:facet name="header">choose</f:facet>
<h:selectBooleanCheckbox value="#{searchedFriends[_user]}"/>
</h:column>
<h:column>
<f:facet name="header">name</f:facet>
<h:outputText value="#{_user.name}"/>
</h:column>
</rich:dataTable>
<div class="actionButtons">
<a:commandButton
value="submit"
action="#{friendList.selectFriends}"
reRender="myFriends"
oncomplete="#{rich:component('findFriend')}.hide()"/>
</div>
</h:form>
</rich:modalPanel>
</ui:composition>
5 the import-dev file:
insert into people(name) values('tom');
insert into people(name) values('sam');
insert into friend(name) values('susan');
insert into friend(name) values('jude');
That's all! you can copy above files to the correspoding directories to deploy the test project.
The question is: in the home.xhtml, I first select one person from usersearchpanel.xhtml, and then get two friends from friendsearchpanel.xhtml, but when click the test button which binding to PeopleHome.savePeople method, I get the following output from the console:
INFO [PeopleHome] selected people =People [id=null, name=tom]
INFO [PeopleHome] selected friends=[Friend [id=1, name=susan], Friend [id=2, name=jude]]
That meams, the selected person is lost, and only selected friends are avaliable from savePeople method. So, why selectedUser (outjected in PeopleList.java and injected in PersonHome.java) is lost?
More strangely, if I only select one person(don't click "select friends"), then selectedUser is available from PeopleHome.savePeople method. That is , I can not get selectedUser and selectedFriends both available from PeopleHome.savePeople method.
Anybody would like to help me? Thanks in advance!
Su Baochen