neděle 23. srpna 2009

EP: X++ Web UI Framework končí

Ve starších verzích AX se webové uživatelské rozhraní vytváří v AOT pomocí WebForms apod. V AX2009 se objevil nový přístup a to vytváření komponent v ASP.NET (a mapování na DataSets v AOT). Tento nový přístup má být v nové verzi AX jediný možný - a bude tedy třeba zmigrovat existující implementace postavené na původním frameworku. Převzato z: Dilip's blog

The records buffer is NULL

Tento příspěvek dokumentuje jedno ne zrovna intuitivní chování Axapty. Vezměme následující jednoduchou třídu:
class Test
{
    public server static void main(Args args)
    {
        Test::recordOnClient();
    }

    public client static InventTable recordOnClient()
    {
        InventTable inventTable;
        select firstOnly forUpdate inventTable;
        return inventTable;
    }
}
Tento kód (respektive pokus o vrácení hodnoty z metody recordOnClient()) vyhodí run-time výjimku Error executing code: The record buffer is NULL. Testováno v AX2009, AX3 jednoduše spadne (AX4 nemám po ruce). Právě vytvořením kódu sestřelujícího Axaptu 3 toto chování jeden můj kolega objevil. Zajímavé je, že se tak děje pouze při volání client metody ze serveru a pokud metoda vrací buffer vybraný pro update. Všechny ostatní scénáře skončily bez chyby. Doufal jsem, že se mi na základě chybové hlášky podaří najít více informací, ale nebyl jsem úspěšný. Zřejmě se to moc často vytvořit nepovede. Doplnění: Pokud je na bufferu volán insert(), dostane buffer příznak forUpdate. Výše popsané chování tedy platí i v takovém případě.

Convergence 2009 Europe

Convergence je oficiální akce Microsoftu na téma Dynamics. Původně plánovaná celoevropská konference byla rozdělena do čtyř měst takto: 27.10.2009 Londýn 29.10.2009 Vídeň 03.11.2009 Frankfurt 05.11.2009 Rotterdam Registrace začíná 1.9.2009, cena pro zákazníky je 150€, pro partnery dvojnásobek. Záznamy z akce pak budou přístupné nejen účastníkům, ale i všem partnerům a zákazníkům s BREP (Business Ready Enhancement Plan). Oficiální stránky: Convergence 2009 Europe Další info, vč. Breakout Sessions (PPT): Partner Update 20.8.2009

sobota 22. srpna 2009

Iterator vs. Enumerator

Pro procházení kolekcí lze v Axaptě využít dvě třídy - Iterator a Enumerator. Respektive, pro každou kolekci existuje specializovaný iterátor a enumerátor, např. SetIterator a SetEnumerator. Použití iterátoru vypadá takto:
SetIterator iterator = new SetIterator(set);
while (iterator.more())
{
    info(iterator.value());
    iterator.next();
}
…a enumerátoru takto:
SetEnumerator enumerator = set.getEnumerator();

while (enumerator.moveNext())
{
    info(enumerator.current());
}
Je best practice používat enumerátor namísto iterátoru. O tomto doporučení vím již dlouho, ale až tento týden jsem se dozvěděl jeden zásadní rozdíl: volání iterátoru totiž selže, pokud jsou iterátor a iterovaná kolekce na jiné vrstvě (ve smyslu klient/server). V takovém případě je vyhozena run-time výjimka s tím, že objekt iterátoru není inicializován. Enumerator s touto situací počítá a vznikne na stejné vrstvě jako kolekce. Procházení všech prvků kolekce umístěné na jiné vrstvě zas může být výkonnostní problém, ale to už je jiná kapitola… MSDN: ListEnumerator MSDN: ListIterator MSDN: MapEnumerator MSDN: MapIterator MSDN: SetEnumerator MSDN: SetIterator

čtvrtek 20. srpna 2009

AxDecisions 2009

Virtuální konference jsou čím dál oblíbenější - je to zejména daleko lacinější varianta než "fyzická" konference. AX Decision 2009 je další taková virtuální konference a jak název naznačuje, půjde o Dynamics AX. Bude se konat 14.10.2009 - více informací je k dispozici na webu AxDecisions. Z čistě vývojářského hlediska není zveřejněný program nijak lákavý, ale pro přehled o trendech a možných přístupech by mohl posloužit dobře. Za tu cenu… (je zdarma) PS: Koho zajímá, jaktože je konference zdarma, doporučuji standardní postup: podívejte se, jak je prezentována potenciálním sponzorům. :-)

AxAssist

AxAssist je bezpochyby jeden z nejužitečnějších nástrojů, které jsou pro vývoj v Dynamics AX k dispozici. Není sice zdarma, ale přináší mnoho skvělých funkcí za rozumné peníze. Navíc je k dispozici třicetidenní zkušební verze, takže každý má možnost si AxAssist důkladně osahat. Hned na úvod odkáži na oficiální stránky (AxAssist.com), protože je tam většina funkcí popsána a nechybí flashová videa, která přiblíží chování AxAssistu asi lépe než cokoli jiného. Mým cílem tedy není popsat všechna nastavení atd., spíše rychle prolétnout všechny funkce a podívat se na pár praktických zkušeností. Jen jeden obrázek (z AX3) pro představu, o čem je řeč: Doplňování kódu Nejviditelnější a nejdůležitější shopností je doplňování kódu při psaní. MorphX sice dokáže nabídnout seznam metod objektu nebo polí tabulky a dokonce i seznam tříd či datových typů (pod různými záhadnými klávesovými zkratkami), ale AxAssist to dělá řádově lépe. Nabízí datové typy při deklaraci, proměnné vhodného datového typu v přiřazení nebo volání parametrické metody, nabízí i makra atd. atd. Navíc je toto chování konfigurovatelné, např. lze definovat, po kolika zapsaných znacích se má nabídka zobrazit. Další příbuzná funkce je Acronyms, tedy zkratky. Slouží k nabízení datových typů a principem je „skákání po hrbech velblouda“, abych tak odkázal na velbloudí notaci. :-) Zkrátka nabídnou se ty typy, v nichž jsou v daném pořadí obsažena zadaná velká písmena. Například pro LJTI se (v AX3) nabídne LedgerJournalTrans_InventTrans (je-li povolena volba Extended Acronyms), LedgerJournalTransImport a LedgerJournalTypeId. Rozdíl v počtu znaků, které je nutné napsat, je evidentní. Užitečná funkce je také možnost zadání ignorovaných prefixů. Pokud vaše firma například prefixuje objekty trojicí znaků XYZ, můžete nechat prefix XYZ ignorovat a typ XYZOrderId se nabídne po prostém zadání OI. Lze zadat i více prefixů, oddělených čárkou. Po nastavení prefixu budete pravděpodobně muset restartovat AX klienta. Do nabídek lze přidat vlastní kusy kódu, tedy různé často zapisované konstrukce, komentáře dle firemních pravidel atd. Text nemusí být úplně statický, výsledná podoba je zkonstruována při spuštění AxAssist. Lze tedy např. předpřipravit komentář s vyplněným jménem přihlášeného uživatele apod. A ještě jedna drobnost: rozbalovací nabídka také zobrazuje ToolTip pro aktuálně vybraný prvek (a v něm např. typ proměnné, předka typu, label apod.). Způsob vytváření těchto ToolTipů lze také libovolně modifikovat a přidávat tak další informace, měnit formátování atd. Tlačítka Ve výchozím nastavení AxAssist také přibyde šest tlačítek na hlavní lištu a do AOT a tři do lišty editoru kódu. Z první skupiny zaujme třeba možnost otevření datového typu pole v AOT (což lze volat i z definice datového zdroje formuláře apod.), v editoru je zásadní skvěle fungující Open in AOT (lze použít z definice i použití libovolné proměnné a její typ je otevřen v samostatném AOT okně). Některá tlačítka mě příliš nezaujala z prostého důvodu, že všude používám Tabax a mám je tam (a třeba TableBrowser je v Tabaxu lepší ;)). Funkce tlačítek může být měněna, mohou být přidávana další atd. Vyžaduje to drobné zásahy do kódu, ale je to popsáno na webu AxAssist a není na tom nic složitého. Další změny v IDE Do IDE dále přibylo:
  • dolní lišta v AOT – zobrazuje definici (třídy, metody) nebo label (tabulky, formuláře, pole, EDT...)
  • rozbalovací seznam metod v editoru
  • panel v editoru (vlevo dole) – zobrazuje informaci o vybrané proměnné, včetně např. všech hodnot výčtového typu. I toto lze velmi snadno rozšiřovat a často se to hodí. Zobrazené hodnoty lze i kopírovat, typicky odtud kopíruji název datového typu.
Klávesové zkratky AxAssist umožňuje definovat vlastní klávesové zkratky a to zvlášť pro editor a zvlášť pro zbytek IDE. Funkce, pro kterou chcete definovat klávesovou zkratku, musí být definována v třídách AxAssist. Defaultně tam jsou funkce pro jednotlivá tlačítka a Code reformatter (viz dále). Opět odkáži na dokumentaci na webu, kde je postup přidávání dalších funkcí dobře popsán. Code reformatter Cílem Code reformatteru je zpřehlednit existující kód pomocí jeho rozdělení na více řádek a odsazení. Zřejmě se tak děje jen pro parametry metody a deklarace proměnných, což je pro mě trochu zklamání, ale budiž. Způsob odsazování lze nakonfigurovat v nastavení (čtvrtá záložka, „ReFormatter“). Spouštění reformatteru je poněkud zvláštní. Spouštěcí funkce je implementována a lze k ní přiřadit klávesovou zkratku nebo tlačítko, ale defaultně to provedeno není – tudíž ve výchozím nastavení není možné reformatter spustit. Nicméně stačí přidat čtvrté tlačítko do editoru a bude automaticky volat Code reformatter. Instalace, spuštění, synchronizace AxAssist se distribuuje jako jeden .exe soubor obsahující instalátor. Ten mj. uloží do instalačního adresáře soubor AxAssist.xpo, který musíte naimportovat do AX. Dále je třeba udělat ještě drobný zásah do třídy EditorScripts (viz web), jinak vám AxAssist vynadá, že instalace není dokončena. Po instalaci se ale AxAssist ještě nijak nespouští - je třeba spustit formulář DEV_AxAssistForm. Může být spouštěn buď automaticky po startu (zásah do Info.startupPost(), resp. workspaceWindowCreated()), nebo ručně (k tomu je ideální Tabax - stačí přidat ikonku Display_DEV_AxAssistForm.bmp do AX adresáře \Share\Include\Tabax\Plugs). Při startu provádí AxAssist synchronizaci, kdy si ukládá informace o typech a tyto informace pak využívá při konstrukci nabídek. Synchronizace trvá cca půl minuty, což může pochopitelně zdržovat, chcete-li se např. jen rychle na něco podívat. V závislosti na osobních preferencích pak můžete spuštět AxAssist ručně, automaticky s případným přeskočením startu AxAssist (typicky stiskem Shift nebo Ctrl; toto musí výslovně implementováno ve spouštěcí logice), používat různé konfigurace (např. konfiguraci bez AxAssist pro AxPath) atd. Cena Aktuální ceník naleznete zde. Rád bych upozornil na dvě věci:
  1. Jste-li firma, nemůžete zakoupit Single Developer License, vždy musíte koupit zakoupit Company License
  2. AxAssist se pořizuje pro každou verzi AX zvlášť, ale zároveň je hned zmíněna možnost slev (s čímž ovšem zkušenost nemám)
Support Při nasazování na projekt v AX3 jsem narazil na určité nejasnosti a výkonnostní problémy (v předchozí verzi AxAssist, nyní je již problém vyřešen) a vyzkoušel jsem tedy i support. Reakce byla rychlá a přínosná a pomohla i v přípravě tohoto příspěvku. Takže díky, Alexi! Závěr AxAssist umožňuje pracovat významně rychleji a lépe se soustředit na smysl implementace, protože není třeba přerušovat psaní kódu hledáním typu v AOT a podobně. Je až s podivem, kolik Dynamics AX vývojářů o AxAssist nikdy ani neslyšelo. Snad se to teď v české kotlině trochu změní… :-)

neděle 2. srpna 2009

Vyhledávání

Vyhledávání v kódu nebo v AOT je velice častá činnost. Hledáme použití proměnné, modelový kus kódu, objekty určitých vlastností atd. Přesto řada lidí neovládá některé užitečné funkce, které pro to Axapta nabízí. A právě na ty se nyní podíváme. Spustit formulář pro vyhledávání v AOT jistě dokáže každý, ale tento formulář umí podstatně více než jen vyhledat zadaný řetězec. Přímo na formuláři jsou další pole pro upřesnění kritérií (ačkoli pro některé jsem dosud nenašel smysluplné využití) a dokonce možnost zapsat vlastní funkci, která se spustí pro každý TreeNode (jaké má mít metoda parametry se dočtete v nápovědě k formuláři). Co už není tak očividné je možnost zadat regulární výraz do vyhledávacích polí. Syntaxe odpovídá metodě match() a je u ní zdokumentovaná. Takže např. následující příklad hledá přiřazení do proměnné i - jinak řečeno, proměnnou i následovanou libovolným počtem mezer a znakem =. Dohromady i: *=. Obdobně lze hledat třeba metody, jejichž název odpovídá určitému regulárnímu výrazu (např. <check.*sales pro metody začínající check a pak kdekoli obsahující sales). V tomto případě pochopitelně umístíme regulární výraz do pole (Nazváno) Named. Regulární výrazy lze využít i při vyhledávání labelů (což je mimochodem funkce k nezaplacení) a také v editoru kódu. V editoru hlavně pozor na to, že se vyhledává od pozice kurzoru do konce, to je dost matoucí. A kupodivu hledání v AOT a hledání v editoru pracuje jinak např. s koncem řádku… Při hledání v AOT lze využít ještě jednu zajímavou funkci a to vyhledávání ve vlastnostech. Nejprv je nutné přepnout volbu Hledat (Search) na Vše (All nodes) - tím se zobrazí další záložka: Vlastnosti (Properties). Na ní si pak najdeme patřičné vlastnosti, označíme jako Selected a zadáme hodnotu. Ta má opět hodnotu regulárního výrazu. Může to vypadat třeba takto:

Reflexe - AOT

Třída TreeNode představuje uzel AOT, tedy objekty, metody, pole ale i "adresáře" jako třeba Forms. S její pomocí pak můžeme provádět akce, na jaké jsme zvyklí při ruční práci s AOT. Například tento kód vytvoří novou třídu a spustí ji:
#AOT
TreeNode nodeClasses = TreeNode::findNode(#ClassesPath);
TreeNode nodeClass;
TreeNode nodeMethod;
;

nodeClass = nodeClasses.AOTadd('NovaTrida');
nodeMethod = nodeClass.AOTadd('main');
nodeMethod.AOTsetSource(
   'public static void main(Args _args){;info("Bezi");}', true);
nodeClass.AOTsave();
nodeClass.AOTcompile();
nodeClass.AOTrun();
Příklad asi nepotřebuje mnoho komentáře. Makro #AOT obsahuje cesty k různým prvkům (nebo části cest, jako třeba '\%1\\Fields\\\%2'). Skupinu všech tříd, novou třídu i její metodu reprezentuje třída TreeNode. Díky této funkcionalitě lze například snadno vytvářet generátory kódu apod. Další užitečná věc je práce s vlastnostmi (Properties). Vlastnost vyhledáme podle jejího názvu a v tom nám pomůže další makro - #Properties.
#AOT
#Properties
TreeNode nodeBOM = TreeNode::findNode(#TablesPath + #AOTDelimiter + tableStr(BOM));
;
info(nodeBOM.AOTgetProperty(#PropertyCachelookup));
Obdobně lze vlastnosti i nastavovat:
tableNode.AOTsetProperty(
   #PropertyFormRef,
   menuitemDisplayStr(Form1));
tableNode.AOTsave();
Často je také potřeba procházet iterovat přes větší množství AOT uzlů. K tomu se hodí tyto třídy:
  • TreeNode - metody AOTfindChild(), AOTfirstChild(), AOTnextSibling() atd.
  • TreeNodeIterator - prochází přímé potomky. Lze získat voláním AOTiterator() na TreeNode.
  • TreeNodeTraverser - prochází potomky včetně nepřímých.
  • TreeNodeTraverserSource - potomek TreeNodeTraverser; prochází jen uzly obsahující zdrojový kód.
Některé zajímavé metody pro práci s uzly AOT naleznete ve tříde SysTreeNode. Je jasné, že TreeNode obsahuje funkcí daleko více, ale pro základní představu to stad stačí.