# Synchronized in JavaEE



## reNur (17. Nov 2011)

Hallo,

eine etwas blöde Frage - aber ich bin mir irgendwie nicht sicher:

Die Benutzung von "manuellen" Locks usw. ist ja innerhalb EJB verboten, ich darf also beispielsweise kein "synchronized" in einem Stateless EJB verwenden.

Ist es aber erlaubt, auf ganz normalen Java-Objekten, die von EJBs aufgerufen werden, Methoden als synchronized zu deklarieren?


----------



## FArt (18. Nov 2011)

Nachdem jeder Call seine eigene Instanz eines SLSB erhält, besteht dort kein Bedarf für Synchronisation. Ausnahme ist ein Singleton Bean, aber da kann man über den Container oder das Bean synchronisieren lassen (EJB 3.1 Spec - 4.8.5 Bean Concurrency).


----------



## reNur (25. Nov 2011)

Hallo,

ich glaub ich verstehe das noch nicht ganz.
Angenommen, ich habe 2 SLSBs, die auf eine Datenbanktabelle zugreifen - z.B. Hinzufügen eines Artikels in eine Tabelle "Bestellung". Jeder Artikel hat eine Nummer (z.B. Position 1, 2, 3,....), die pro Bestellung einmalig ist.

Egal wie ich auf die Datenbank zugreife - die Vergabe dieser Unique-ID erfolgt ja letztendlich im Datenbankmanagementsystem. Sollten nun 2 SLSB quasi gleichzeitig einen Artikel hinzufügen wollen, so erfolgt ja wohl die Synchronisation auf DB-Seite, sprich irgend ein Lock wird angelegt.

So, und angenommen ich habe die Daten einer Bestellung nicht in einer DB, sondern also "normales" Java-Objekt (Bestellung.java oder wie auch immer). Und dieses Objekt hat die Methode "Artikel hinzufügen", und in dieser Methode wird die Unique-ID festgelegt. Darf ich dann die Methode dieser Klasse als synchronized deklarieren (z.B. public synchronized int artikelHinzufuegen) und dann diese Klasse in einer JavaEE Umgebung benutzen?


----------



## FArt (25. Nov 2011)

reNur hat gesagt.:


> Hallo,
> 
> So, und angenommen ich habe die Daten einer Bestellung nicht in einer DB, sondern also "normales" Java-Objekt (Bestellung.java oder wie auch immer). Und dieses Objekt hat die Methode "Artikel hinzufügen", und in dieser Methode wird die Unique-ID festgelegt. Darf ich dann die Methode dieser Klasse als synchronized deklarieren (z.B. public synchronized int artikelHinzufuegen) und dann diese Klasse in einer JavaEE Umgebung benutzen?



Wie "normal" ist denn dein Objekt? Wie stellst du sicher, dass alle Beans diese Objektinstanz zu sehen bekommen und somit konsistente IDs ziehen?
Den Service für die IDs sollte man über eine SLSB als Singleton realsieren.


----------



## reNur (28. Nov 2011)

Hallo,

Das Szenario, bei dem ich mir diese Gedanken gemacht habe, war folgendes:
Ich arbeite eigentlich an einer ganz anderen Baustelle. Für ein paar Tests habe ich mir Features anlegen müssen, die erst später richtig implementiert werden. Dazu gehört eben auch eine Art "Bestellungs"objekt.

Dieses Object hat eine Unique ID, die später sicherlich in einer Datenbank etc. verwaltet wird. Für meine Zwecke habe ich mir ein Singleton EJB gebaut, in dem eine Methode "erzeuge neue Bestellung" implementiert ist, die eine neue Instanz des Objekts "Bestellung" anlegt und auch die ID vergibt.
Analog dazu gibt es eine Methode "getBestellung(id)" in dem Singleton Bean.

Jedes SLSB, das mit einer ID die getBestellung-Methode aufruft, erhält also die richtige Instanz, da hier im Singleton synchronisiert wird.

Dann habe ich mir überlegt, was wohl passieren würde, wenn ich die Methoden der Klasse "Bestellung" nicht über das Singleton laufen lassen (also z.B. im SingletonBean "addArtikel( Bestellung, Artikel ), sondern direkt auf dem Object eine Methode "synchronized addArtikel(Artikel)" hinzufüge.


----------



## FArt (29. Nov 2011)

Nun, jedes SLSB hat eine eigene Instanz. Auf dieser Instanz wird nicht konkurrierend zugegriffen, somit ist synchronized unnötig. Die Frage wäre in dem Fall immer noch: wer hält deinen Zähler und in welcher Form?
Wenn du an ein (static) Field im SLSB denkst, dann lautet die Antwort: das ist laut Spec verboten, weil nicht sichergestellt ist, dass das funktioniert.


----------



## reNur (29. Nov 2011)

Der Zähler liegt im Singleton Bean...

mal als Pseudocode:


```
@Singleton
public class SingletonClass...

private List<Bestellungen> liste;
private int zaehler;

public void addBestellung( Bestellung b )
{
int id = zaehler + 1;
b.setId(id)
}

public Bestellung getBestellung( int id )
{
return liste.get( id )
}
```


Nun, und wenn die Klasse Bestellung nun eine Method addArtikel( String artikel ) hätte - könnte man diese synchronisieren?


----------



## FArt (29. Nov 2011)

reNur hat gesagt.:


> Nun, und wenn die Klasse Bestellung nun eine Method addArtikel( String artikel ) hätte - könnte man diese synchronisieren?




Wozu? Die Bestellung wird doch nur von einem SLSB verarbeitet bzw. von einem Call gleichzeitig verarbeitet.


----------



## reNur (29. Nov 2011)

Aber was, wenn nicht?

Also wenn - nur so als Beispiel - Artikel messagebasiert hinzugefügt werden. Mehrere MDBs hören auf eine "füge Artikel zu Bestellung mit ID x hinzu" Nachricht. Trifft diese ein, so holen sie sich eine Instanz der Bestellung über die Singleton Bean. Zu der entsprechenden ID wird - da Singleton - ja immer die selbe Instanz der Bestellung zurückgeliefert. Es kann also sein, dass mehrere MessageDriven Beans eine Bestellungs-Instanz bearbeiten und mit "addArtikel" einen Artikel hinzufügen wollen.


----------



## FArt (30. Nov 2011)

Das wäre fehlerhaftes Design in einem EE Umfeld.

Du denkst einfach zu "kleinkariert", also mit den Gedanken eines Java-Entwicklers, nicht eines Enterprise-Entwicklers. Wie du schon sagtest, sind das natürlich normalerweise Entitäten auf der DB und somit über die Transaktion gekapselt. Wenn du so etwas zur Laufzeit machen möchtest, müsstest du das in einem Singleton Bean ("Service") tun, also nicht den Artikel herausgeben.

Das Problem in der Enterpriseumgebung ist, dass du mit einfachen Javamitteln gar nicht sinnvoll synchronisieren kannst. Es kann, bedingt durch Konfiguration und Infrastruktur, passieren, dass zwei Consumer zwar die selbe Entität, aber verschiedene Instanzen davon refernzieren. Somit haben diese auch verschiedene Monitore beim synchronisieren.


----------



## reNur (1. Dez 2011)

Hmm ok ich verstehe schon dass man das aus einer anderen Sichtweise betrachten muss.
Bei Entitäten, die in Datenbanken verwaltet werden, ist mir das auch sonnenklar. Wenn ich mir aus dem DB-Object eine Java-Instanz generiere, steht diese ja praktisch in keiner Verbindung zum DB-Object und muss erst wieder persistent gemacht werden, damit die Änderungen in dem Objekt überhaupt vorgenommen werden.
Aber technisch gesehen erhält jeder Aufruf zu einer getBestellung-Methode doch genau ein Objekt dass in irgendeiner Speicheradresse liegt... wobei ich merke schon, da muss ich mich noch einlesen.

Eine andere Frage, die mir gerade gekommen ist:
Angenommen, ich habe eine Singleton-Bean, die alle Bestellungen verwaltet. Clients (also andere EJBs) können selbstständig neue Artikel-Objekte erstellen (die wiederum Attribute wie z.B. Name, Anzahl etc. enthalten).
Dann werden diese Artikel an die Bestellung übergeben - also z.B. durch Aufruf einer addArtikelPosition( BestellungsID, ArtikelObject )-Methode der Singleton Bean. Im Singleton wird dann die ID des Artikels gesetzt etc. Ist das ein 'sauberer' Ansatz.

P.S.: Das sind alles nur Fragen bzw. Beispiele, die mich im Zusammenhang mit JEE beschäftigen - ich versuche also nicht, eine Shop-Applikation oder so zu entwickeln


----------



## FArt (2. Dez 2011)

reNur hat gesagt.:


> Aber technisch gesehen erhält jeder Aufruf zu einer getBestellung-Methode doch genau ein Objekt dass in irgendeiner Speicheradresse liegt... wobei ich merke schon, da muss ich mich noch einlesen.


Nein, genau das ist ja der Haken. Die Spezifiakation sichert dir lediglich zu, dass du ein Objekt der Klasse A mit dem passenden Inhalt siehst. Das kann auch eine Kopie sein. Bei Calls auf eine Remoteinterface war das früher immer eine Kopie (marshalling/unmarshalling beim Call). Heutzutage optimieren Applikationsserver den Call in der Regel in einer VM, aber wie gesagt: das kann der Container machen wie er lustig ist.



reNur hat gesagt.:


> Angenommen, ich habe eine Singleton-Bean, die alle Bestellungen verwaltet. Clients (also andere EJBs) können selbstständig neue Artikel-Objekte erstellen (die wiederum Attribute wie z.B. Name, Anzahl etc. enthalten).
> Dann werden diese Artikel an die Bestellung übergeben - also z.B. durch Aufruf einer addArtikelPosition( BestellungsID, ArtikelObject )-Methode der Singleton Bean. Im Singleton wird dann die ID des Artikels gesetzt etc. Ist das ein 'sauberer' Ansatz.


Das ist ein unpraktisches Beispiel, aber egal. Nennen wir das Singleton-Bean "Bestellservice" (das muss kein Singleton Bean sein, das wäre lediglich ein Implementierungsdetail) dann wäre das ein konsistenter Weg. Über Aufgaben (somit Methoden) des Services müsste man sich in deinem Fall wieder ein wenig streiten, aber im Prinzip wäre das so richtig.


----------

