public class VpEventManager extends Object implements Runnable
This is an implementation of an event manager. It will handle two forms of events:
De event manager wordt gebruikt om gebeurtenissen die plaatsvinden ergens in ViewPoint te melden aan geinteresseerde stukken code. Neem als voorbeeld de koppeling met Casper of met MOCA. Casper en MOCA willen alle wijzigingen die een ViewPoint gebruiker maakt op een werkbon zo snel mogelijk weten. Een "flut"methode om dit voor elkaar te krijgen is de methode die nu voor de Casper koppeling gebruikt wordt: laat om de paar seconden iets in de database "pollen" om te zien of er iets gewijzigd is. Dit is erg duur en niet herbruikbaar: voor ieder pakket wat dezelfde informatie nodig heeft moet opnieuw zo'n stuk geschreven worden wat pollt.
Het Event mechanisme gaat als alternatief hiervoor dienen, en wordt later verder uitgebouwd om SOA events mogelijk te maken vanuit ViewPoint. Met dit event mechanisme is de koppeling naar Casper op een veel eenvoudiger manier mogelijk, als volgt:
Dit mechanisme ontkoppelt code door gebeurtenissen te scheiden van het afhandelen van de gevolgen voor de verschillende koppelingen. Daarnaast is de koppeling goedkoop (geen polling*), herbruikbaar en interactief.
Hierbij worden events gebruikt voor code wat altijd uitgevoerd moet worden en alleen op de server waarop het event optreed. Notifications dienen om VP servers onderling te synchroniseren, en notifications worden niet gegarandeerd afgeleverd rond server startup/shutdown.
De huidige implementatie is suboptimaal omdat nog steeds polling gebruikt wordt, maar ze is later in geval van problemen te vervangen mits alleen de publieke interface in deze class gebruikt wordt. Hoewel er gepolled wordt is de overhead tamelijk miniem omdat slechts een enkele polling gebruikt wordt voor alle notifications.
De huidige implementatie creeert een Oracle table RED_VP_EVENTS in de database. Deze table ziet er uit als:
UPID NUMERIC(20, 0) not null primary key,
UTIME DATE not null,
EVNAME VARCHAR(80) not null,
SERVER VARCHAR(80) not null,
OBJ VARCHAR(4000)
De UPID PK is monotoon stijgend gevuld vanuit de sequence RED_VP_EVENTS_SQ. Zowel tabel als
sequence worden door de code zelf gecreeerd. Ieder event wat wordt gegenereerd door de code
wordt als enkel record in deze tabel opgenomen.
Iedere ViewPoint applicatie-server in het cluster heeft een eigen instance van de EventManager singleton. Tijdens initialisatie start deze instance een thread die iedere 4 seconden een select doet op deze tabel: select ... from RED_VP_EVENTS where upid > :last:. Door telkens de laatst ingelezen UPID te onthouden is dit een erg goedkope query die via de index alleen de voor de server nieuwe events leest. Doordat alle servers dezelfde tabel lezen worden events die op server A gegenereerd worden ook door alle andere servers gezien, zodat alle servers de bijbehorende event listeners aanroepen.
Het aanroepen van de event listeners is normaliter asynchroon: de event polling thread roept ze pas aan wanneer de events in de database gezien worden. Dit geldt zelfs voor de server die de event genereert. Er bestaat echter wel een call waarmee de postende server synchroon de event handlers aanroept, dus wanneer de postEventSynchronous() call terugkeert dan zijn alle handlers aangeroepen geweest. Dit synchrone gedrag geldt echter allen voor de postende server; de andere servers voeren de handlers pas uit wanneer de polling thread het event in de database tegenkomt.
De code controleert dat een event slechts eenmaal uitgevoerd wordt door de UPID van het laatst geziene event steeds te bewaren. Dit voorkomt tevens dat de event tabel steeds in het geheel doorgelezen moet worden om nieuwe events te vinden.
| Modifier and Type | Method and Description |
|---|---|
<T extends AppEventBase> |
addListener(Class<T> cl,
ListenerType lt,
AppEventListener<T> listener) |
<T extends AppEventBase> |
addWeakListener(Class<T> cl,
ListenerType lt,
AppEventListener<T> listener) |
static VpEventManager |
getInstance()
Get the instance.
|
static void |
initialize(DataSource ds,
String tableName,
IEventMarshaller eventMarshaller)
Initialize for production mode.
|
static void |
initializeForTest() |
static boolean |
inJUnitTestMode() |
void |
postDelayedEvent(Connection dbc,
AppEventBase ae)
Post an event asynchronously.
|
void |
postDelayedEvent(Connection dbc,
List<? extends AppEventBase> ae)
Post a list of events asynchronously.
|
void |
postEvent(Connection dbc,
AppEventBase ae)
Post an event synchronously.
|
void |
postEvent(Connection dbc,
List<? extends AppEventBase> aelist)
Post all of the events in the list synchronously.
|
void |
removeListener(Class<?> cl,
AppEventListener<?> listener)
Remove a weak or normal listener from a map.
|
<T extends AppEventBase> |
removeWeakListener(Class<T> cl,
AppEventListener<T> listener) |
void |
run()
Thread entry.
|
long |
sendEventMain(Connection dbc,
AppEventBase ae,
boolean commit,
boolean isimmediate)
NOT FOR COMMON USE - Primitive event poster.
|
void |
start()
Must be called after init to actually start handling events.
|
void |
stop() |
void |
waitUntilHandled(long value)
Sleep until the specified event has been handled.
|
public static VpEventManager getInstance()
public static void initialize(DataSource ds, String tableName, @Nonnull IEventMarshaller eventMarshaller) throws Exception
ds - tableName - eventMarshaller - Exceptionpublic static void initializeForTest()
public static boolean inJUnitTestMode()
public void stop()
public void start()
public void run()
run in interface RunnableRunnable.run()public long sendEventMain(@Nonnull Connection dbc, @Nonnull AppEventBase ae, boolean commit, boolean isimmediate) throws Exception
Exceptionpublic void removeListener(@Nonnull Class<?> cl, @Nonnull AppEventListener<?> listener)
cl - listener - public <T extends AppEventBase> void addListener(@Nonnull Class<T> cl, @Nonnull ListenerType lt, @Nonnull AppEventListener<T> listener)
public <T extends AppEventBase> void addWeakListener(@Nonnull Class<T> cl, @Nonnull ListenerType lt, @Nonnull AppEventListener<T> listener)
public <T extends AppEventBase> void removeWeakListener(@Nonnull Class<T> cl, @Nonnull AppEventListener<T> listener)
public void postEvent(@Nonnull Connection dbc, @Nonnull AppEventBase ae) throws Exception
dbc - ae - Exceptionpublic void postDelayedEvent(@Nonnull Connection dbc, @Nonnull AppEventBase ae) throws Exception
dbc - ae - Exceptionpublic void postDelayedEvent(@Nonnull Connection dbc, @Nonnull List<? extends AppEventBase> ae) throws Exception
dbc - ae - Exceptionpublic void postEvent(@Nonnull Connection dbc, @Nonnull List<? extends AppEventBase> aelist) throws Exception
dbc - aelist - ExceptionCopyright © 2017 etc.to. All rights reserved.