Friday 5 August 2016

MongoDB Jolie Connector Part 2: Application Example

In the previous post I looked at the basic use of Jolie's MongoDB connector with an overview of its characteristic and it basic uses. In this post we are looking at a real use of the connector, the obvious choice would have been the implementation of Sales and Distribution application; yet in the company where I work such a need has not arisen. The opportunity to use MongoDB and jolie have arisen when approving the development of a Plant Management software. Production plants are often very complex structures with hundreds of  components. The best way to represent such complex structures is by using a tree representation  where the hierarchical nature of plant and its sub component can be best expressed. The tree data structure also fits perfectly with jolie data structures and with MongoDB document approach.
Therefore the first step in the development process was to define a "document" or better a tree data structure that represents my company production plants.  
     
 type ProductionSiteType {  
  .productionSite:void{  
   .productionSiteName:string  
   .productionSiteErpCode:string  
   .mainLine*:void{  
       .mainLineName:string  
       .mainLineErpCode:string  
       .subLine*:void{  
         .subLineName:string  
         .subLineErpCode:string  
          .equip*:void{  
           .equipName:string  
           .equipErpCode:string  
          }  
         }  
        }  
       }  
    }  
 }  

The second issue was to valuate how flexible this data structure is? can it adapt to changes required by the business , with the insertion of  new information. Let us suppose that the business requires to specify a mainLineManager (under the mainLine node ) with his/her contact details, and also it is required to supplierMaterialCode. The compulsiveness of the information can be now handled using the jolie  node's cardinality.

       .mainLineManager:void{  
          .managerName:string  
          .email:string  
          .phone:string        
       }  

The insertion of this node node will require the data within the collection to be  processed again

        .equip*:void{  
           .supplierMaterialCode?:string
           .equipName:string  
           .equipSapCode:string  
          }  

Where in this case there will be no need for the collection to be processed again
So far the reader may think that the writer has only shown  how to represent a possible plant structure using jolie.
The advantage of the document approach will become evident when looking at the interface and the operation

interface MaintanaceServiceInterface{
   RequestResponse:
    addProductionSite( ProductionSiteType )(AddProductionSiteResponse)
 }

It can be seen that any change in the document is propagated at the addProductionSite operation, and it is also evident looking at the implementation,

   [addProductionSite(request)(response){
    scope (addProductionSiteScope){
     install (default => valueToPrettyString@StringUtils(addProductionSiteScope)(s);
              println@Console(s)());
              q.collection = "SiteStructure";
              q.document << request;
              insert@MongoDB(q)(responseq)
     }
     }]{nullProcess}

The same can be said for the reading of plants structures


type GetMainLineRequest: void{
     .productionSiteErpCode?:string
}
type GetMainLineResponse:void{
  .document*:productionSiteType
}
  
interface MaintanaceServiceInterface{
   RequestResponse:
    addProductionSite( ProductionSiteType )(AddProductionSiteResponse),
    getProductionSite(GetProductionSiteRequest)(GetProductionSiteResponse)
 }


With the following implementation


  [getProductionSite(request)(response){
      scope (getProductionSiteScope){
       install (default => valueToPrettyString@StringUtils(getProductionSiteScope)(s);
                          println@Console(s)());
                q.collection = "SiteStructure";
                if ( is_defined (request.productionSiteErpCode)){
                   q.filter << request;
                   q.filter = "{'productionSite.productionSiteErpCode': '$productionSiteErpCode'}"
                };
                if (DEBUG_MODE){
                  valueToPrettyString@StringUtils(q)(s);
                  println@Console(s)()
                };
                query@MongoDB(q)(responseq);
                if (DEBUG_MODE){
                  valueToPrettyString@StringUtils(responseq)(s);
                  println@Console(s)()
                };
                response << responseq
       }
      }]{nullProcess}


Once again it can be noticed that the filter is expressed as MongoDB standard query language with the injection of the data directly from the jolie type.
It has been also necessary to refactor some of the subNode such as the equip defining a not inline type



       type equipType:void{  
           .equipName:string  
           .equipSapCode:string  
          }

 type AddEquipmentRequest {
     .productionSiteErpCode:string 
     .mainLineErpCode:string
     .subLineErpCode:string
     .equip: equipType     
  }
  interface MaintanaceServiceInterface{
      RequestResponse:
                 addProductionSite( ProductionSiteType )(AddProductionSiteResponse),
                 getProductionSite(GetProductionSiteRequest)(GetProductionSiteResponse),
                 addEquipment( AddEquipmentRequest )(AddProductionSiteResponse)
    } 


By defining a new jolie complex type it has been possible centralizing the definition of the equipment that can be used both as type for further operations or directly as new document for a new collection
An other example of the usefulness of the type/document  driven design is the access to subNodes content as individual nodes


type GetMainLineRequest: void{
     .productionSiteErpCode?:string
  }
type GetMainLineResponse:void{
   .document*:productionSiteType
}
  interface MaintanaceServiceInterface{
      RequestResponse:
                 addProductionSite( ProductionSiteType )(AddProductionSiteResponse),
                 getProductionSite(GetProductionSiteRequest)(GetProductionSiteResponse),
                 addEquipment( AddEquipmentRequest )(AddProductionSiteResponse)
    } 


 [getMainLine(request)(response){
   scope (getMainLineScope){
    install (default => valueToPrettyString@StringUtils(getMainLineScope)(s);
                       println@Console(s)());
         q.collection = "SiteStructure";
         q.filter[0] = "{ $match : { 'productionSite.productionSiteErpCode' :'$productionSiteErpCode' } }";
         q.filter[0].productionSiteErpCode = request.productionSiteErpCode;
         q.filter[1] = "{$unwind : '$productionSite'}";
         q.filter[2] = "{$unwind : '$productionSite.mainLine'}";
         if (DEBUG_MODE){
           valueToPrettyString@StringUtils(q)(s);
           println@Console(s)()
         };
            aggregate@MongoDB(q)(responseq);
         if(DEBUG_MODE){
              valueToPrettyString@StringUtils(responseq)(s);
              println@Console(s)()
            };
        response << responseq


  }
   }]{nullProcess}


By using the aggregation operation it has been possible to extract the content of the subNode mainLine for a specific plant and creating the correlation one document for each mainLine.

With in the limit of blog post I hope the reader will appreciate how jolie and jolie's MongoDB connector are a valid  technology to approach microservices  based data intensive applications.

No comments:

Post a Comment