JavaEE Basics: Singleton EJB — Concurrent Access Timeout in den Griff bekommen

Markus Kühle
coodoo
Published in
2 min readApr 18, 2017

--

Mit @Singleton kann jede EJB zu einer Singleton EJB werden, was bedeutet, dass nur eine Instanz dieser Bean in der JVM existiert. Dabei wird per Voreinstellung garantiert, dass jeder zugreifende Client alleinigen exklusiven Zugriff auf die Session Bean hat. Die Voreinstellung für diesen serialisierten Zugriff lautet “container-managed concurrency”.

Container Managed Concurrency

Versuchen zwei oder mehr Clients gleichzeitig auf eine Singleton EJB zuzugreifen, müssen sie sich hintereinander einreihen und warten bis der vorherige Aufruf abgearbeitet ist. Und so kommt es, dass jeder JavaEE Entwickler ab und an folgende Exception bei dem Zugriff auf seine Singleton EJB zu sehen bekommt:

Caused by: javax.ejb.ConcurrentAccessTimeoutException: WFLYEJB0241: EJB 3.1 PFD2 4.8.5.5.1 concurrent access timeout on <SingletonBeanName> — could not obtain lock within 5000MILLISECONDS

In diesem Fall dauerte die Ausführung einer Methode mehr als 5000 Millisekunden (5 Sekunden), so dass der Container die Ausführung des Aufrufsversuch auf diese oder eine andere Methode dieser Singleton Bean mit der ConcurrentAccessTimeoutException abbricht.

Read und Write Lock manuell vergeben

Die JavaEE Spezifikation bietet mit der Annotation javax.ejb.Lock sowie dem Parameter javax.ejb.LockType die Möglichkeit bei einer Container Managed Concurrency Bean darauf zu reagieren.

Darf eine Methode von mehreren Clients parallel aufgerufen werden, dann kann sie mit @Lock(LockType.READ) annotiert werden.
Soll die Bean für andere Aufrufe gesperrt werden muss die Methode mit @Lock(LockType.WRITE) annotiert werden. In der Regel wird dies verwendet, wenn der Zustand der Singleton Bean durch den Aufruf dieser Methode verändert wird.

Nur bei Methoden, die mit WRITE annotiert wurden, kann die ConcurrentAccessTimeoutException auftreten. Ist bekannt, dass der Aufruf sehr lange dauert kann mit der Annotation javax.ejb.AccessTimeout die Timeout Dauer verlängert werden.

Es ist also möglich per Konfiguration die Zugriffseinschränkungen in den Griff zu bekommen und auf die ConcurrentAccessTimeoutException zu reagieren.

Wenn auch das nicht hilft kann man die Container Managed Concurrency abschalten und auf Bean Managed Concurrency wechseln. In diesem Fall übernimmt der Entwickler vollständig die Zugriffsverwaltung.

--

--