Sunday, May 25, 2014

AX 2012 R2 to AX 2012 R3 Upgrade

The latest upgrade guide is very well written and covers the complete upgrade process.  However, I am listing down an overview of the upgrade process and things to remember before starting the upgrade. I hope, this shall enable you to achieve a smooth upgrade.

Things to remember before starting the R2 to R3 Upgrade 

  1. Before installing AX 2012 R3, All R2 components needs to be uninstalled in the environment in which the upgrade is planned.
  2. During the code & data upgrade process, Make sure that you Mark all the steps in the code/data upgrade checklist before you restart AX client/AOS as complete even though it is not yet completed else a blank(empty) start up application workspace will be displayed and no modules will be listed when you re-open the AX client.  
  3. Always compile the application using command “axbuild xppcompileall” from the command prompt whenever compilation is required during Code/data upgrade process.
  4. Please make sure that the below steps are followed else during the data upgrade, the pre-sync and post-sync jobs might struck in ‘Ready’ status and may not be executed.

a.     The user account logging into the Dynamics AX client to run the checklist is the Dynamics AX admin account and NOT just a member of the system administrator security role.
b.     Check the userinfo table in SQL: select * from userinfo where ID = 'admin'  to make sure a record for the "admin" ID has  a valid SID, networkdomain, and networkalias for each partition in the environment. 
c.     Check the batch form directly in the client by going to System Administration | Batch Jobs | Batch Jobs and check the Createdby fields and if the DataUpdate job has already scheduled as an account other than admin, you need to start the upgrade over by logging in as the admin account or you may be able to change the records in the batch and batchjob tables to be the admin account. 
d.     Remove any records in the SysServerSessions table that are not valid in this environment, you should do this while the AOS servers are stopped and make sure to have a SQL backup first.
e.     Check the setup under system administration | setup | system | Server configuration
f.      Delete any AOS instances here that are not valid in this environment.
g.     Make sure the remaining AOS instance is marked “is batch server”
h.     Make sure batch server schedule is setup with proper start/end time i.e. Start time 12:00:00 am end time 11:59:59, so there are no gaps in the scheduled time.
i.      Make sure that the remaining valid AOS server that is also marked for batch has the blank batch group and data Update batch group assigned to it.
j.      Change the status of any other batch jobs from waiting to withhold so they don't interfere with the Data Upgrade batch jobs.  To change the status highlight the jobs you want to change and select Functions | Change Status and choose Withhold
k.     Check for any previously running batch jobs that are stuck in a status of Executing.  You may need to change the status to cancelled or remove the Job from the Batch and Batchjob table from the SQL backup.

Upgrade Steps

Step 1. Synchronize, Compile and Generate CIL on the AX 2012 R2 application.
Step 2. Stop AOS & then back up model and business data databases.

Step 3. Restore the model and business data databases in a new environment.

Step 4. Start the AX 2012 R3 installation setup on a new environment.

Step 5. Select only the databases component.

Step 6. Select configure existing databases.

Step 7. In this step, Assign the R2 database and make sure that the Baseline database name field is left blank during this procedure.

Step 8. On the Select additional models page, select the Foundation model, Foundation Upgrade model, and any other models that you require for your deployment. Select the Foundation Labels model only if you are using country/region-specific features.
After this step, the system creates a new baseline database which contains upgraded AX 2012 R3 models in the SYS, GLS, FPK, and SLN layers and Non-upgraded customer models in the ISV, VAR, CUS, and USR layers.

Step 9. Now install all other required AX components.

Step 10. Now, assign the database and upgraded baseline database in this step.

Step 11. Once, the installation is completed then compile the whole application using the command “axbuild xppcompileall” from the command prompt. This compiled the whole application for me in just 30 to 40 minutes.

Step 12. Now restart AOS and proceed with the code upgrade & data upgrade checklists. Follow the code upgrade document on the complete details. 

Move objects from one layer to another in AX 2012 by retaining object ids

Hi Folks,

In AX 2009, We had an option of importing the new objects with ids using xpo from one layer to another. However, In AX 2012, The object ids are installation specific and we do not have an option to import them with object ids and this may affect in losing the data. The work around steps to move objects from one layer to another and still retain the old objects is as below:

Step 1. Create a new model and create a CUS layer project in this new model.

Step 2. Move all the CUS layer objects into this new model and export the project as an xpo.

Step 3. Export the required languages ald files from the label files created in CUS layer by navigating to AOT-> “Label Files” -> Languages

Step 4. Stop AOS.

Step 5. Backup model and business data dbs.

Step 6. Uninstall all the models in CUS layer and then start the AOS.

Step 7. Synchronize the database from the AOT. This will delete the data but we will retrieve it later.

Step 8. Create a new model in VAR layer then import the xpo from the xpo backup taken in step 2.

Step 9. Import the ald files from Step 3 into  the new model by navigating to AOT-> “Label Files”.( Right-click on the Label file node and use option “Create from File).

Step 10. Stop AOS and export this new model.

Step 11. Restore the model and business data databases that was backed up in step 5.

Step 12. Import the new model from step 10,  Start the AOS and then Synchronize Data dictionary.
 This restores the Id’s of all the new objects. So no data will be lost.

Step 13. Stop AOS, Uninstall all the models in CUS layer and then start the AOS.

Step 14. Synchronize and compile the application.           

Sunday, October 28, 2012

Get Active workflow configuration

Hi Folks,

The below code snippet would help you to get an active workflow configuration in Ax 2009 for a workflow template.

WorkflowConfigurationTable  workflowConfigurationTable;
    select firstonly workflowConfigurationTable
                                                where   workflowConfigurationTable.TemplateName   ==         &&                                                  workflowConfigurationTable.Enabled              == NoYes::Yes     &&                                                    workflowConfigurationTable.Type                 == WorkflowConfigurationType::Definition  &&
                                                        workflowConfigurationTable.DefaultConfiguration == NoYes::Yes;

Happy DAXing............

Get fields set in the workflow configuration conditions

Hi Folks,

I have been busy with my project for sometime and so couldn't post anything on my blog. I have got an interesting post for today.

 i.e., The below code snippet will help you to get the fields or parm methods which is set in the query condition of Workflow configuration in AX 2009. I hope this would work good in AX 2012 as well.

    WorkFlowElementTable    elementTable;
    WorkflowStepTable       workflowStepTable;
    ExpressionTable         expressionTable;
    XmlTextReader           xmlTextReader ;
    str                     attributeName, attributeValue;
    Map                     parmMethodMap;
    Map                     fieldsMap;
    int                     delimiterPosition;
    TableName               tableName;
    FieldName               fieldName;
    parmMethodMap = new Map(Types::String, Types::String); // Stores the names of parm methods used in the conditions of a workflow configuratoion
    fieldsMap     = new Map(Types::String, Types::String); // Stores the names of parm methods used in the conditions of a workflow configuratoion    while select ExpressionId, ExpressionDefinition from expressionTable join ElementId, ExecuteStepId from workflowStepTable
                                                                         join ConfigurationId from elementTable
                                                                        where elementTable.ConfigurationId == _configId// Pass an active configuration id
                                                                           && workflowStepTable.ElementId  == elementTable.ElementId
                                                                           && expressionTable.ExpressionId == workFlowStepTable.ExecuteStepId
        xmlTextReader = XmlTextReader::newXml(expressionTable.ExpressionDefinition, true) ;

            if (xmlTextReader.NodeType() == XmlNodeType::Element)
                while (xmlTextReader.MoveToNextAttribute()) // Read the attributes.                {
                    attributeName   = xmlTextReader.Name();
                    attributeValue  = xmlTextReader.Value();
                    if (attributeName == #Property)
                        delimiterPosition = strfind(attributeValue, #Delimiter, 1, strlen(attributeValue));
                        tableName = substr(attributeValue, 1, delimiterPosition-1);
                        fieldName = substr(attributeValue, delimiterPosition+1, strlen(attributeValue)-strlen(tableName)-1);
                        delimiterPosition = strfind(fieldName, #Delimiter, 1, strlen(fieldName));
                        if (delimiterPosition)
                            tableName = substr(fieldName, 1, delimiterPosition-1);
                            fieldName = substr(fieldName, delimiterPosition+1, strlen(fieldName)-strlen(tableName)-1);
                        if (substr(fieldname, 1, strlen(#ParmPrefix)) == #ParmPrefix)
                            parmMethodMap.insert(fieldName, tableName);
                            fieldsMap.insert(fieldName, tableName);

You can modify the above code as well to get the expressions and values used in the workflow configuration conditions as well.

Happy DAXing............... :)

Thursday, June 28, 2012

Compilation error in SysReportLibraryExport class

Hi Folks,

Once I have compiled the complete AX 2009 environment on the Server where AOS is installed and found that there was a compilation issue in the Class declaration of SysReportLibraryExport class but it seems to be fine with other environments.

I couldn't get any clue why this happened suddenly and atlast I tried opening AX client of this environment from the database server and compiled this class. The syntax error is gone and there are no more issues in it even though i have opend it on the application server environment.

I hope this post would help facing similar issue.

Tuesday, June 5, 2012

insert_recordset doesn't take the value of TableId from the value

Hi Folks,

Today, I have observed a very strange thing in AX.

I had to do a bulk insert from some other table where I also need to copy the tableId from the other table.

I have found a strange issue i.e.,everything was getting copied except the tableId. You can try this in a job.

insert_recordset TestTable1(RefRecId, RefTableId) select recId, TableId from TestTable2;

So, the tableid from some other table cannot be used in Insert_recordSet. Atlast, I had to use RecordInsertList class to insert the bulk data.

Sunday, May 13, 2012

Cryptography in AX using CryptoAPI class

    Hi Folks,

For some clients, you would require to encrypt some phrases or words like passwords. For this, we can use cryptography class(CryptoAPI) which would allow us to encrypt/decrypt the phrases. The following example explains about the CryptoAPI class.

    CryptoApi cryptoApi;
    Container cont,cont1;
    ContainerClass cc;
   /* Salt is like a password, While encrypting and descrypting the phrase, the CryptoAPI class has to instantiated with same salt(99999999999). The phrases/words are encrypted & decrypted based on the salt. */
    cryptoApi = new CryptoApi(99999999999);
    cc = new ContainerClass(["giridhar"]);
    cont = CryptoApi.encrypt(cc.toBlob()); // The encrypt method requires BLOB as a parameter
    cont1 = ContainerClass::blob2Container(CryptoApi.decrypt(cont));

Happy DAXing............