<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1142216887529966979</id><updated>2011-04-22T00:03:58.000+01:00</updated><category term='exceptions'/><category term='TTS'/><category term='architecture'/><title type='text'>Statics AX</title><subtitle type='html'>Here is the place I wanted to invite all of you - to have a room to discuss AX technical side in large and small picutres, from the small tips to architectural changes.

As you see the name is choosen a little contrariwise to new branding.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://staticsax.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1142216887529966979/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://staticsax.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Michał Kupczyk</name><uri>http://www.blogger.com/profile/10982020721868032005</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1142216887529966979.post-5078140118015824960</id><published>2009-01-19T16:26:00.002Z</published><updated>2009-01-19T16:29:14.623Z</updated><title type='text'>Restore(ctrl-F5) and access control (AllowEdit) problem</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;Trivia:&lt;/div&gt; &lt;div&gt;It is usual programming pattern in AX that one overrides active() method on  the datasource to allow/disallow data entry on fields depending on values of any  fields in record.&lt;/div&gt; &lt;div&gt;It is also usual pattern to do similar thing overriding modified() method  on datasource fields.&lt;/div&gt; &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I would like to warn anyone using that pattern , that every screen in AX2009  SP0  will fail to behave as expected.&lt;/div&gt;&lt;div&gt; &lt;/div&gt; &lt;div&gt;Problem:&lt;/div&gt; &lt;div&gt;When you re-read the contents of the record on the form using F5 function  key, AX 2009 SP0 does call the datasource's active method, allowing you to  re-set access (   _DS.object(&lt;fieldnum&gt;).allowEdit(...)    )&lt;/fieldnum&gt;&lt;/div&gt; &lt;div&gt;but DOES NOT call *_DS.active()  method when one press Ctrl-F5.&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;Scenario of failure:&lt;/div&gt; &lt;div&gt;User arrives at the record, enters some data , is allowed access to the  other fields (based on previous input).&lt;/div&gt; &lt;div&gt;Now user presses Ctrl-F5, and all field values return to initially fetched,  but *_DS.active() method is not called, potentially making editable fields which  were not  available upon arrival to that record.   User happily changes the  data, and developer ask himself a question how did it happened.&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;BTW: _DS.cursorNotify() is not called either.&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;It would be good if someone would confirm this behaviour in AX4 and  AX2009SP1&lt;/div&gt; &lt;div&gt; &lt;/div&gt;&lt;div&gt;Solution:&lt;/div&gt; &lt;div&gt;For the time being there's small generic solution to this. You need to  modify the SysSetupFormRun.task() to make it call active() after Ctrl-F5 was  pressed. &lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;public int task(int _p1)&lt;br /&gt;{&lt;br /&gt;    #task&lt;br /&gt;    FormDataSource  formDataSource;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    int ret;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    if (_p1 == #taskFilter)&lt;br /&gt;    {&lt;br /&gt;        formDataSource =  this.objectSet();&lt;br /&gt;        if (formDataSource &amp;amp;&amp;amp;&lt;br /&gt;             formDataSource.queryRun() &amp;amp;&amp;amp;&lt;br /&gt;             formDataSource.queryRun().args() &amp;amp;&amp;amp;&lt;br /&gt;             !formDataSource.queryRun().args().caller())&lt;br /&gt;        {&lt;br /&gt;             formDataSource.queryRun().args().caller(this);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    ret = super(_p1);&lt;br /&gt;     //mku------------------------------------------------- to call the datasource's  active and allow re-setting the access----------&lt;br /&gt;    if(_p1 == 2839)&lt;br /&gt;     {&lt;br /&gt;        formDataSource = this.objectSet();&lt;br /&gt;         if(formDataSource)&lt;br /&gt;        {&lt;br /&gt;             formDataSource.active();&lt;br /&gt;        }&lt;br /&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'lucida grande';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    //mku ------------------------------------------------------  end   ------------------------------------------------------------&lt;br /&gt;    return  ret;&lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1142216887529966979-5078140118015824960?l=staticsax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://staticsax.blogspot.com/feeds/5078140118015824960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1142216887529966979&amp;postID=5078140118015824960&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1142216887529966979/posts/default/5078140118015824960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1142216887529966979/posts/default/5078140118015824960'/><link rel='alternate' type='text/html' href='http://staticsax.blogspot.com/2009/01/restorectrl-f5-and-access-control.html' title='Restore(ctrl-F5) and access control (AllowEdit) problem'/><author><name>Michał Kupczyk</name><uri>http://www.blogger.com/profile/10982020721868032005</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1142216887529966979.post-936217485857590798</id><published>2007-11-13T15:24:00.000Z</published><updated>2007-11-13T15:36:01.150Z</updated><title type='text'>New approach to Exceptions and Transactions handling</title><content type='html'>&lt;p&gt;As much as I like the transactional support in the core of the X++ language, as much I dislike the connection between exception handling and transactions.&lt;/p&gt; &lt;p&gt;In my opinion transaction should be part of the syntax and have syntax based scope.&lt;/p&gt;&lt;p&gt;Here is my suggestion to Microsoft:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1) ban the standalone ttsbegin and ttscommit&lt;/p&gt;&lt;p&gt;2) replace it with special try-catch syntax , as drafted below:&lt;/p&gt; &lt;p&gt;    try(new Connection())&lt;/p&gt; &lt;p&gt;    {                                       //implicit TTSbegin&lt;/p&gt;&lt;p&gt;       [do your stuff]&lt;br /&gt;&lt;/p&gt; &lt;p&gt;    }                                       //implicit TTScommit&lt;/p&gt; &lt;p&gt;    catch(Exception::Error)&lt;/p&gt; &lt;p&gt;    {                                       //implicit TTSabort.&lt;/p&gt;&lt;p&gt;        [oops]       &lt;br /&gt;&lt;/p&gt; &lt;p&gt;    }&lt;/p&gt; &lt;p&gt;Both Oracle and MSSQL2005 support the nested transactions, and that would be ideal opportunity to use it.&lt;/p&gt; &lt;p&gt;    conn = new Connection();&lt;/p&gt; &lt;p&gt;    try(conn)&lt;/p&gt; &lt;p&gt;    {                                               //implicit TTSbegin = BEGIN TRANS LEVEL1&lt;/p&gt; &lt;p&gt;             try(conn)&lt;/p&gt; &lt;p&gt;             {                                         //implicit TTSbegin = BEGIN TRANS LEVEL2&lt;/p&gt; &lt;p&gt;                          SalesFormLetterInvoice::post(SalesTable);&lt;/p&gt; &lt;p&gt;             }                                        //implicit TTScommit = COMMIT TRANS  LEVEL2&lt;/p&gt; &lt;p&gt;             catch(Exception::Error)&lt;/p&gt; &lt;p&gt;             {                                        //implicit TTSabort  = ROLLBACK TRANS LEVEL2&lt;/p&gt; &lt;p&gt;            if(..cannot compensate the error...)&lt;/p&gt; &lt;p&gt;                              throw Error(....)&lt;/p&gt; &lt;p&gt;                      else&lt;/p&gt; &lt;p&gt;                              [compensate the error.]&lt;/p&gt; &lt;p&gt;             }&lt;/p&gt; &lt;p&gt;    }                                           //implicit TTScommit =  COMMIT TRANS LEVEL1&lt;/p&gt; &lt;p&gt;    catch(Exception::Error)&lt;/p&gt; &lt;p&gt;    {                                        //implicit TTSabort = ROLLBACK TRANS LEVEL1&lt;/p&gt;&lt;p&gt;        [...]&lt;br /&gt;&lt;/p&gt; &lt;p&gt;    }&lt;/p&gt; &lt;p&gt;That way each try-catch block is eligible to work, not only this started outside of transaction, and when needed each of them can operate own (sub) transaction.&lt;/p&gt; &lt;p&gt;It is also much less demanding on the developer, preventing  improper or unbracketed use of ttsbegin and ttscommit. Normal (non db) try-catch bloack work as usually, allowing to catch X++ and CLR exceptions without unwanted rollbacks.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1142216887529966979-936217485857590798?l=staticsax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://staticsax.blogspot.com/feeds/936217485857590798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1142216887529966979&amp;postID=936217485857590798&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1142216887529966979/posts/default/936217485857590798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1142216887529966979/posts/default/936217485857590798'/><link rel='alternate' type='text/html' href='http://staticsax.blogspot.com/2007/11/as-much-as-i-like-transactional-support.html' title='New approach to Exceptions and Transactions handling'/><author><name>Michał Kupczyk</name><uri>http://www.blogger.com/profile/10982020721868032005</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1142216887529966979.post-4423295377265079165</id><published>2007-08-16T20:25:00.000+01:00</published><updated>2007-08-16T20:52:14.449+01:00</updated><title type='text'>Coordinated transactions using MSDTC</title><content type='html'>It would be very nice to be able to take advantage of distributed transactions.&lt;br /&gt;I saw a lot of intefaces written for AX and all of them were unnecessarily&lt;span style=""&gt; &lt;/span&gt;complicated to make sure no double processing takes place nor nothing is lost in the middle. All that complication can be avoided if we make use of Microsoft Distributed Transaction Coodinator. Easy said, but unfortunatelly Axapta does not provide such functionality 'out of box'. But not everything is lost, and with some luck it seems to be possible.&lt;br /&gt;MSDN says: In the first step application must call DtcGetTransactionManager from xoleHlp.dll. Piece of cake.&lt;br /&gt;Short script with DLL and DLLFunction and... Oops. "Called dll returned wrong value in BP register". A first obstacle is here: DtcGetTransactionManager is compiled with __cdecl directive, but AX calls it as it were __stdcall, thus stack is not cleaned, and BP mismatched.&lt;br /&gt;To pass this problem I wrote a xolehlp.dll wrapper, which has functions declared in the way AX has no problem to call it.&lt;br /&gt;Now I can call DtcGetTransactionManager and get the object with IID_TransactionDispenser interface. I can even start distributed transaction now.&lt;br /&gt;[to be continued]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1142216887529966979-4423295377265079165?l=staticsax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://staticsax.blogspot.com/feeds/4423295377265079165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1142216887529966979&amp;postID=4423295377265079165&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1142216887529966979/posts/default/4423295377265079165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1142216887529966979/posts/default/4423295377265079165'/><link rel='alternate' type='text/html' href='http://staticsax.blogspot.com/2007/08/coordinated-transactions-using-msdtc.html' title='Coordinated transactions using MSDTC'/><author><name>Michał Kupczyk</name><uri>http://www.blogger.com/profile/10982020721868032005</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1142216887529966979.post-1187664782273571310</id><published>2007-08-07T21:29:00.000+01:00</published><updated>2007-08-08T11:41:37.638+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TTS'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='exceptions'/><title type='text'>Real world processing: TTS and exceptions</title><content type='html'>Hi everyone,&lt;br /&gt;&lt;br /&gt;This is my first post in my blog, so I will start with something which bugs me right from the start of my work with Axapta.&lt;br /&gt;What I find the major flaw in the X++ design is the fact that when exception is thrown, the main, outermost transaction is automatically rolled back, and there is no support for nested transactions.   Automatic rollback is even advertised as a 'feature'.&lt;br /&gt;&lt;br /&gt;That simple thing is preventing code in AX from doing the real world mass processing, as any exception that will be generated (from the code you have no control over) will destroy all work done so far, even if in particular situation your code is perfectly capable of handling the problem. In fact it should be your, designer's decision about the scale of the problem. Your code has to decide about scale of the problem:  it's local, and there's special path to restore from that error- let's go with backup scenario. Outgrows foreseen options? Let's escalate.&lt;br /&gt;&lt;br /&gt;Auto-rollback executed as a part of exception is simply taking that decision away from your code and that substantially cripples the number of ways processing can be designed.&lt;br /&gt;&lt;br /&gt;Next time I will try to highlight possible solutions to that fundamental issue.&lt;br /&gt;Please do not hesitate to scribble me a comment with your view.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1142216887529966979-1187664782273571310?l=staticsax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://staticsax.blogspot.com/feeds/1187664782273571310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1142216887529966979&amp;postID=1187664782273571310&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1142216887529966979/posts/default/1187664782273571310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1142216887529966979/posts/default/1187664782273571310'/><link rel='alternate' type='text/html' href='http://staticsax.blogspot.com/2007/08/real-world-processing-tts-and.html' title='Real world processing: TTS and exceptions'/><author><name>Michał Kupczyk</name><uri>http://www.blogger.com/profile/10982020721868032005</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
