Services

Die TopLogic-Engine besteht aus einer Vielzahl von Services, die über die Anwendungskonfiguration eingebunden und parametrisiert werden. Ein Service ist hierbei ein Singleton-Objekt (ein Objekt einer Klasse, von der es nur genau eine Instanz gibt) im System. Eine solche Service-Instanz hat einen bestimmten Lebenszyklus. Sie wird beim Booten des Systems erstellt und initialisiert. Während der Laufzeit des Systems bietet die Service-Instanz Dienste an oder verwaltet Resourcen des Systems. Beim Shutdown des Systems wird die Service-Instanz ebenfalls informiert und kann Aufräumarbeiten durchführen.

Service-Klasse

Ein Service ist eine Ableitung der Klasse com.top_logic.basic.module.ManagedClass. Er kann die Methoden startUp() und shutDown() überschreiben, um Initialisierungs- und Aufräumarbeiten beim Booten und Herunterfahren des System durchzuführen. Daneben benötigt eine Service-Klasse noch eine Descriptor-Klasse, mit der er in der Konfiguration registriert wird. Die Descriptor-Klasse ist typischerweise eine innere Klasse des Service mit Namen Module abgeleitet von TypedRuntimeModule. Die Descriptor-Klasse muss das Singleton-Pattern implementieren (vgl. Singleton-Referenz), um aus der Konfiguration referenzierbar zu sein.

Service-Konfiguration

Ein Service kann über Konfigurationsoptionen parametrisiert werden. Typsicherweise liegt die Grundkonfiguration in der Anwendungskonfiguration in dem Modul, das den Service definiert. In der konkreten Anwendung können die Parameter überschrieben sein. Der Service kann auch zur Laufzeit der Anwendung im Service-Editor angezeigt und seine Konfigurationseinstellungen bearbeitet werden.

Die Konfigurationsoptionen, die für einen Service eingestellt werden können, legt der Service in seinem Konfigurationsinterface fest. Das Konfigurationsinterface folgt dabei den Regeln der Typisierte Konfiguration. Für jede Konfigurationseigenschaft definiert das Konfigurationsinterface eine Get-Methode, die den Wert liefert. Der Name der Methode bestimmt den Namen der Konfigurationseigenschaft (oder es ist explizit über die Annotation @Name(...) an der Get-Methode festgelegt). Das Konfigurationsinterface ist mit dem Service über den Service-Konstruktor verknüpft. Der Service-Konstruktor muss hierfür die Signatur public MyService(InstantiationContext, Config) haben. Hierbei ist Config das Konfigurationsinterface des Service, welches seinerseits eine Erweiterung von ServiceConfiguration sein muss.

Minimale Service-Klasse

Ein minimaler Service (mit Konfigurationsoptionen) besteht aus den folgenden Klassen:

import com.top_logic.basic.config.InstantiationContext;
import com.top_logic.basic.config.annotation.Name;
import com.top_logic.basic.module.ConfiguredManagedClass;
import com.top_logic.basic.module.TypedRuntimeModule;

/**
 * Custom service.
 */
public class MinimalService extends ConfiguredManagedClass<MinimalService.Config<?>> {

	/**
	 * Configuration options for {@link MinimalService}.
	 */
	public interface Config<I extends MinimalService> extends ConfiguredManagedClass.Config<I> {

		/**
		 * Example for an int-valued configuration option.
		 */
		@Name("my-option")
		int getMyOption();

	}

	/**
	 * Creates a {@link MinimalService} from configuration.
	 */
	public MinimalService(InstantiationContext context, Config<?> config) {
		super(context, config);

		// TODO: Do something with the options in config.
	}

	@Override
	protected void startUp() {
		super.startUp();

		// TODO: Some startup task.
	}

	@Override
	protected void shutDown() {
		// TODO: Some cleanup work.

		super.shutDown();
	}

	/**
	 * Service descriptor for {@link MinimalService}
	 */
	public static class Module extends TypedRuntimeModule<MinimalService> {

		/**
		 * Singleton {@link Module} instance for reference in the configuration.
		 */
		public static final Module INSTANCE = new Module();

		private Module() {
			// Singleton constructor.
		}

		@Override
		public Class<MinimalService> getImplementation() {
			return MinimalService.class;
		}

	}

}

Statt ManagedClass direkt abzuleiten wird hier ConfiguredManagedClass verwendet, um den Service über Konfigurationsoptionen parametrisieren zu können. In diesem Fall muss das Konfiugrationsinterface des Service entsprechend ConfiguredManagedClass.Config erweitern.

Aktivieren des Service

In der Anwendungskonfiguration muss jetzt der Service-Deskriptor eingebunden und der Service dort aktiviert werden:

<application xmlns:config="http://www.top-logic.com/ns/config/6.0">
	<services>
		<config service-class="com.top_logic.basic.module.ModuleSystem">
			<instance>
				<modules>

					<!-- Register and activate service here. -->
					<module key="my.package.MinimalService$Module" value="true"/>

				</modules>
			</instance>
		</config>
	</services>
</application>

Service-Grundkonfiguration

Die Service-Grundkonfiguration wird ebenfalls in der Anwendungskonfiguration hinterlegt. Hier muss mindestens die Service-Klasse (hier MinimalService) und deren Service-Implementierung (hier ebenfalls MinimalService) angegeben werden. Weiterhin können Werte für Konfigurationsparameter hinterlegt werden, die im Konfigurationsinterface des Service definiert wurden:

<application xmlns:config="http://www.top-logic.com/ns/config/6.0">
	<services>

		<!-- Core configuration with example option. -->
		<config service-class="com.top_logic.base.MinimalService">
			<instance class="com.top_logic.base.MinimalService"
				my-option="42"
			>
			</instance>
		</config>

	</services>
</application>