De Topic-titel biedt te weinig ruimte om een goede omschrijving te geven. Ik had willen zeggen: "Een entity bean zoeker binnen dezelfde transactie als waar de bean in is gecreëerd."
Laat me de casus omschrijven door de doorlopen stappen aan te geven:
-1) Een stateful SessionBean SB wordt in het leven geroepen waarbij geldt dat SB is BMP+BMT.
-2) SB start een transactie T1.
-3) SB creëert EntityBean A waarbij geldt dat A is CMP+CMT. Alle methods in A zijn "Mandatory" gedeclareerd, dus ze draaien mee in de transactie T1.
-4) SB zoekt of een bean met criteria X bestaat. Dit is niet het geval dus wordt EntityBean B gecreëerd waarbij geldt dat B is CMP+CMT. Alle methods in B zijn "Mandatory" gedeclareerd, dus ze draaien mee in de transactie T1. Bovendien geldt dat A een CMR heeft naar B.
-5) SB creëert EntityBean C. waarbij geldt dat C is CMP+CMT. Alle methods in C zijn "Mandatory" gedeclareerd, dus ze draaien mee in de transactie T1.
-7) SB zoekt of een bean met criteria X bestaat. Dit zou nu wel het geval moeten zijn want B is gecreëerd. In dat geval moet C een relatie maken naar de bestaande B. Hier gaat het fout!
-8) SB commit transactie T1.
In stap 7 treedt de volgende exceptie op aan de serverkant in de finder voor het zoeken naar beans met criteria X:
Hierdoor treedt de volgende exceptie op aan de clientkant:
Mijn interpretatie is dat in stap 7 niet gezocht kan worden een bean met criteria X omdat B nog niet ge-commit is. Tevens geldt dat B niet gecommit kan worden zolang SB de transactie niet ge-commit heeft. De finder zal wachten op de commit van B die nooit zal plaatsvinden omdat stap 7 onderdeel is van dezelfde transactie. En voila: een deadlock.
Wat ik heb overwogen:
Ik zou B kunnen commiteren in een nieuwe transactie T2. Hiertoe moet ik een T2 nesten in transactie T1. Dit is mogelijk, echter kan dan nooit meer een rollback plaatvinden van hetgeen ge-commit werd in T2 indien T1 een rollback uitvoert. Alles wat aangemaakt wordt in T1 moet ongedaan gemaakt worden als er iets fout gaat waardoor een geneste transactie geen oplossing is. Ik zie eigenlijk geen goede aanpak hiervoor. Suggesties zeer welkom!
Tevens wil ik het problem nog wat algemener voorleggen: kun je een entity bean opzoeken en gebruiken binnen de zelfde transactie waarin de bean gecreëerd werd? Of kom je in zo'n geval altijd op een deadlock uit?
Laat me de casus omschrijven door de doorlopen stappen aan te geven:
-1) Een stateful SessionBean SB wordt in het leven geroepen waarbij geldt dat SB is BMP+BMT.
-2) SB start een transactie T1.
-3) SB creëert EntityBean A waarbij geldt dat A is CMP+CMT. Alle methods in A zijn "Mandatory" gedeclareerd, dus ze draaien mee in de transactie T1.
-4) SB zoekt of een bean met criteria X bestaat. Dit is niet het geval dus wordt EntityBean B gecreëerd waarbij geldt dat B is CMP+CMT. Alle methods in B zijn "Mandatory" gedeclareerd, dus ze draaien mee in de transactie T1. Bovendien geldt dat A een CMR heeft naar B.
-5) SB creëert EntityBean C. waarbij geldt dat C is CMP+CMT. Alle methods in C zijn "Mandatory" gedeclareerd, dus ze draaien mee in de transactie T1.
-7) SB zoekt of een bean met criteria X bestaat. Dit zou nu wel het geval moeten zijn want B is gecreëerd. In dat geval moet C een relatie maken naar de bestaande B. Hier gaat het fout!
-8) SB commit transactie T1.
In stap 7 treedt de volgende exceptie op aan de serverkant in de finder voor het zoeken naar beans met criteria X:
java.sql.SQLException: Deadlock found when trying to get lock; Try restarting transaction, message from server: "Lock wait timeout exceeded; try restarting transaction"
Hierdoor treedt de volgende exceptie op aan de clientkant:
java.rmi.ServerException: RuntimeException; nested exception is: java.lang.IllegalStateException: No transaction.
Mijn interpretatie is dat in stap 7 niet gezocht kan worden een bean met criteria X omdat B nog niet ge-commit is. Tevens geldt dat B niet gecommit kan worden zolang SB de transactie niet ge-commit heeft. De finder zal wachten op de commit van B die nooit zal plaatsvinden omdat stap 7 onderdeel is van dezelfde transactie. En voila: een deadlock.
Wat ik heb overwogen:
Ik zou B kunnen commiteren in een nieuwe transactie T2. Hiertoe moet ik een T2 nesten in transactie T1. Dit is mogelijk, echter kan dan nooit meer een rollback plaatvinden van hetgeen ge-commit werd in T2 indien T1 een rollback uitvoert. Alles wat aangemaakt wordt in T1 moet ongedaan gemaakt worden als er iets fout gaat waardoor een geneste transactie geen oplossing is. Ik zie eigenlijk geen goede aanpak hiervoor. Suggesties zeer welkom!
Tevens wil ik het problem nog wat algemener voorleggen: kun je een entity bean opzoeken en gebruiken binnen de zelfde transactie waarin de bean gecreëerd werd? Of kom je in zo'n geval altijd op een deadlock uit?
"Kill one man, and you are a murderer. Kill millions of men, and you are a conqueror. Kill them all, and you are a god." -- Jean Rostand