Friday, October 28, 2011

Tutorial: AX 2012 - Invalid field access or Accessing unretrieved fields

Read the post all the way until the end - there's an ask for you guys there!

As many of you have already seen in the new AX 2012 release, there are a lot more tables present in the application, because we went through an exercise of normalizing the data model.
Another feature that was added at the same time was the Table Inheritance, allowing to sub-class tables and add additional fields reusing some of the behaviors of the base table.

All of it is great! The only problem with it is that it comes at a price - we now need to retrieve a lot more data and do a lot more joins between tables. So we tried to mitigate that by using field lists where possible and adding AdHoc query support, which basically eliminates unneccessary joins between tables from the hierarchy, if fields from these tables are not selected.

We have also implemented a number of things that allow us to clearly see if the field was selected in the user interface, the APIs needed for doing the same, as well as special handling for invalid field access.

This tutorial contains a form, which showcases the different aspects of data access in cases described above.
You can download the project with the tutorial from my SkyDrive.

On the first tab, we have the standard "On hand" view, which in the data model is a join between InventSum and InventDim, with group by clauses on selected fields, in this case, ItemId from InventSum and InventLocationId from InventDim, and aggregation on the AvailPhysical column.
As you can see from the screenshot below, the rest of the InventDim fields are shown as Unretrieved. So, naturally, accessing one of them from code, for example, should not be a legal operation.
To verify that statement, there are 2 buttons on the form, the Incorrect and the Correct was of accessing the field. Clicking on the first one simply tries to read the value out of the InventSiteId field, while the second one uses the API method TableBuffer.isFieldDataRetrieved() to first verify if the field can actually be accessed.

Note, that in the below example, both buttons will work, as in, there won't be any errors shown to the user. When accessing the field, even though it is not retrieved to the client, the value will be treated as the default value for that type, that is, an empty string.

In order to verify that we do not access fields in an invalid way like above, we have introduced a parameter, that will throw an exception if a field that was not retrieved is being accessed.

In order to enable this validation, you need to update the below shown parameter in the Server configuration form (Located under System administration \ Setup \ System). After changing the value (note, that it is per AOS) you need to restart the AOS for the changes to take effect.


Now, if you try to use the first button (under Incorrect) from above, you will get a stack trace, notifying you that the specified field was not retrieved.



We suggest that when testing your modifications in the application, you always have that flag enabled, so as to avoid unpleasant and hard-to-find bugs later on in the production environment.


On the second tab of the Tutorial form, the same type of information is presented, only this time the output is actually based on a new table inheritance structure I created.


The base table, GenericBall, contains 2 characteristics of any ball. SoccerBall is extending it and adding an additional characteristic (for the sake of the example, let's assume Brand is only relevant to soccer balls). This is basically a very simple table inheritance structure.

In the form, however, I am only selecting to view the Brand field from SoccerBall, not selecting the other 2 fields from the base table. As expected, they show up as Unretrieved in the user interface.
However, there is one difference in how Scsc tables are handled - and that is, they will always throw an exception when you try to access one of the unretrieved fields.
The two buttons above the grid demonstrate that. Try it out, enabling/disabling the server configuration parameter shown above.


That's pretty much all there's to it. Let me know if you have any questions.

Now, I have one thing to ask you all too.
We in the AX Test team have done our best to find invalid field access problems before the release, but if you find one using the approach above, please log it either through the standard Microsoft channels (partner/ MsConnect/ etc.), or as a comment directly under this blog post.

Thank you!

15 comments:

  1. Invalid Access in
    Form SysRecordLevelSecurityWizard
    Method getRoles Line 10

    Field role.Description is not selected but read.

    ReplyDelete
  2. Stack trace: Field 'BudgetType' in table 'BudgetTransactionLine' has not been explicitly selected.

    Stack trace

    (S)\Data Dictionary\Tables\BudgetTransactionLine\Methods\setTransactionCurrencyAmount - line 34

    ReplyDelete
  3. Stack trace: Field 'DataArea' in table 'CompanyInfo' has not been explicitly selected.

    Stack trace

    (C)\Data Dictionary\Tables\CompanyInfo\Methods\validateWrite - line 5
    (C)\Classes\FormDataSource\validateWrite
    (C)\Forms\smmOpportunityTable\Data Sources\DirPartyTable\Methods\validateWrite - line 7
    (C)\Classes\FormDataSource\leaveRecord
    (C)\Classes\FormRun\task
    (C)\Classes\SysSetupFormRun\task - line 20

    ReplyDelete
  4. \Classes\InventTransferUpdShip\shippedNowDimensions 30

    In lines 24 and 42 there is a fieldlist selected from an inventDim record and that record is passed into InventDim::findOrCreate which calls InventDim::findDim where nearly all fields are used.
    That leads to the "has not been explicitly selected" stacktrace.

    ReplyDelete
  5. Thanks. This last one I am not sure if we would be able to fix this one, as the expectation is that the default value will be used in the select statement in findDim, if the dimension is not filled in. But I'll log it and see what others think.

    ReplyDelete
  6. SalesTableListPage:

    Stack trace: Field 'CashDiscOnInvoice' in table 'TaxParameters' has not been explicitly selected.

    Stack trace

    (C)\Forms\SalesTable\Methods\init
    (C)\Classes\SysSetupFormRun\init - line 3
    (C)\Classes\FormFunctionButtonControl\Clicked

    ReplyDelete
  7. Hi,

    Stack trace: Field 'DataArea' in table 'CompanyInfo' has not been explicitly selected.

    Stack trace

    (C)\Data Dictionary\Tables\CompanyInfo\Methods\validateWrite - line 5


    Any solution for this?

    Thanks,
    Saju K.

    ReplyDelete
    Replies
    1. Hi Saju,

      Can you please describe the steps you took in the application to encounter the above error?

      Thanks

      Delete
    2. Hi Kashperuk,
      System is throwing stack race,When I am validating the any journal.Later I found at that system is trying to get the data from unretrived field.

      /*CompanyInfo/Isconsolidation() method
      result = [CompanyInfo::findDataAre(_dataArea).IsConsolidationCompany];*/

      May I know root cause of this error.
      How to resolve this.

      Contact id: sajukbrave@gmail.com

      Thanks,
      Saju K

      Delete
  8. To resolve this WTF error is necesary to delete all null values in this tables, remove it using SQL server.

    ReplyDelete
  9. Hi Vanya,

    I have come across an 'invalid field access' problem also.

    The scenario is... Trying to Post a two line intercompany General journal in a standard AX2012 R2 CU1.

    The "Error on invalid field access" is set to NO.
    The "IsConsolidationCompany" field has a configurationKey of LedgerAdvConsolidations - this is turned on.

    Looking at the code, Its a fairly standard select statement that field seems to be selected ok??

    I have noticed that if the value is NoYes::No then the error occurs, if its NoYes::Yes then code executes ok.

    Stack trace: Field 'IsConsolidationCompany' in table 'CompanyInfo' has not been explicitly selected.
    \Data Dictionary\Tables\CompanyInfo\Methods\isConsolidationCompany 17
    \Classes\LedgerJournalTransUpdate\checkConsolidation 16
    \Classes\LedgerJournalTransUpdate\checkWhenPost 25
    \Classes\LedgerJournalTransUpdateLedger\checkWhenPost 23
    \Classes\LedgerJournalCheckPost\postTrans 102
    \Classes\LedgerJournalCheckPost\postJournal 819
    \Classes\LedgerJournalCheckPost\run 153
    \Classes\LedgerJournalPost\post 140
    \Classes\LedgerJournalPost\main 26
    \Forms\LedgerJournalTransDaily\Designs\DesignList\PostJournal\Methods\Clicked 7

    Dayle P.

    ReplyDelete
  10. I'm getting a similar error. Any ideas what might be causing this? The error is occurring when I validate/post a AR or GL journal.

    Stack trace: Field 'IsConsolidationCompany' in table 'CompanyInfo' has not been explicitly selected.

    When I go to company info table, I see untretrieved in the field.

    Thanks!
    Tyler
    tbarron2@gmail.com

    ReplyDelete
  11. Hello Ivan,

    We encountered a similar issue trying to execute the GL\Periodic\Batch transfer for subledger journals ...

    Stack trace: Field 'createdDateTime' in table 'SourceDocumentHeader' has not been explicitly selected.

    All records in this table looks good in SQL and Table browser... I solved that by launching a full CIL compilation and an AOS restart.

    ReplyDelete

Please don't forget to leave your contact details if you expect a reply from me. Thank you