Session-Bean aufräumen bei Timeout bei Seam/EJB

JanHH

Top Contributor
Hallo,

bei meiner Anwendung gibts pro User eine Stateful Session Bean, mit Session-Scope, die eine Entity hält, welche von dem Benutzer bearbeitet wird. Die zu bearbeitende Entity (JPA-@Entity, also Eintrag einer Datenbanktabelle) wird, wenn sich ein User einloggt, zufällig ausgewählt; um zu verhindern, dass mehrere User versehentlich die gleiche Entity zugeordnet bekommen, hat diese ein boolean-Flag "selected", welches nach Auswahl auf "true" gesetzt wird und wenn der User fertig ist, wieder auf "false".

Probleme bereitet mir nun der Fall, wenn der User sich nicht ordnungsgemäß ausloggt und seine Arbeit beendet, sondern einfach so weggeht oder den Browser schliesst, und die Session Bean letzten Endes durch ein Timeout der HTTP-Session abgeräumt wird. In diesem Fall muss die Entity natürlich auch wieder auf "false" gesetzt werden, da sie ja sonst für alle anderen User gesperrt bleibt, was natürlich nicht beabsichtigt ist.

Nur will das irgendwie nicht funktionieren. Es handelt sich um eine Seam/EJB3-Anwendung, und nach allem was ich so weiss, gibts da zwei Varianten, die so aussehen:

a)
Java:
@In
private EntityManager entityManager

@Destroy
public void cleanup()
{
   myEntity.setSelected(false);
   entityManager.merge(myEntity);
}

b)
Java:
@PersistenceContext
private EntityManager entityManager

@PreDestroy
public void cleanup()
{
   myEntity.setSelected(false);
   entityManager.merge(myEntity);
}

Also unterschiedlich, je nachdem ob man den EBJ- oder den Seam-EntityManager benutzt.

Aber beides funktioniert nicht.. Fehlermeldungen:

a)
06:32:17,078 ERROR [AssertionFailure] an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: cannot copy a reference to an object with a null id
at org.hibernate.type.EntityType.replace(EntityType.java:255)

b)

06:38:30,718 WARN [Component] Exception calling stateful session bean default @Remove method: startProject
java.lang.RuntimeException: javax.persistence.TransactionRequiredException: EntityManager must be access within a transaction
at org.jboss.ejb3.interceptor.LifecycleInterceptorHandler.preDestroy(LifecycleInterceptorHandler.java:135

Was mag da los sein?

Und vor allem: ist mein Ansatz, die Entity in der Destroy/PreDestroy-Funktion zu verändern, überhaupt der richtige? Oder wie macht man sowas normalerweise?

Gruß+Danke
Jan
 
M

maki

Gast
Und vor allem: ist mein Ansatz, die Entity in der Destroy/PreDestroy-Funktion zu verändern, überhaupt der richtige? Oder wie macht man sowas normalerweise?
Du baust dir gerade dein eigenes Pessemistic Locking nach ;)

Abgesehen daovn verstehe ich nicht warum man zu beabeitende Entities zufällig auswählen wollen würde..
 

JanHH

Top Contributor
Na ob die nun zufällig ausgewählt werden oder bewusst, sie bleiben gesperrt, wenn der User sich nicht ausloggt oder sie wieder freigibt. Dachte, genau dazu sind diese Funktionen.. Notwendige Aufräumarbeiten, wenn die Session timeout hat. Sehe ich das verkehrt?
 

FArt

Top Contributor
Die preDestroy-Methode läuft in einem unspezifiziereten Transaktions- und Securitycontext (siehe EJB Spec). Es ist nicht sichergestellt, dass preDestroy auch aufgerufen wird (Gründe: siehe EJB Spec). Der Beanentwickler darf nur die Callback-Methoden einsetzen, um eigene Arbeiten zu verrichten.

maki hat schon angemerkt, dass du hier etwas "nachbaust". Was ist das für eine Entity? Was wird einem User zugeordnet?
 

JanHH

Top Contributor
Naja der Anwendungsfall ist doch eigentlich relativ einfach. Ein User wählt einen Datensatz aus um diesen zu bearbeiten, diese Bearbeitung kann recht lange dauern, und während dieser Zeit muss sichergestellt sein, dass dieser Datensatz nicht zur Auswahl für andere User zur Verfügung steht. Also muss er irgendwo als "gerade in Bearbeitung" markiert werden. Wenn der User den Vorgang ordnungsgemäß abschliesst, ist alles ok. Wenn er einfach das Browserfenster schliesst und wegläuft, bleibt der Datensatz als "in Bearbeitung" markiert, was natürlich nicht so sein soll. Daher bleibt da nur, beim Session Timeout des Users, den Datensatz wieder freizugeben.

So mal ganz prosaisch formuliert ,).

Wie löst ihr denn sowas? Ich habs jetzt hingekriegt, allerdings auf eine etwas "unkonvetionelle" Art.
 
Zuletzt bearbeitet:

FArt

Top Contributor
Das über Locking zu lösen ist schon ok. Es muss aber nicht persistent sein.

Entweder die User holen sich die Datensätze nicht, sondern bekommen sie z.B. über eine Factory (und melden ein Ende der Arbeit). Meldet sich der User nicht mehr zurück, wird mit dem Ende der Session die Ressoruce wieder freigegeben. Zu realisiern mit einer einfachen Collection, in der die aktiven DS enthalten sind.

Wenn sich der User die DS selber holen muss, kann man das immer noch ähnlich realisieren, inem der User die DS erst registrieren muss. Man kann dann auch (wenn nötig) sicherstellen, dass Änderungen nur an registrierten Objekten und nur von dem registrierten User erlaubt sind.

P.S.: dem fachlichen Objekt direkt ein Attribut "selected" zu verpassen ist eine unschöne Vermischung ... das könnte man z.B. dekorieren ...
 

JanHH

Top Contributor
Doch, das Attribut "Datensatz wurde schon benutzt" soll persistent in der Datenbank stehen. Das ist auch für einige andere Dinge notwendig (z.B. eine Übersicht, wieviele Datensätze schon verwendet worden sind, und wieviele noch unangetastet sind).

Das Problem scheint nur zu sein, eine Methode aufzurufen, die bei session timeout eine Datenbankaktion durchführt. Das habe ich allerdings hinbekommen, wenn auch auf eine absolut unelegante Art. Definitiv nur eine Notlösung. Es wird ganz brutal per Hand eine JDBC-Verbindung aufgebaut, und da dann ein SQL-Statement durchgeführt. Und das innerhalb eines EJB Application Servers...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
K EJB Session Bean Application Tier 2
A Stateful Session Bean will nicht "stateful" sein Application Tier 18
S Statefull Session Bean für UserLogin Application Tier 4
O javax.naming.NoInitialContextException - Remote Session Bean Application Tier 2
O Anfängerproblem mit Session Bean Application Tier 3
N Kummunikation Application Client - Session Bean Application Tier 8
F Time-out Zeit für Session-Bean Application Tier 4
M Entity Bean wird nicht in stateless Session Bean injeziert Application Tier 3
M EJB3 Annotations für Session Beans mit einem Parameter ? Application Tier 5
K Benutzer-Daten über mehrere Session-Beans Application Tier 14
F Lose Kopplung zwischen Session Beans Application Tier 4
S DB-Verbindung beenden beim auflauf der session? Application Tier 7
V EJB: Eine Remote Bean soll eine Local Bean ansprechen und dem Client übergeben Application Tier 2
B Spring context:component-scan: No such bean definition Application Tier 2
M EJB Stateless Bean ist immer null im REST WebService Application Tier 3
T ERROR: Bean name must not be empty! Application Tier 3
P Timer Bean Application Tier 11
B Message-Driven Bean reagiert nicht Application Tier 3
F Property-Datei in Stateless-Bean laden Application Tier 8
V Stateless-Bean soll Info aus Stateful-Bean holen Application Tier 3
byte [Spring] Referenced Bean not found Application Tier 2

Ähnliche Java Themen

Neue Themen


Oben