In order to test document services we need to do many steps from configuring AIF until the setup and development in visual studio. This post provide an easy tool to test AIF services (crea
In order to test document services we need to do many steps from configuring AIF until the setup and development in visual studio. This post provide an easy tool to test AIF services (create, update and delete) with a X++ job in Ax 2012. In this example we are going to test operation service functions of the document service created in my previous post ( CRUD Operations with AIF Document Services in Visual Studio) . We are doing this test in Dynamics Ax and there is no need for AIF/VS setup or have XML files available.
As we create a Document service with the AIF Document Service Wizard,
In de Wizard we choose the yellow marked service operations:
When complete the wizard, the system will generate a private project with objects in the AOT .We see that system generated 5 different classes with have each it’s own extension:
first class has an extension to AxInternalBase class. With the AxInternal base we can store objects or records.
We see a second class generated with an ‘AxdBase’ extension. Classes extend the AxdBase class are the document classes. They represent business documents. An example of a business document could be an inventory journal or a sales/purch order. A document class also handles the generation of XML Schema Definition (XSD), which defined the document structure and business rules. In my next posts I will write more about XSD.
The third class has an extension to AIFDocumentService. Actually this class implements the service operations that we have defined in the Service Operation section of the wizard.
The fourth class has an extension to the AIFDocument class, which provide the data for the service class.
The last generated class has an extension to the AfStringlyTypeDataContainer class. Also this class provide data to the service class.
In this example we gonna test the create, update and delete service in a job, without XML file and without AIF setup. In order to do this we use the classes extended to the AIFDocumentService, AIFDocument and the AfStringlyTypeDataContainer.
Apart from that, we need for the both update and delete operations also the AifEntityKeyList. In order to use the AifEntityKeyList list we also need the AifEntityKey. Example how to get a correct AifEntityKetList with X++:
Regarding the AIFDocument class. For the update operations a hashcode is mandatory. See the code to generate the hashcode:
With the variable ‘entityAction’ can be switched between the operations Create, Update and Delete.
We give the parameters in the class which is extended to ‘ AfStringlyTypeDataContainer’, via the class which is extended to AIFDocument.
Appendix: full code of the job:
static void testJobAIFDocumentServices(Args _args) { #define.CourseId("AX7-DEVI") #define.CourseName("AX7 Introduction DevelopmentI") #define.Trainer("van Kessel") FOXCourseQueryService service; // Service class (extends with AifDocumentService) FOXCourseDocument document; // Document object (extends with AifDocument) FOXCourseDocument_FoxCourse dataObject; // Data object (extends with AifStronglyTypedDataContainer) String30 id; Map map; AifEntityKey key = new AifEntityKey(); AifEntityKeyList entityKeyList = new AifEntityKeyList(); //Choose the transactiontype AxdEntityAction entityAction = AxdEntityAction::update; str getHashCode(String30 _courseId) { //Hashcode is mandatory for updating AxdBaseRecordInfo recordInfo; FOXCourse foxCourseLoc; str documentHash; Map dataSourceMap = new Map(Types::Integer,Types::Integer); select firstOnly name, trainer from foxCourseLoc where foxCourseLoc.Id == _courseId; recordInfo = AxdBaseRecordInfo::newCommon(foxCourseLoc, 1 , dataSourceMap); documentHash = recordInfo.getRecordHash(); return documentHash; } void getDocumentData() { document = new FOXCourseDocument(); document.createFoxCourse(); dataObject = document.parmFoxCourse().addNew(); if (entityAction == AxdEntityAction::update) { //Hashcode is mandatory by update dataObject.parm_DocumentHash(getHashCode(#CourseId)); } //Key Id should also given for update //In that case should the given key the same as he orig key // (see validation rule in AxdBase/checkFieldsForUpdate) dataObject.parmId(#CourseId); dataObject.parmName(#CourseName); dataObject.parmTrainer(#Trainer); } //Instantiate the service service = FOXCourseQueryService::construct(); //Document if (entityAction == AxdEntityAction::update || entityAction == AxdEntityAction::create) { getDocumentData(); } // Compose the map with the keyfield map = new Map(Types::Integer, Types::Container); map.insert(fieldnum(FOXCourse, Id), [#CourseId]); // Compose the keyfield key.parmTableId(tablenum(FOXCourse)); key.parmKeyDataMap(map); // Compose the entity key list entityKeyList.addEntityKey(key); // run the service switch (entityAction) { case AxdEntityAction::create : service.create(document); break; case AxdEntityAction::update : service.update(entityKeyList, document); break; case AxdEntityAction::delete : service.delete(entityKeyList); break; } id = entityKeyList.getEntityKey(1).parmKeyDataMap().lookup(fieldnum(FOXCourse, Id)); info(strfmt("Course %1 is %2d", id, entityAction)); }