Persistent Collection malfunction

P

pek

OK, here is what I have:
Class Game with :
@OneToMany
List getTeams()
@OneToOne
CardStack centerStack()

Class Team
@OneToMany
List getPlayers()

Class Player
@OneToOne
CardStack getHandStack()

Class CardStack
@OneToMany
List getCards()

Every list is an ArrayList. The problem is that I has a Stateful Bean
GameManager that has a persisted game reference.
When all players tell to the game that they are ready to play through
the setPlayerReady(boolean state) of GameManager, then the method
startGame() automatically is called. startGame() adds 108 cards in the
centerStack and then from centerStack it gives each player 11 cards by
removing them from the centerStack (I do more things with it thats why
I don't give them right away to players hand). This is done by using
this method:
for (Team aTeam:game.getTeams()) {
for (Player aPlayer:aTeam.getPlayers()) {

aPlayer.getHandStack().getCards().add(game.getCenterStack().getCards().remove(0));
}
}

This correctly adds 11 cards to player's hand. But the funny part is
that it also adds 11 identical references of the player in the team!
After doing this, I refresh the game through EntityManager manager;
manager.refresh(game) and call
game.getTeams().get(0).getPlayers().size() = 11. All players are the
same one. The database has everything correct, 1 player for each team
and 11 cards for each player. I don't get it..I tried doing every
thing.. Flushing before adding cards, flushing before removing,
refreshing, merging..Everything.. And the wierd part is that every
change makes other malfunctions. Some times I get a duplicate key
violation when I try to remove one card from center stack and add it
to players hand all at once (like above) and to avoid this I have to
do:
Card aCard = game.getCenterStack().getCards().remove(0);
manager.flush();
aPlayer.getHandStack().getCards().add(aCard);
and that works but has other problems... I can't find any good source
for working with collections..

Any help..?
Thanks in advance.
 
J

Joshua Cranmer

pek said:
OK, here is what I have:
Class Game with :
@OneToMany
List getTeams()
@OneToOne
CardStack centerStack()

Class Team
@OneToMany
List getPlayers()

Class Player
@OneToOne
CardStack getHandStack()

Class CardStack
@OneToMany
List getCards()

Every list is an ArrayList. The problem is that I has a Stateful Bean
GameManager that has a persisted game reference.
When all players tell to the game that they are ready to play through
the setPlayerReady(boolean state) of GameManager, then the method
startGame() automatically is called. startGame() adds 108 cards in the
centerStack and then from centerStack it gives each player 11 cards by
removing them from the centerStack (I do more things with it thats why
I don't give them right away to players hand). This is done by using
this method:
for (Team aTeam:game.getTeams()) {
for (Player aPlayer:aTeam.getPlayers()) {

aPlayer.getHandStack().getCards().add(game.getCenterStack().getCards().remove(0));
}
}

This correctly adds 11 cards to player's hand. But the funny part is
that it also adds 11 identical references of the player in the team!
After doing this, I refresh the game through EntityManager manager;
manager.refresh(game) and call
game.getTeams().get(0).getPlayers().size() = 11. All players are the
same one. The database has everything correct, 1 player for each team
and 11 cards for each player. I don't get it..I tried doing every
thing.. Flushing before adding cards, flushing before removing,
refreshing, merging..Everything.. And the wierd part is that every
change makes other malfunctions. Some times I get a duplicate key
violation when I try to remove one card from center stack and add it
to players hand all at once (like above) and to avoid this I have to
do:
Card aCard = game.getCenterStack().getCards().remove(0);
manager.flush();
aPlayer.getHandStack().getCards().add(aCard);
and that works but has other problems... I can't find any good source
for working with collections..

Any help..?
Thanks in advance.

First off, just a little comment to make about your design: I think it
would be better to have addTop(), addBottom(), removeTop(),
removeBottom() for your CardStack class to clean a little code up.

Design decisions aside, are you using multiple threads? If so, then you
might be having race conditions -- the key violations would seem to
imply that.

Could you also elaborate more on the extra players, i.e., does
game.getTeams().get(0).getPlayers().get(0) ==
game.getTeams().get(0).getPlayers().get(1) ?
 
P

pek

First thanks for the quick reply. I really need it..
First off, just a little comment to make about your design: I think it
would be better to have addTop(), addBottom(), removeTop(),
removeBottom() for your CardStack class to clean a little code up.
Currently I thought of removing completely the CardStack since it only
has a set of cards in an ArrayList<Card>. But I found this useful in
other situations (where a ArrayList<CardStack> is needed, I found it
really hard to map ArrayList<ArrayList<Card>> in the database :S) so I
am not sure if removing it is a good idea after all. Interesting
thought with these methods though, but since it only beautifies my
code I'd like to firstly find out what is the problem and then little
by little make changes trying not to affect (disastrously) the code
(XP programming style).
Design decisions aside, are you using multiple threads? If so, then you
might be having race conditions -- the key violations would seem to
imply that.
The GameManager is a stateful bean. Every member of the network must
create remotely this bean and create or join an existing game. From
there he uses the bean for game interactions. I had to persist all the
data for sharing it. I don't create any threads in the bean, but I
assume that every bean is a thread by itself. I am not sure if this is
a problem.
Could you also elaborate more on the extra players, i.e., does
game.getTeams().get(0).getPlayers().get(0) ==
game.getTeams().get(0).getPlayers().get(1) ?
Well, I am using List which allows duplicates, but no. There isn't
anywhere in my code that adds the same player. A member of the game
must create a GameManager remotely, create a game or join an existing
with a token he got when he logged in (String
DomainManager.login(String username,String password)). This token (64
random characters) is used to locate the members data in the database
(for security reasons I don't want to send any member data to the
client,or any reference to any server-side object at all) and then
create a Player object with the member's data that was found, in
Players class constructor [Player(Member aMember)]. After that, the
player is added properly to the teams player list. I thought of using
a collection that doesn't allow duplicates but I couldn't find one
that is also indexed. A player can add himself in any team using the
teams index and any where in the teams player list using seatIndex
(game.getTeams().get(teamIndex).getPlayers().add(seatIndex,Player)).

I hope this is enough. Thank you again. I am really waiting for your
reply.
 
J

Joshua Cranmer

pek said:
First thanks for the quick reply. I really need it..

Currently I thought of removing completely the CardStack since it only
has a set of cards in an ArrayList<Card>. But I found this useful in
other situations (where a ArrayList<CardStack> is needed, I found it
really hard to map ArrayList<ArrayList<Card>> in the database :S) so I
am not sure if removing it is a good idea after all. Interesting
thought with these methods though, but since it only beautifies my
code I'd like to firstly find out what is the problem and then little
by little make changes trying not to affect (disastrously) the code
(XP programming style).
The GameManager is a stateful bean. Every member of the network must
create remotely this bean and create or join an existing game. From
there he uses the bean for game interactions. I had to persist all the
data for sharing it. I don't create any threads in the bean, but I
assume that every bean is a thread by itself. I am not sure if this is
a problem.

I don't know much about beans, so I don't know if it creates threads.
The easiest way to find out is to use the command
System.err.println(Thread.getAllStackTraces());
Could you also elaborate more on the extra players, i.e., does
game.getTeams().get(0).getPlayers().get(0) ==
game.getTeams().get(0).getPlayers().get(1) ?
Well, I am using List which allows duplicates, but no. There isn't
anywhere in my code that adds the same player. A member of the game
must create a GameManager remotely, create a game or join an existing
with a token he got when he logged in (String
DomainManager.login(String username,String password)). This token (64
random characters) is used to locate the members data in the database
(for security reasons I don't want to send any member data to the
client,or any reference to any server-side object at all) and then
create a Player object with the member's data that was found, in
Players class constructor [Player(Member aMember)]. After that, the
player is added properly to the teams player list. I thought of using
a collection that doesn't allow duplicates but I couldn't find one
that is also indexed. A player can add himself in any team using the
teams index and any where in the teams player list using seatIndex
(game.getTeams().get(teamIndex).getPlayers().add(seatIndex,Player)).

What your wording seems to imply is that the program is somehow
deep-copying all of the players, but I doubt this is the case.
Seeing as I have no idea how the for loops could mangle the players so,
I would think that including all of the code of startGame() would be
helpful. Tracking done segfaults in C has taught me that the incorrect
code need not be the instruction that actually fails.

Actually, on second thought, the code of Card and GameManager would be
really helpful right about now (especially if it's Card that's causing
duplicate key information).
 
P

pek

pek said:
First thanks for the quick reply. I really need it..
Currently I thought of removing completely the CardStack since it only
has a set of cards in an ArrayList<Card>. But I found this useful in
other situations (where a ArrayList<CardStack> is needed, I found it
really hard to map ArrayList<ArrayList<Card>> in the database :S) so I
am not sure if removing it is a good idea after all. Interesting
thought with these methods though, but since it only beautifies my
code I'd like to firstly find out what is the problem and then little
by little make changes trying not to affect (disastrously) the code
(XP programming style).
The GameManager is a stateful bean. Every member of the network must
create remotely this bean and create or join an existing game. From
there he uses the bean for game interactions. I had to persist all the
data for sharing it. I don't create any threads in the bean, but I
assume that every bean is a thread by itself. I am not sure if this is
a problem.

I don't know much about beans, so I don't know if it creates threads.
The easiest way to find out is to use the command
System.err.println(Thread.getAllStackTraces());


Could you also elaborate more on the extra players, i.e., does
game.getTeams().get(0).getPlayers().get(0) ==
game.getTeams().get(0).getPlayers().get(1) ?
Well, I am using List which allows duplicates, but no. There isn't
anywhere in my code that adds the same player. A member of the game
must create a GameManager remotely, create a game or join an existing
with a token he got when he logged in (String
DomainManager.login(String username,String password)). This token (64
random characters) is used to locate the members data in the database
(for security reasons I don't want to send any member data to the
client,or any reference to any server-side object at all) and then
create a Player object with the member's data that was found, in
Players class constructor [Player(Member aMember)]. After that, the
player is added properly to the teams player list. I thought of using
a collection that doesn't allow duplicates but I couldn't find one
that is also indexed. A player can add himself in any team using the
teams index and any where in the teams player list using seatIndex
(game.getTeams().get(teamIndex).getPlayers().add(seatIndex,Player)).

What your wording seems to imply is that the program is somehow
deep-copying all of the players, but I doubt this is the case.
Seeing as I have no idea how the for loops could mangle the players so,
I would think that including all of the code of startGame() would be
helpful. Tracking done segfaults in C has taught me that the incorrect
code need not be the instruction that actually fails.

Actually, on second thought, the code of Card and GameManager would be
really helpful right about now (especially if it's Card that's causing
duplicate key information).

OK, I have uploaded the parts that are needed over here:
http://pek.ekei.com/misc/help/cards/source.html
GameManager : The Stateful Bean
Card : The Card class
Game : A Data Type class that holds all information of a game.
Client : An example of how things work

Each file has some documentation in it.
 
J

Joshua Cranmer

pek said:
pek said:
First thanks for the quick reply. I really need it..
First off, just a little comment to make about your design: I think it
would be better to have addTop(), addBottom(), removeTop(),
removeBottom() for your CardStack class to clean a little code up.
Currently I thought of removing completely the CardStack since it only
has a set of cards in an ArrayList<Card>. But I found this useful in
other situations (where a ArrayList<CardStack> is needed, I found it
really hard to map ArrayList<ArrayList<Card>> in the database :S) so I
am not sure if removing it is a good idea after all. Interesting
thought with these methods though, but since it only beautifies my
code I'd like to firstly find out what is the problem and then little
by little make changes trying not to affect (disastrously) the code
(XP programming style).
Design decisions aside, are you using multiple threads? If so, then you
might be having race conditions -- the key violations would seem to
imply that.
The GameManager is a stateful bean. Every member of the network must
create remotely this bean and create or join an existing game. From
there he uses the bean for game interactions. I had to persist all the
data for sharing it. I don't create any threads in the bean, but I
assume that every bean is a thread by itself. I am not sure if this is
a problem.
I don't know much about beans, so I don't know if it creates threads.
The easiest way to find out is to use the command
System.err.println(Thread.getAllStackTraces());


Could you also elaborate more on the extra players, i.e., does
game.getTeams().get(0).getPlayers().get(0) ==
game.getTeams().get(0).getPlayers().get(1) ?
Well, I am using List which allows duplicates, but no. There isn't
anywhere in my code that adds the same player. A member of the game
must create a GameManager remotely, create a game or join an existing
with a token he got when he logged in (String
DomainManager.login(String username,String password)). This token (64
random characters) is used to locate the members data in the database
(for security reasons I don't want to send any member data to the
client,or any reference to any server-side object at all) and then
create a Player object with the member's data that was found, in
Players class constructor [Player(Member aMember)]. After that, the
player is added properly to the teams player list. I thought of using
a collection that doesn't allow duplicates but I couldn't find one
that is also indexed. A player can add himself in any team using the
teams index and any where in the teams player list using seatIndex
(game.getTeams().get(teamIndex).getPlayers().add(seatIndex,Player)).
What your wording seems to imply is that the program is somehow
deep-copying all of the players, but I doubt this is the case.
Seeing as I have no idea how the for loops could mangle the players so,
I would think that including all of the code of startGame() would be
helpful. Tracking done segfaults in C has taught me that the incorrect
code need not be the instruction that actually fails.

Actually, on second thought, the code of Card and GameManager would be
really helpful right about now (especially if it's Card that's causing
duplicate key information).

OK, I have uploaded the parts that are needed over here:
http://pek.ekei.com/misc/help/cards/source.html
GameManager : The Stateful Bean
Card : The Card class
Game : A Data Type class that holds all information of a game.
Client : An example of how things work

Each file has some documentation in it.

/** Stupid Method */

Gotta love documenting stuff, don't you? (I've always thought that
documenting stuff like setFoo: Sets the foo variable were pointless)

At this point, it seems to me that either Utility's deckCreator (less
likely) is either messing up the players or that J2EE or JavaBeans (more
likely) are. Suffice to say, this is completely flummoxing me right now.
 
L

Lew

Joshua said:
At this point, it seems to me that either Utility's deckCreator (less
likely) is either messing up the players or that J2EE or JavaBeans (more
likely) are. Suffice to say, this is completely flummoxing me right now.

J2EE and JavaBeans are specifications. How do you think they are "messing up
the players"?

JavaBeans are like any other class - they are written by someone and could be
buggy. Which beans do you suspect of causing trouble? It is meaningless to say
"JavaBeans" are at fault generally; that's exactly like saying "classes" are
at fault. It may be true, but not usefully so. What is useful is to identify
which JavaBeans are causing trouble.

Are you suggesting that the J2EE container is messing up? Which one are you
using? The major ones are very, very unlikely to be the source of your
difficulty. On what basis could you say that it is "more likely" to be a cause
of trouble?

What is "Utility" and its "deckCreator"? Why do you think these artifacts are
"less likely" to be the source of trouble?

-- Lew
 
P

pek

J2EE and JavaBeans are specifications. How do you think they are "messing up
the players"?

JavaBeans are like any other class - they are written by someone and could be
buggy. Which beans do you suspect of causing trouble? It is meaningless to say
"JavaBeans" are at fault generally; that's exactly like saying "classes" are
at fault. It may be true, but not usefully so. What is useful is to identify
which JavaBeans are causing trouble.

Are you suggesting that the J2EE container is messing up? Which one are you
using? The major ones are very, very unlikely to be the source of your
difficulty. On what basis could you say that it is "more likely" to be a cause
of trouble?

What is "Utility" and its "deckCreator"? Why do you think these artifacts are
"less likely" to be the source of trouble?

-- Lew

I'm personally using JBoss
 
J

Joshua Cranmer

Lew said:
J2EE and JavaBeans are specifications. How do you think they are
"messing up the players"?

JavaBeans are like any other class - they are written by someone and
could be buggy. Which beans do you suspect of causing trouble? It is
meaningless to say "JavaBeans" are at fault generally; that's exactly
like saying "classes" are at fault. It may be true, but not usefully so.
What is useful is to identify which JavaBeans are causing trouble.

Are you suggesting that the J2EE container is messing up? Which one are
you using? The major ones are very, very unlikely to be the source of
your difficulty. On what basis could you say that it is "more likely" to
be a cause of trouble?

What is "Utility" and its "deckCreator"? Why do you think these
artifacts are "less likely" to be the source of trouble?

-- Lew
What I mean is that the some hitch in the specifications are causing the
trouble, IMHO. If you read that source code that pek posted, you will
see what I mean by Utility (a class) and deckCreator (a method). I think
that they are less likely to be the source because the method seems
straightforward to me and more difficult to cause problems than the J2EE
or JavaBeans code. That said, I am casting about in unknown waters, so
my opinion should not be taken as truth.
 
P

pek

What I mean is that the some hitch in the specifications are causing the
trouble, IMHO. If you read that source code that pek posted, you will
see what I mean by Utility (a class) and deckCreator (a method). I think
that they are less likely to be the source because the method seems
straightforward to me and more difficult to cause problems than the J2EE
or JavaBeans code. That said, I am casting about in unknown waters, so
my opinion should not be taken as truth.

Is there anywhere in the web that I can find information about
collection implementation in J2EE... All the books I have found and
JavaDocs simply say how to remove and add to a collection, there isn't
anywhere something like collection.add(anotherCollection.remove(0)) to
tell me if this is wrong or right and why...
 
L

Lew

pek said:
Is there anywhere in the web that I can find information about
collection implementation in J2EE... All the books I have found and
JavaDocs simply say how to remove and add to a collection, there isn't
anywhere something like collection.add(anotherCollection.remove(0)) to
tell me if this is wrong or right and why...

Sure there is:

<http://java.sun.com/javase/6/docs/api/java/util/Collection.html#add(E)>

and

<http://java.sun.com/javase/6/docs/api/java/util/Collection.html#remove(java.lang.Object)>

which, without even following the links, tells you right away that unless
collection holds Boolean and anotherCollection holds Integer, the idiom will
not work.

You should be in the habit of checking the API docs for this kind of question.

-- Lew
 
P

pek

Sure there is:

<http://java.sun.com/javase/6/docs/api/java/util/Collection.html#add(E)>

and

<http://java.sun.com/javase/6/docs/api/java/util/Collection.html#remov...)>

which, without even following the links, tells you right away that unless
collection holds Boolean and anotherCollection holds Integer, the idiom will
not work.

You should be in the habit of checking the API docs for this kind of question.

-- Lew

I believe this is incorrect. The remove of collection is
Collection.remove() with no parameters. I use ArrayLists which
implements List and has a method ArrayList.remove(int index) which
returns the removed object in the specified index
( http://java.sun.com/javase/6/docs/api/java/util/List.html#remove(int)
)
 
L

Lew

I believe this is incorrect. The remove of collection is
Collection.remove() with no parameters.

No, it's remove( Object o ) with one parameter. You hid that fact with the
ellipsis when you quoted the URL for the Javadoc of the method:

<http://java.sun.com/javase/6/docs/api/java/util/Collection.html#remove(java.lang.Object)>

is the correct link.
I use ArrayLists [sic] which

you didn't say. You said "collection".
implements List and has a method ArrayList.remove(int index) which
returns the removed object in the specified index
( http://java.sun.com/javase/6/docs/api/java/util/List.html#remove(int)
)

Unless the source List contains Integers, in which case there is some
ambiguity with autoboxing.

If not dealing with that case, you still have to make sure the base types of
the two Lists are the same.

If they are the same, then

dest.add( src.remove( 0 ))

is perfectly legitimate for two Lists.

What is the exact error you get when you try it?

-- Lew
 
P

pek

pek said:
I believe this is incorrect. The remove of collection is
Collection.remove() with no parameters.

No, it's remove( Object o ) with one parameter. You hid that fact with the
ellipsis when you quoted the URL for the Javadoc of the method:

<http://java.sun.com/javase/6/docs/api/java/util/Collection.html#remov...)>

is the correct link.
I use ArrayLists [sic] which

you didn't say. You said "collection".
implements List and has a method ArrayList.remove(int index) which
returns the removed object in the specified index
(http://java.sun.com/javase/6/docs/api/java/util/List.html#remove(int)
)

Unless the source List contains Integers, in which case there is some
ambiguity with autoboxing.

If not dealing with that case, you still have to make sure the base types of
the two Lists are the same.

If they are the same, then

dest.add( src.remove( 0 ))

is perfectly legitimate for two Lists.

What is the exact error you get when you try it?

-- Lew

There is no error... It does exactly what I want it do to.. It removes
a card from one list and adds it to the other..the problem is that
somehow after the method is over and the transaction is commited, the
teams have the same number of players with the number of cards I add,
meaning, I add 11 cards to the player
(player.getCards().add(game.getCenterDeck().getCards().remove(0)) and
the team has 11 references to the SAME player.
game.getTeams().get(1).getPlayers().size = 11.. I can't understand
why. I think that the problem is the way the transaction is commited.
I mean, since the transaction is executed after the method ends, it
probably doesn't make the correct changes. I read somewhere that
hibernate follows a number of steps. I think that this is what screws
everything. But I can't figure out the solution. Any help..?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top