Wstęp
Sekcja hook'ów
Jest to interfejs zawierający hook'i dla danej sekcji systemu. Sekcją taką mogą być zastępstwa użytkownika. Tworzony jest jeden interfejs UserDelegationHook, który zawiera zbiór metod (hook'ów) związanych z zastępstwami.
LOWEST_PRECENDENCE
Należy pamiętać, aby po dodaniu nowej sekcji hook'ów uzupełnić listę z hook'ami w Spis hook'ów systemowych.
Definiowanie sekcji hook'ów składa się z 4 etapów.
Utworzenie interfejsu dla sekcji hook'ów
Każda sakcja hook'ów musi posiadać interfejs. Interfejs definiuje metody (hook'i), które mogą być zaimplementowane i wywoływane w systemie.
public interface UserDelegationHook { public boolean confirmCreateDelegation( String userName, UserDelegation delegation ); public void delegationAdded( String userName, UserDelegation delegation ); }
Interfejs UserDelegationHook definiuje dwa hook'i. Pierwszy jest wywoływany przed utworzeniem zastępstwa, w zależności jaka wartość będzie zwrócona, od tego będzie zależeć, czy zastępstwo powinno zostać utworzone. Drugi hook wywoływany jest już po pomyślnym dodaniu zastępstwa.
Interfejs musi znaleźć się w projekcie API.
Utworzenie klasy abstrakcyjnej dla sekcji hook'ów, która pełni rolę adaptera interfejsu
Klasa abstrakcyjna musi implementować utworzony interfejs oraz implementować wszystkie jego metody. Pełni ona rolę adaptera dla interfejsu. Dzięki temu we wdrożeniu nie trzeba implementować wszystkich metod, tylko te, które są potrzebne. Zapobiega to również błędom kompilacji we wdrożeniach w momencie, gdy zostanie dodany kolejny hook do interfejsu.
Uwaga
Implementowane metody nie mogą w żaden sposób zmieniać działania systemu. Powinny zachowywać się tak, jakby nie były w ogóle wykonywane. Logika metod powinna być zawarta we właściwej implementacji sekcji hook'ów.
Klasa abstrakcyjna powinna również implementować interfejs org.springframework.core.Ordered oraz jego metodę getOrder(). Klasa ta pozwala na wywołanie kilku hook'ów tego samego typu w określonej kolejności. Domyślnie implementowana metoda powinna zwracać wartość zapisaną w zmiennej Ordered.LOWEST_PRECEDENCE, co skutkuje tym, że taki hook wykonywany jest na samym końcu.
public abstract class UserDelegationHookAdapter implements UserDelegationHook, Ordered { public boolean confirmCreateDelegation( String userName, UserDelegation delegation ) { return true; } public void delegationAdded( String userName, UserDelegation delegation ) { } public int getOrder() { return Ordered.LOWEST_PRECEDENCE; } }
Adapter musi znaleźć się w projekcie API.
Utworzenie procesora dla sekcji hook'ów
Procesor musi implementować interfejs odpowiadający odpowiedniej sekcji hook'ów oraz rozszerzać klasę abstrakcyjną com.suncode.pwfl.hook.AbstractHookProcessor<T>, gdzie T - jest to typ odpowiedniej sekcji hook'ów. Dodatkowo procesor musi posiadać adnotację @HookType( value = clazz), gdzie clazz - jest to interfejs dla odpowiedniej sekcji hook'ów. Dzięki klasie AbstractHookProcessor procesor dziedziczy metodę getHooks(), która zwraca wszystkie zdefiniowane hook'i danego typu. Hooki te są rejestrowane podczas startu systemu za pomocą rejestratora HookRegistry.class.
@HookType( value = UserDelegationHook.class ) public class UserDelegationHookProcessor extends HookProcessorAdapter<UserDelegationHook> implements UserDelegationHook { public boolean confirmCreateDelegation( String userName, UserDelegation delegation ) { boolean confirm = true; for ( DelegationHook hook : getHooks() ) { try { confirm = hook.confirmCreateDelegation( String userName, delegation ); if( confirm == false ) { return false; } } catch ( HookException e ) { throw new HookExecutorException( "Hook " + hook.getClass().getSimpleName() + " zwrócił następujący wyjątek: '" + e.getMessage() + "'" ); } } return confirm; } public void delegationAdded( String userName, UserDelegation delegation ) { for ( DelegationHook hook : getHooks() ) { try { hook.delegationAdded( String userName, delegation ); } catch ( HookException e ) { throw new HookExecutorException( "Hook " + hook.getClass().getSimpleName() + " zwrócił następujący wyjątek: '" + e.getMessage() + "'" ); } } } }
Procesor powinien znaleźć się w projekcie CORE.
Osadzanie hook'ów w systemie
Po wykonaniu wszystkich wcześniejszych kroków, należy osadzić hook'i w odpowiednich miejscach systemu. Aby tego dokonać należy pobrać istniejąca instancję HookRegistry z contextu Spring'a.
@Autowired private HookRegistry hr;
lub
private HookRegistry hr = SpringContext.getBean( HookRegistry.class );
Mając instancję HookRegistry osadzamy hook'i następująco:
//dla hook'a confirmCreateDelegation boolean confirm = hr.invoke( UserDelegationHook.class ).confirmCreateDelegation( userName, delegation ); //dla hook'a delegationAdded hr.invoke( UserDelegationHook.class ).delegationAdded( userName, delegation );
Metoda invoke( UserDelegationHook.class ) zwraca procesor zarejestrowany dla sekcji hook'ów UserDelegationHook. Następnie w procesorze wywoływana jest odpowiednia metoda dla hook'a. Jeżeli nie ma utworzonej żadnej implementacji hook'a, to procesor niczego nie wykona.