Tuesday 28 April 2015

Using defined macro vs personalized Jolie service

When designing software solution using microservices  one finds himself to wander how do handle repetitive code.  This is particularly true when one uses microservices for data handling and data mapping; where often it is required to transform data from a format to another for example:
  1. Date Format
  2. Double Value Format 
  3. Other Alphanumerical manipulation  
Jolie language provides  to the programmer already with some rather powerful primitives to manipulate such data but is not uncommon to have to personalize some behavior. And this is where the dilemma araises. Do I go for 
  1. A series of  macros defined by the primitive define 
  2. Or do I create a service with a number of exposed operation
Now this post does not aim to set a standard or either to propose a methodology for microservices coding in Jolie, Its only aim is to share a personal checklist when taking a coding decision on repetitive code .
Let's look  to an example of date transformation
   
define transformDate{

    if (is_defined(__date)){

requestSplit= __date;
requestSplit.length = 4 ;
splitByLength@StringUtils (requestSplit)(resultSplitYear);
year = resultSplitYear.result[0];
requestSplit= resultSplitYear.result[1];
requestSplit.length =2;
splitByLength@StringUtils (requestSplit)(resultSplitMonth);
month = resultSplitMonth.result[0];
day = resultSplitMonth.result[1];
__transformedDate =day+"-"+month+"-"+year
}
}


Now this section of code could be defined with in an iol file and included by several services and used in this way

__date = value_original_date
transformDate
value_new_date = __transformedDate

Now let us see the same functionality implemented with a service

type DateTransformRequest:string

type DateTransformResponse:string

interface TransformInterface {
RequestResponse:
 transformDate (DateTransformRequest)(DateTransformResponse)
}

and with an implementation that looks like

inputPort TransformerInputPort{ 
  Location:"socket://localhost:8099" 
  Interfaces:TransformInterface
  Protocol:sodep 
}
main{
transformDate(request)(response){
  //the code that does it here
}]{nullProcess}


Now let us go down to the topic of the post how can we compare the two implementations

Define implementation

Pro
Con
Need to restart all the services if there a change to be implemented

Yes
No network resources
Yes

Shorter time of implementation
Yes

Clear error tractability

No
Network deploy

No

and for the Jolie service implementation

Jolie Service implementation

Pro
Con
Need to restart all the services if there a change to be implemented
No

No network resources

No
Shorter time of implementation

No
Clear error traceability
Yes

Network deploy
Yes


Now the reader may be tempted to object to such a limited arbitrary check list and he or she would be right to do so, but my aim was not to give a definitive answer but more indicate a methodology of thinking.
Now let us step back to the drawing board and consider the following questions.

  1. Do I need to re-use the code several time and across several implementations
  2. My hardware infrastructure will be subject to  changes
  3. Do I need trace possible errors specializing error raising and handling
  4. Do I need to use complex data type  

If the answer to all these questions is yes is my opinion that would be better to opt for a Jolie Service Implementation approach for the following reason:
  1. In both implementation the cross usability is possible but the Jolie service implementation is favorable for :
    1. In case of code changes I need to change in a single place 
    2. If I need to use in a new project I do not have to copy specific implementation but refer to an interface and leave the implementation stable
  2. This point is often underestimated during the design phase of the project but in microservices architecture has a huge impact ; also in this case the Jolie Service Implementation is favorable because:
    1. Its naturally more adaptable to infrastructure changes ( the service can be deploy where ever )
    2. If there is a need of splitting the microservices implementation over several machine, in the case of the define base implementation we will find ourself duplication the implementation on several machine , with all the problems concerning code duplication
  3. The error handling  it is essential in any software paradigm , but it is even more important in SOA architecture where the high level of concurrent execution would almost impossible to trace errors. In the case of the Jolie Service Implementation the possible error are definable at level of interface making in my opinion simpler the use of the functionalists
  4. /* define implementation */
    define myDefine{
       /*some code*/
       throw (someError)
       /* some other code */
       throw (someOtherError) 
    }
    /* Use of interface  */
    interface myInterface{
    RequestResponse:
    myOperation (requestType)(responseType) throws someError , someOtherError
    }  
    1. As the code above tries to exemplify the user of the functionalists  would   find easier to identify the possible error to catch via interface instead of having to scan the implementation
  5. Similarly to the issue of the fault handling the use of complex types is aided massively by the use of  a Jolie Service Implementation approach where we can define complex types in a clear way instead of having to reverse engineer the code of the define
I hope you will find my post somehow useful to define define recurrent code in jolie

Sunday 25 January 2015

Using Jolie to implement BTE transactions

For whom of you that is familiar with SAP and its complex behaviours, the term BTE ( Business Transaction Event  ) should be familiar. For those less familiar with SAP a BTE can be defined as a specific moment ( status ) in  the life cycle of enterprise document. such concept transcends SAP and its implementation of an ERP  For example an Sales Invoice can be represented by a cohesive object that contains all the required information.
In the service oriented programming object as such do no exist instead they are  substituted by operation and they relative input and output messages. In a standard WSDL notation operations and their relative messages are represented in this way 

<message name="createSalesInvoiceRequest">
  <part name="clientCode"    type="xs:string"/>
  <part name="invoiceDate"   type="xs:string"/>
  <part name="invoiceAmount" type="xs:double"/>
</message>

<message name="createSalesInvoiceResponse">
  <part name="invoiceId" type="xs:string"/>
</message>

<portType name="salesInvoiceInterface">
  <operation name="createSalesInvoice">
    <input message="createSalesInvoiceRequest"/>
    <output message="createSalesInvoiceResponse"/>
  </operation>
</portType>

In Jolie the operation can be represented using the following definition

type createSalesInvoiceRequest:void{
   .clientCode:    string
   .invoiceDate:   string
   .orderNumber : string
   .invoiceAmount: double
}
type createSalesInvoiceResponse:void{
      .invoiceId:int
}

interface SalesInvoiceInterface{
 RequestResponse:
    createSalesInvoice (createSalesInvoiceRequest)(createSalesInvoiceResponse)
}

Is not a case that as an example of operation createSalesInvoice was selected as an example: often the communication medium of such document varies from client. Let’s look at some examples

Your customer is :

1.     A big corporation and wants a communication via XML File 
2.     A medium size company that requires PDF
3.     A small company may just want an e-mail
Now let's us define a DocumentInterface

type createDocumentRequest:void{
   .invoiceId:    int
   .invoiceDate:   string
   .orderNumber : string
   .invoiceAmount: double
   .clientInfo:clientInfoType
   .
}
type createDocumentResponse:void{
      .docId:string
}

interface DocumentInterface{
 RequestResponse:
    createDocument (createDocumentRequest)(createDocumentResponse)
}

Now let's us assume that three separate services are created and each of the them is implementing the documentInterface

Now in the service that implements createSalesInvoice we need to define an output port in this way

outputPort DocumentServicePort {
  Location:  "local"
  Protocol:sodep
  Interfaces: DocumentInterface
}

and an implementation of the operation as follow

[ createSalesInvoice(request)(response){
  /*code to save on the DB */
  response.invoiceId = responseDB.invoice
}]{ 
     requestClientInfo.clientCode = request.clientCode;
     getClientInfo@ClientServicePort(requestClientInfo)(responseClientInfo);
     requestDocumentCreator.invoiceId =  response.invoiceId ;
     requestDocumentCreator.invoiceDate = request.invoiceDate;
     requestDocumentCreator.orderNumber = request.orderNumber;
     requestDocumentCreator.invoiceAmount =request.invoiceAmount;
     requestDocumentCreator.clientInfo << responseClientInfo.clientInfo;
     DocumentServicePort.location = responseClientInfo.serviceInfo.location
    createDocument@DocumentServicePort( requestDocumentCreator) (responseDocumentCreator);
}

It can be seen on the line underlined in green how the location of the DocumentService is dynamically this will allow to select the location dynamically depending on the client code the location and therefore its implementation of createDocument.
Let’s go back to our three clients with there relative localtion

1.     A big enterprise =>"socket://localhost:3001"
2.     A medium enterprise =>  "socket://localhost:3002"
3.     A small enteprise=>  "socket://localhost:3003"

Let’s assume now that in the life cycle of the implementation will be necessary to specialize even further the document service
The IT development team will be able to design and develop the new service without having to touch the existing code. Once tested and approved by the business it will be possible to activating by simply adding the new location to all the client master data that need to have this new service

I hope this post has showed some the excellent flexibility capabilities Jolie possess in implement BTE. How a change in a part of the business workflow does not mean long hours of redesign and redeployment. The author does realize that this example centrally does not represent the complexity of a real business work flow, but this post aims to propose Jolie as a serious contend for Business workflow design and implementation