Service Virtualization

  • 1.  Shared Model Map

    Posted Jul 18, 2018 08:05 PM

    Hi,

     

    I referred the documentation provided at this thread https://communities.ca.com/thread/119299345

    @ Joel Nesmith, Srikanth Gajawada please help me here.

     

    DevTest Version - 10.1 is being used

    I am trying to implement the shared model map for one scenario.

     

    Scenario:

    There are 2 services getDetails and maintainDetails. These are part of same vsm file. Application invokes the services with the following sequence

    getDetails 

    maintainDetails

    getDetails

    First get call will display the accounts

    User action add/delete invokes the maintainDetails service. Here I see the AccountNumber

    Post that, there is get a getDetails that has the respective account linked or de-linked

     

    Issue:

    Here, I am trying to fetch Account number rom maintain and pick right response for #2 getDetails. But somehow it is not fetching the value, and picking up the first getDetails response.

     

    Code Details:

    The following code is added for ExecuteScript step in the vsm file.

    maintainDetails -

    Properties myProps = new Properties();

    myProps.setProperty("smmMyMessage", testExec.getStateValue("prop_SomeMessage") );

    SharedModelMap.putObject(“<myNamespaceHere>”, “<enterKeyValueHere>”, myProps);

     

    getDetails -

    Properties myProps = (Properties) SharedModelMap.getObject(“<myNamespaceHere>”,
    “<enterKeyValueHere>”);

    String myAccount = myProps.getProperty("smmMyMessage");

     

    Kindly let me know whether I am missing something or is there any better way in which it can be achieved.

     

    Thanks,

    Harshad

     

     

     



  • 2.  Re: Shared Model Map

    Broadcom Employee
    Posted Jul 19, 2018 02:58 AM

    Hi Harshad,

     

    I think you wrote script in "Execute Script(JSR-223).step" by referencing the documentation "How To - Use SharedModelMap.pdf" in VSE-Sharing data between two services.
    How do you test the vsm/vsi files?
    Do you deploy to the VSE or do you use ITR in DevTest Workstation?
    Is it possible to attach your vsm/vsi files in this question?

     

    Thank you,



  • 3.  Re: Shared Model Map

    Posted Jul 19, 2018 11:56 AM

    Hi Yusuke,

     

    Thanks for your response!

    Yes! That's right. I used the Execute Script step by reading through the pdf document.

    I validated it by deploying the vsm file over the VSE.

    I am picking the response from external DB source, so it would be great if I can screen share and demo.

    Let me check if I can attached the vsi-vsm as well.

     

    Thanks & Regards,

    Harshad Mulye



  • 4.  Re: Shared Model Map

    Posted Jul 19, 2018 02:40 PM

    So, you are not using the VSI to select responses.

    The basics of my original response below may be somewhat applicable so long as the logic identifies a way to translate the count of the number of times the getDetails API is invoked into a query value that selects the proper response from the DBMS table. The basic assumption is that the DBMS holds the various getDetails API responses for the combinations the requirement calls for.

    Be cautious though about storing large amounts of data in the Shared Model Map. This is an in-memory hash table that is held at the JVM level.



  • 5.  Re: Shared Model Map

    Posted Jul 19, 2018 08:37 AM

    I believe this topic is going to become lengthy because there may be more complexity than we see in the original post.

    The short answer is that your service might best work using a Stateful Model (Stateless and Conversational VSE Transactions - DevTest Solutions - 10.1 - CA Technologies Documentation) rather than Stateless model. 

     

    Before we look at the Shared Model Map, let's consider some things. Consider these assumptions. Changes in these assumptions affect virtual service implementation behavior:

    a) The order of the calls must be as follows as per the original post:

        getDetails (account 123 - 1st response)

        maintainDetails (account 123)

        getDetails (account 123 - 2nd response) 

        getDetails (account 123 - 1st response)

    b) The order of the calls can not be as follows:

        getDetails (account 123 - 1st response)

        getDetails (account 123 - 1st response)

        maintainDetails (account 123)

        getDetails (account 123 - 2nd response)

     c) The order of the calls can not be as follows:

        getDetails (account 123 - 1st response)

        maintainDetails (account 123)

        getDetails (account 123 - 2nd response)

        maintainDetails (account 123)

        getDetails (account 123 - 3rd response)

        -- repeat this process 'n' number of times

    d) The order of the calls can not be as follows:

        getDetails (account 123 - 1st response)

        getDetails (account 123 - 1st response)

        getDetails (account 123 - 1st response)

        getDetails (account 123 - 1st response)

        getDetails (account 123 - 1st response)

        -- repeat this process 'n' number of times

    [my point with the assumptions is that controlling state within a stateless model means the service may need to cater for variety of request / response scenarios and sequences. Establishing the behavioral characteristics supported by the service is critical to setting the expectations for what the service can and cannot do.]

     

    In a stateless model, one approach is to consider the maintainDetails operation call as the 'triggering' event because it helps the service deal with the assumption scenarios above.

    This means that the response to the getDetails transaction is the first response (regardless of the number of times the getDetails operation is invoked). Only a maintainDetails call can trigger the beginning of subsequent getDetails responses. This helps in those situations where getDetails is called, but maintainDetails is not part of the test scenario.

     

    This also means that the number of times the maintainDetails call occurs may be used as a counter on which the VSI can select subsequent getDetails responses. We will see a high level implementation of this approach below.

     

    The next thing to consider is how does the virtual service know when to start over?

    The posted scenario depicts a simple pattern of getDetails (rsp 1) -> maintainDetails -> getDetails (rsp 2), and the implication is that the flow starts over after the maintainDetails call is made the first time. But, what happens if some response sequences need 3, 4, or 5 different responses to simulate multiple calls associated with maintainDetails? How does the service determine this and know when to reset the flow back to "1"? This is a critical issue that must be clearly understand because the setup of the VSI depends on it.

     

    The remainder of this post examines the post in the context of the simple case (e.g., getDetails [rsp 1] -> maintainDetails -> getDetails [rsp 2], and then flow starts back at 1 with a couple of twists

    - Suppose the VSI could support an additional property as a request argument that is injected at run time. The VSI could use this argument as a counter enabling an additional comparison. If the VSM were to manually add this argument (let's call it devtest_seqNum) to the VSI on the getDetails transaction, the VSI could enable the concept of having multiple specific transactions for a given account number.

    VSI View of GET /getDetails operation:

    Spec Txn 1, Acct = 123, devtest_seqNum = 0, response is response 1

    Spec Txn 2, Acct = 123, devtest_seqNum > 0, response is response 2

    Spec Txn 3, Acct = ABC, devtest_seqNum = anything, always send this response

    (Account = ABC never participates in sending answers other than 1 response)

    Spec Txn 4, Acct = 789, devtest_seqNum = 0, response is response 1

    Spec Txn 5, Acct = 789, devtest_seqNum = 1, response is response 2

    Spec Txn 6, Acct = 789, devtest_seqNum > 1, response is response 3

    (Account 789 participates in a scenario where two maintainDetails calls are made followed by a getDetails so we need additional responses)

     

    - The JSR step or Scriptable DPH could then use the Model Map to store a combination of key=accountNumber / value=sequenceNum to keep track of how many times the maintainDetails operation has been called. The count of the number of times maintainDetails has been invoked for a given account number determines which VSI selection (above) happens.

     

    - The trick then is to insert (or add) an additional argument to the incoming request's argument list when the getDetails call happens. This additional argument provides a counter on which the VSI can perform a lookup.

     

    Potential psuedo code for this type of logic follows a pattern similar to the following:

    if (request operation is NOT 'GET /getDetails' and 'POST /maintainDetails' )

        exist JSR or Scriptable DPH step // nothing to do

    // so the logic can add a new argument only on getDetails

    ParameterList paramList = lisa_vse_request.getArguments();  

     

    if ( request operation = 'GET /getDetails' ) {

      // account not on map means maintainDetails has not been called

      if (NOT SharedModelMap.containsKey(<namspace>, <accountNum from lisa_vse_request>)

        // no reason to add acct to map since maintainDetails has been made

        // this also keeps the map as small as possible

        add devtest_seqNum=0 to paramList

        lisa_vse_request.setArguments( paramList )

      else 

        // getDetails never increments the counter only uses the counter

        // this enables multiple getDetails calls w/out a maintainDetails in the middle

        add devtest_seqNum=SharedModelMap.get(<namspace>, <accountNum from lisa_vse_request>)

        lisa_vse_request.setArguments( paramList )

     

      exit JSR or Scriptable DPH step

    }

    if ( request operation = 'POST /maintainDetails' ) {

       // not on the map means first call for this account

       if (NOT SharedModelMap.containsKey(<namspace>, <accountNum from lisa_vse_request>)

          SharedModelMap.put(<namespace>, <accountNum from lisa_vse_request>, "1")

          add devtest_seqNum=1 to paramList

          lisa_vse_request.setArguments( paramList )

       else

          String val = SharedModelMap.get(<namspace>, <accountNum from lisa_vse_request>)

          // convert to int for math but OK to save as string so you don't have to deal 

          // no reason to store objects on the map unless you just want to

          // this is where you might need to deal with resetting

          // the counter - base this on the requirements for example

          // if counter > 2 

          //     SharedModelMap.removeKey(<namespace>, <accountNum from lisa_vse_request>)

          //     maybe you want to start the devtest_seqNum back to "0" and exit script

          add 1 to the seq #

          SharedModelMap.put(<namespace>, <accountNum from lisa_vse_request>, <incremented value>)

          add devtest_seqNum=<incremented value toString> to paramList

          lisa_vse_request.setArguments( paramList )

    }

    exist JSR or Scriptable DPH step

          

    - Additionally, one needs to determine how to reset the map. What happens if a transaction becomes hung?

    Shared Model Map memory is only cleared out by start/stop of VSE.

    You might consider adding a custom, administrative operation to the service such as 'GET /getDetails/clearMap' and a custom step in the VSM that, when this operation is encountered, a step iterates the map (e.g., SharedModelMap.keySet(<namespace>) and removes all entries or 'GET /getDetails/clearMap?acct=1234' (e.g., SharedModelMap.remove(<namespace>, <accountNum from lisa_vse_request>) with logic to remove a specific account number from the map. And, 'GET /getDetails/displayMap' returns a list of each account number and its sequence number for the admin to view entries on the map. Admin approaches like these provide the developer a bit of administrative control over the map without taking services offline or shutting down VSE to clear the map.

    Don't forget that by default, the Shared Model Map namespace only holds 256 entries to minimize the impact of in-memory storage. If you have an unlimited number of account numbers you might need to switch to Persistent Model Map. 



  • 6.  Re: Shared Model Map

    Posted Jul 19, 2018 04:43 PM

    Hi Joel,

     

    Thanks for response! I am going through that.

    Please find the details below.

    1. The order of calls for any session would be

        getDetails (account 123 - 1st response)

        maintainDetails (account 123)

        getDetails (account 123 - 2nd response) ---- Here the test case ends.

        getDetails (account 123 - 1st response) ---- next session different test case

    2. I am storing additional responses in the SQL Server Database and connecting vsm to it. In the vsi, I am passing the Response as parameter.

    3. The database table structure is common, so I am unable to add any field [devtest_seqNum].

     

    I will check with my team if I can share the vsi-vsm.However it would be really great, if we can do some screenshare.

    Kindly let me know.

     

    Thanks & Regards,

    Harshad Mulye

     



  • 7.  Re: Shared Model Map

    Posted Jul 19, 2018 05:00 PM

    Sounds good.

    If the pattern above applied and the responses were in the VSI, you could use the Allow Duplicate Specific Transactions  (Transactions Tab for Stateless Transactions - DevTest Solutions - 10.3 - CA Technologies Documentation) response. DevTest will internally keep track of the sequence and start over as needed. So, if the VSI held two specific responses, DevTest would cycle through and give the following:

    getDetails (account 123 - 1st response)

    getDetails (account 123 - 2nd response) 

    getDetails (account 123 - 1st response) 

    getDetails (account 123 - 2nd response) 

    getDetails (account 123 - 1st response) 

    :

    When using Allow Duplicate Specific Transactions, the getDetails API contains no linkage whatsoever to the maintainDetails API call.

    However, your VSM is accessing responses from a database. How does the SQL query differentiate between the first and second responses? Wouldn't there be a column of some sort to select the first response vs the second? Hopefully, the VSM is not reading the both responses into memory and then toggling between the two there? If were to be the case, the service needs to be careful and not gobble up too much memory else the VSE could start experiencing heap issues.



  • 8.  Re: Shared Model Map

    Posted Jul 20, 2018 05:12 PM

    The duplicate transaction wouldn't work for our framework, as we are storing one transaction with operation match style and getting response using 1-2 mandatory parameters.

     


    However, your VSM is accessing responses from a database. How does the SQL query differentiate between the first and second responses? Wouldn't there be a column of some sort to select the first response vs the second? Hopefully, the VSM is not reading the both responses into memory and then toggling between the two there? If were to be the case, the service needs to be careful and not gobble up too much memory else the VSE could start experiencing heap issues.

    PFB my response -

    SQL query is same for both the get responses, but the input parameter will vary, if we don't get any value from maintain [first case]. It would be default response that I am setting. For the second case, I will get Account in the maintain that I plan to use for the subsequent get request.

    We thought of index logic to pick 2 different responses, but that would limit for the variant responses to 2. Also we would have to change the design of all other messages, so trying to see if there's solution.

    The VSM isn't reading both into the memory, we have less number of cases for these though. However that is good point, I will keep an eye on it.

     

    Thanks,

    Harshad