Header Image

Translate

donderdag 15 september 2016

Modules niet langer aanwezig in navigatiemenu

Een gebruiker melde dat het navigatiescherm niet meer toegang gaf tot de verschillende modulen. Favorieten waren nog wel zichtbaar een gebruikbaar, maar er kon niet langer een module geopend worden. Het onderste deel van de modulen was weg;


Ook de slider was weg, dus het menu kon niet ophoog getrokken worden. De >> was er dus ook niet. AUC verwijderd en ook onder het account van de gebruiker zijn usersettings weggegooid. Geen effect. Onder weergeven \ Navigatievensteropties kan je het menu 'opnieuw instellen' maar dat had geen effect.

Oorzaak was wel de usersettings. Maar zoals normale usersettings worden deze opgeslagen als je het venster sluit. Het menu sluit je als je Ax herstart, dus dan worden usersettings weer opgeslagen. Dit had ik opgelost door Ax af te sluiten bij deze gebruiker, en met de tablebrowser van de resourcenodes de syslastvalue tabel te openen en de volgende records te verwijderen bij de geburiker:
Mogelijk was de NavPaneOpionsButtons al voldoende.

Het is mij vaker opgevallen dat usersettings 'corrupt' lijken. Schermen die een vaste grootte hebben die ineens alleen een titelbalk hebben als voorbeeld. Niet alleen Ax 4.0, ook 2009 en 2012.

vrijdag 5 augustus 2016

Performance compileren productbuilder

In Ax 4.0 genereerd de productbuilder effectief een class welke middels code de bepaling zoals visueel is weergegeven in X++ vertaald. Bij complexe modellen kan het zijn de class hierdoor 1000-en methoden krijgt. Dit is onvoorkomenlijk, inherent aan de technische realisatie van deze functionaliteit.

Het kan echter voorkomen dat het compileren van een productmodel het systeem laat bevriezen. Een model dat 2975 methoden genereerd, gaf ik na 30 minuten de opdracht tot afbreken. De oorzaak zit hem in de compiler van deze funcionaliteit;


Effectief: ga alle methodes langs en verwijder deze. Bij 2975 methoden doet dit meer dan een seconde per methode, dus ongeveer 50 minuten. Dat is slechts één onderdeel van de stappen, maar de oorzaak waarom het lang duurt.

Dit heb ik vervangen door het volgende:

Effectief: verwijder de class en maak deze opnieuw aan met behoud van ID. Anders gaat het ID's gebruiken en dat is minder makkelijk als in dezelfde laag ook nog ontwikkeld wordt in een DEV omgeving en er ID conflicten gaan ontstaan.

code:
    TreeNode            methodNode;
    TreeNodeIterator    nodeIterator;
    UtilIdElements  utilIdElements; // INT561
    TreeNode tn;
    ;

    if (useClasses)
    {
        classBuild.classNode().AOTrestore();
        classBuild.classNode().AOTsave();

        // INT561
        // Drop & recreated with existing ID much more efficient then
        //  delete all subnodes (methods).
        utilIdElements.initValue();
        utilIdElements.Name = classBuild.classNode().name();
        utilIdElements.recordType = UtilElementType::Class;
        utilIdElements.Id = classbuild.classNode().iD();
        classBuild.classNode().AOTdelete();
        utilIdElements.insert();

        tn = xUtilIdElements::getNode(utilIdElements);
        if (tn)
        {
            tn.AOTcompile(1);
            tn.AOTsave();
        }
        classBuild = new classBuildConfigurator(utilIdElements.name, true);
        // INT561

        this.addSource2TreeSource(PBA::_pbaSourceArgs() + PBA::cr() + PBA::start() + PBA::cr() + PBA::tabSpace() + PBA::callSuper() + PBA::cr() + PBA::tabSpace() + PBA::PBAInitCall(useClasses) + PBA::cr());
Hierbij heb ik gebruik gemaakt van deze link:
 http://www.axaptapedia.com/ClassBuild_Class

woensdag 27 juli 2016

Applicatie lagen corrupt

Ax maakt gebruik van een mooi lagen-systeem, waarbij de basis applicatie in de SYS laag zit, oplossing van partners in onder andere de BUS, de VAR voor de value-added-reseller, CUS voor klant specifiek en USR voor de gebruikers. Om maar een paar te noemen, want met Ax 2012 komen er nog een paar bij. Nu is het normaal zo dat een ontwikkelaar in een bepaalde laag AX opstart en code daarin alleen maar in die laag komt. Maar soms doet Ax rare dingen. Zo liep ik tegen het probleem aan dat ik een methode niet kon verwijderen die ik net had aangemaakt. Ax beweerde dat deze in een andere laag zat. Als ik inlogde in die laag, dan was die methode er niet. Samengevat had ik het terug kunnen brengen tot dit:

Ik log in in de CUS laag:


Nieuw form, override de run:


Zoals je ziet aan de AddressCountryRegion, worden alle lagen getoond van een element. Form1 bestaat enkel in de CUS laag. Ik verwijder de RUN:

 De run zit in de VAR? Samengevat; ik krijg deze run er niet meer uit.

Diverse zaken geprobeerd. UAC file verwijderen, AOI file verwijderen, AOS herstart uiteraard andere terminal server, zelfs de nieuwste kernel van Ax 2009. 

Uiteindelijk heb ik de applicatie opnieuw opgebouwd. Dit deed ik in de volgende stappen in een TEST ogmeving:

1. Bepaal de lagen waarin code zit. In dit geval: CUS, VAP, VAR, BUS en SYP/SYS.
2. Op volgorde van USR tot de SYP (SYS/SYP dit zelf niet):
      a. Maak een project met alle elementen in de laag
      b. Exporteer het project, met behoud van ID's. _alles_; dus niet alleen die laag
      c. Stop de AOS, verwijder de AOI en AOD file uit de applicatie, start de AOS

Nu had ik per laag de elementen van die laag en een Ax omgeving met enkel de SYS/SYP laag.
TIP: zet nu een breakpoint in de Application.dbSynchornize:

Bij een grote test database is het nogal een zware operatie en het is zonde als applicatie nog niet af is. Een return true; werkt ook, maar als de Application class is aangepast in de laag dan wordt deze code ongedaan gemaakt. Zet variabele 'ok' op true en sleep de executiepointer naar de volgende regel (dus de super niet uitvoeren)

Vanaf het laatste laag-project dat gemaakt is, per laag-project:
3. Importeer met behoud van ID's de elementen en verwijderen elementen. Soms zijn meerdere keren import nodig; een EDT verwijst naar een tabel en dezelfde tabel naar een EDT, krijg je bij een eerste import compilatie problemen.
4. Compileer het project en controleer op compilatie fouten.


Het kan zo zijn (in mijn geval) dat de partner code in de VAR laag had gebasseerd op code in de CUS laag. Dus bij de import in de VAR kreeg ik dus fouten en moest elementen uit de CUS in de VAR laag overzetten. Bij database tabellen/velden is dit lastig vanwege databehoud, dus ik had besloten delen in de CUS laag al op te leveren voordat de VAR laag compileerde. Het was bij mij zelfs zo, dat de BUS laag enkele marco's uit de SYP laag had verwijderd die in de VAR laag weeg waren toegevoegd. Even logisch verstand gebruiken bij deze gevallen.

Bij de 2e import van de CUS laag liep ik nog tegen een melding aan:
 Bezig met importeren van class INTEditLinesView met ID 41375. ID is al geactiveerd door class INTEditLinesDialog. In de AOT is er inderdaad een INTEditLinesDialog met ID 41375, de XPO:

Vanwege onduidelijke redenen is er een verschil in de export tussen deze waarden. Na correctie met notepad in de xpo ging het wel goed.

Na de laatste laag een volledige compilatie en synchronisatie. Omdat de ID's van de dataelementen hetzelfde zijn, zou je nu een database restore kunnen doen van Live of Dev om de applicatie te testen. Er zou geen dataverlies mogen optreden, wat uiteraard onwenselijk is.

Nu was het wel mogelijk methoden weer te verwijderen.

Ax 2009 performance bij opbouwen formulier met grid

Performance is nooit te goed en als je iets snel moet doen is het systeem altijd wel te traag. Maar soms is het ook raar. Normaal kan je performance terug leiden tot een index, tot een display/edit methode of veel client/server communicatie. Maar soms ook niet.

Bij een Ax 2009 gebruiker waren al diverse reputabele partijen geweest vanwege performance problemen die al diverse punten hebben aangehaald. Voornamelijk netwerk topologie punten. Maar alsnog geen soelaas.

Situatie schets; de servers worden gehost in een datacenter. Gebruikers hebben een thin client die een remote desktop verbinding maken met een terminal server (TS) in dit datacenter. In dit datacenter staat de Ax AOS met op diezelfde server de database. Zelf als externe Ax consultant had ik via RDP toegang tot de servers. Aangezien de TS nog wat extra software had voor de eindgebruikers het melden even waard. De TS zelf is Windows 2012 R2, de server zelf is Windows 2008. 

Eigenlijk kwam het terug tot dit; een standaard tabel, de InventJournalTrans op een schoon formulier met enkel een tab en een grid als admin ging de performance dramatisch onderuit als alle velden op de grid werden opgenomen. Als je het opende:

Her duurde tot wel 30 seconden voordat het scherm verder werd opgebouwd. En dan nog; het scherm werd zichtbaar opgebouwd:


Het klikken tussen de records zat merkbaar een vertraging in: duurde soms enkele seconden voordat een regel gearceerd werd. Eigenschappen van het form:
 - Kaal formulier met één tab, één grid, > 40 velden
 - Geen edit/display methoden enkel velden dit in de tabel zitten. 
 - Openen vanuit AOT, geen rechten, geen methoden geïmplementeerd(init, run, active, executeQuery, linkactive), eigen queries, sortering or andere properies van de componenten.Zelfs niet eens de moeite genomen de tab een label te geven.
Via de tabel-browser van Ax was de tabel met al zijn velden wel snel benaderbaar.

Bij minder velden (< 20) ging het goed en snel. De situatie is echter, dat na minimaliseren en restoren van het form de performance ineens goed was bij meer dan 20 velden. Deze code opgenomen onder een knop:
    WinAPI::showWindow(element.hWnd(), 6); // 6 = minimize
    WinAPI::showWindow(element.hWnd(), 9); // 9 = restore
Het scherm knippert even, maar de performance is uitstekend. Het opstarten van het formulier is echter nog steeds traag.

Het feit dat de schermen snel zijn na een minimize/restore  geeft mij aan dat het probleem niet in Ax of in de netwerk verbinding zit. Maar waarom is de tabel-browser dan wel snel? Deze velden worden dynamics toegevoegd...Uiteindelijk kwam ik er achter dat verborgen velden hetzelfde effect had:


In de run:


De refreshForm:


Het direct zichtbaar maken in de run (de na de super in de run meteen refreshForm aanroepen) maakte het systeem al wel wat sneller, maar het selecteren van andere records bleef traag.

Een aantal dingen die ik geprobeerd heb:
- Kernel AOS/client bijwerken (laatste versie op dit moment: 5.0.1600.3696)
- Al het maatwerk in de basis zoals SysSetupFormRun, Info, Application etc. die eventueel problemen zou kunnen veroorzaken verwijderen (echt de laag zelf verwijderen).
- Diverse calls zoals yield(), winapi calls die ik kon vinden die mogelijk messages voor een form afhandelde / opschoonde. 
- Applicatie zaken (verwijderen UAC, verwijderen *.I, met herstart AOS uiteraard)

Andere bevindingen;
- Vanaf de TS was het sneller dan rechtstreeks op de server. Dit kan verklaard worden doordat resources op de server beperkter zijn (SQL server wil nogal geheugen claimen). Het scherm opende wel sneller, maar het selecteren van andere records bleef traag tot het scherm geminimaliseerd / gerestored is.
-  Het maakt niet uit voor de server: Windows 2012 R2 met client applicaties en de Ax client die verbinding maakt met een Windows 2008 AOS+DB heeft dezelfde eigenschap als alles op één Windows 2008 machine (client en AOS en DB)
- Aangezien het minimaliseren / restoren van het Form al het euvel verhelpt en de kaalheid van het form, is het mijn insteek dat het niet in de applicatie van Ax zit maar mogelijk in de Ax client zelf icm windows al-dan-niet icm een derde applicatie.

Uiteindelijk heb ik deze functionaliteit meegenomen in de applicatie;





Dus alleen velden dit zicthbaar zijn aan het eind van de init -> verbergen


Dus alles dat inzichtbaar is gemaakt, weer zichtbaar maken. Een minimize/restore kan ook, zie uitgecommentarieerde code. Maar dat flikkert wel het scherm dus.

De timeout in de run:


Dit is geen oplossing voor het probleem, maar meer een workaround voor de symptomen. Tot zover... mocht iemand zoeken naar performance problemen, kan je hier misschien wat mee. Als iemand anders nog ideeën of tips heeft,  dan hoor ik dat ook graag.