Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 38 Next »

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.

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.

Przykład
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.

Przykład
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 odpowiada za wykonywanie wszystkich hook'ów tego samego typu w odpowiedniej kolejności. Dodatkowo musi on wyłapywać wyjątek HookException, który może być rzucony przez hooka. Złapany wyjątek należy rzucić dalej jako HookExecutorException z podaniem jaki Hook rzucił wyjątek i jaką podał wiadomość.

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.

Przykład
@HookType( value = UserDelegationHook.class )
public class UserDelegationHookProcessor
	extends AbstractHookProcessor<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.

  • No labels