Edee.one · Dokumentace

Podpora zpracování konfigurace modulu

Možnosti

Pro účely zjednodušení načítání XML konfigurace je dostupná třída ConfigHelper. Ta obsahuje užitečné metody, které vám umožní:

vytvářet instance a class objekty z řetězce

získávat class objekty ze stringu a tyto classy bezpečně instanciovat (s obalením chyby do případné CpsException s návodným hlášením problému)

metody getClassByPath, getClassInPackageByElementName, getImplementationClassInPackage, instantiateClass

napopulovat data ze sitemapy přes POJO settery do existujících instancí

do existující instance nastaví property dle XML atributů nebo poduzlů

metody configureAccordingToAttributes, configureAccordingToSubElements, configure

inicializovat objekty Springovým způsobem

umožní zpracovat lifecycle callbacky jako InitializingBean, *Aware interfacy atd., autowiring by name z dodaného aplikačního kontextu

metody addUsedObject, initUsedObjects, isObjectRegisteredInUsedObjects

kombinovaně vytvářet instanci dle konfigurace a naplnit ji hodnotami

kombinované metody, které zároveň instanciují i konfigurují třídu podle sitemapy

metody getInstantiatedAndConfiguredClass, getInstantiatedAndConfiguredClassInPackage, getInstantiatedInstanceFromIndex, getInstantiatedAndConfiguredInstanceFromIndex

„indexové” metody nečtou informace o kompletních názvech tříd ze sitemap, ale hledají je podle klíčového slova v mapě - jeden index obsahuje jen třídy objektů Map, druhý index již hotové instance Map, v případě instancí se nevytváří kopie, ale použije se již hotový objekt, který se dále z dat sitemapy již nekonfiguruje

získat data z XML v jednoduché formě k dalšímu zpracování

převede konfigurační tagy do základních datových struktur

metody getChildrenAsMap, recursivelyAddSubElements

Vazba na lifecycle

Typicky probíhá načítání konfigurace ze sitemapy ještě před inicializací aplikačního kontextu - tj. instance objektů vznikají před tím, než máme k dispozici funkční aplikační kontext, ze kterého bychom mohli autowirovat dependence, načítat Resourcy atp.

Z toho důvodu je ConfigHelper navrhnut dvoufázově

  • v první fázi vám pomůže vytvořit instance objektů a napopulovat je daty ze sitemapy
  • a v druhé fázi, kdy už máte k dispozici funkční aplikační kontext zavoláte metodu initUsedObjects která provede Springovou inicializaci všech objektů
    • objekty se nestanou součástí aplikačního kontextu (jsou bezejmenné)
    • jen se provede jejich inicializace jako by v něm byly + autowiring byName.

Registrace objektů

Pokud vytváříte instance prostřednictvím metod ConfigHelperu (např. instantiateClass), nemusíte se o registraci instance starat - je do sady „usedObjects” zařazena automaticky. Pokud si vytváříte instance objektů bokem, je nutné je do seznamu zařadit explicitně voláním metody addUsedObject(s).

Resource populace

Jak již bylo uvedeno populace dat se děje ve chvíli, kdy ještě nemáme k dispozici funkční kontext. Nicméně objekty typu Resource vznikají pomocí tzv. ResourceLoaderu, kterým je právě zmíněný aplikační kontext - tj. vzniká nám tu cyklická dependence pro inicializaci.

Z toho důvodu vznikla třída zvaná DelegatingResource a odpovídající DelegatingResourceEditor, které umí zastupovat libovolný cílový Resource objekt.

Tj. vytvořené instance budou mít do fieldů typu Resource injektován objekt typu DelegatingResource, jehož inicializace finální inicializace se provede až ve chvíli, kdy je aplikační kontext k dispozici. Inicializace všech DelegatingResourců se děje ve chvíli volání metody initUsedObjects.

Příklady

java
public class JobMgrXmlConfigParser {        public JobMgrConfig parse(CpsModuleConfigSupport configSupport) {        final JobMgrConfig jobMgrConfig = new JobMgrConfig();        // prevede xml <asyncDisabled>false</asyncDisabled> do volani setAsyncDisabled(false)        configHelper.configureAccordingToSubElements(            getConfigRootElement(configSupport),            jobMgrConfig,            new String[] {"checks", "jobsConfigOverride"}        );        return jobMgrConfig;    }}

Složitější parser

java
public class XmlWorkflowConfigParser implements WorkflowConfigParser {        public WorkflowDefinition configureWorkflow(ConfigElement workflowElement) {        // naplni XML atributy do pojo field        WorkflowDefinition workflowDefinition = new WorkflowDefinition(workflowElement.getAttributeValue("id"));        configHelper.configureAccordingToAttributes(workflowElement,workflowDefinition,new String[]{"id","class"});        // dataloader plne dle XML konfigurace vcetne volby cilove tridy        ConfigElement dataLoaderElement = workflowElement.getChildElement("dataLoader");        if (dataLoaderElement!=null) {            // instance z <dataLoader class="com.fg.edee.workflow.integration.business.EdeePageWorkflowExternalDataLoader"/>            WorkflowExternalDataLoader dataLoader =                 (WorkflowExternalDataLoader) configHelper.getInstantiatedAndConfiguredClassInPackage(dataLoaderElement, null, true, true);                       workflowDefinition.setDataLoader(dataLoader);        }        // metadata - zpracovani dle fixni package, kde nazev tagu odpovida nazvu tridy        List<ConfigElement> metadataList = workflowElement.getChildElements();        for (ConfigElement metadataElement : metadataList) {            final String metadataName = metadataElement.getElementName();            // chceme pouze tagy dle konvence            if (metadataName.endsWith("Metadata")) {                // instance z konfigurace <pageMetadata pageSystemId="TARGET_PAGE" pageLang="cs"/>                final Class metadataClass = configHelper.getImplementationClassInPackage(metadataElement,                        "com.fg.edee.workflow.core.metadata");                final Object metadata = configHelper.instantiateClass(metadataClass, null);                configHelper.configureAccordingToAttributes(metadataElement, metadata, new String[]{"class"});                configHelper.configureAccordingToSubElements(metadataElement, metadata);                Assert.isInstanceOf(WorkflowMetadata.class,metadata);                workflowDefinition.setMetadata(metadata);            }        }        return workflowDefinition;    }}