javaiso8583jpos

conditionally skip transaction participant in my Jpos-template project


I have multiple participants in my transaction manager config as below. I want to switch between UAT and LOCAL participants based on the object property that the current context holds (like if specific fields have specific values). How can I achieve this without having to change Java code and just modify the XML config? I am not sure if org.jpos.transaction.participant.JSParticipant is the way to go.

NOTE: I am simply using jpos-template project but not the Jpos-EE

<txnmgr class="org.jpos.transaction.TransactionManager" logger="Q2">
    <property name="queue" value="TXNMGR"/>
    <property name="sessions" value="10"/>
    <property name="max-sessions" value="100"/>

 
    <participant name="LOCAL" class="com.sanjok.qbean.RestParticipant">     

        <property name="server-signature-public-key"
                  value="***"/>
        <property name="server-encryption-public-key"
                  value="***"/>
        <property name="base64-client-signature-private-key"
                  value="***"/>
        <property name="base64-client-encryption-private-key"
                  value="***"/>               
    </participant>
    
     <participant name="UAT" class="com.sanjok.qbean.RestParticipant">     

        <property name="server-signature-public-key"
                  value="***"/>
        <property name="server-encryption-public-key"
                  value="***"/>
        <property name="base64-client-signature-private-key"
                  value="***"/>
        <property name="base64-client-encryption-private-key"
                  value="***"/>               
    </participant>

    <participant class="org.jpos.transaction.participant.SendResponse">        
    </participant>
</txnmgr>

Solution

  • You can use a Switch transaction participant with transaction groups like this:

    <txnmgr class="org.jpos.transaction.TransactionManager" logger="Q2">
        <property name="queue" value="TXNMGR"/>
        <property name="sessions" value="10"/>
        <property name="max-sessions" value="100"/>
    
        <participant class="org.jpos.transaction.participant.Switch"
          logger="Q2" realm="Switch">
          <property name="txnname" value="<CONTEXT_KEY_TO_SWITCH_ON>"/> <!--1-->
          <property name="<LOCAL_VALUE>" value="LOCAL"/>                <!--2-->
          <property name="<UAT_VALUE>" value="UAT"/>                    <!--3-->
          <property name="unknown" value="<DEFAULT_ENDPOINT_OR_ERROR_GROUP>"/>  <!--4-->
        </participant>
        <group name="LOCAL">
            <participant name="LOCAL" class="com.sanjok.qbean.RestParticipant">     
    ...
           </participant>
         </group>    
         <group name="UAT">
           <participant name="UAT" class="com.sanjok.qbean.RestParticipant">     
    ...
           </participant>
        </group>
        <participant class="org.jpos.transaction.participant.SendResponse">        
        </participant>
    </txnmgr>
    
    
    1. <CONTEXT_KEY_TO_SWITCH_ON> is the context key that contains the value based on which you want to select the destiny.
    2. <LOCAL_VALUE> is the value of that key that should make the transaction go to local
    3. <UAT_VALUE> is the value of that key that should make the transaction go to UAT.
    4. <DEFAULT_ENDPOINT_OR_ERROR_GROUP> is the endpoint (or an error group, if you want to handle it like that) where you want to go if none of the previous match. Like the default on a java switch statement.

    The Switch transaction participant is documented in the jPOS Programmer's Guide section 9.8.1.

    Basically, we are saying that if the key matches <LOCAL_VALUE> run group LOCAL, if it matches <UAT_VALUE> run group UAT, else run whatever group you define there. Participants in each group get executed right after the Switch participant, and before the next one.

    Select endpoint based on a property of a context object.

    The OP asked in a comment to be able to select the endpoint based on a field of the request. For this we need to use code, it can be in a scripted participant.

    Best option would be to use GroovyParticipant since it enables to precompile the script, but since the OP is not using jPOS-EE, not clear if he doesn't want to, or just isn't but willing to do.

    Using BSHGroupSelector.

    The simplest option is to use BSHGroupSelector since we just need to modify the Switch participant for this xml:

      <participant class="org.jpos.transaction.participant.BSHGroupSelector">
        <select>
          import org.jpos.iso.*;
          ISOMsg m = context.get("REQUEST");
          String de3 = m.getString(3);
          result = (/*condition on DE3 for selecting UAT*/) ?  "UAT" : "LOCAL";
        </select>
      </participant>
    

    result is the variable used by GroupSelector to determine the result of the select method, i.e., get the group to run.

    Using JSParticipant

    There is no way to write a GroupSelector with JSParticipant that I know of. However, we can use a JSParticipant to extract field 3 to a context key. We would need to add this participant, previous to the Switch participant:

    <participant class="org.jpos.transaction.participant.JSParticipant"
      logger="Q2" realm="js" src='cfg/extract-de3.js' />
    </participant>
    

    Where cfg/extract-de3.js has the following content:

    var K = Java.type("org.jpos.transaction.TransactionConstants");
    var prepare = function(id, ctx) {
      //put de 3 in context under de3 key.  ctx.put("de3", 
      ctx.get("REQUEST").getString(3);
      return K.PREPARED;
    }
    

    The Switch participant definition would be as follows:

        <participant class="org.jpos.transaction.participant.Switch"
          logger="Q2" realm="Switch">
          <property name="txnname" value="de3"/> 
          <property name="<LOCAL_VALUE>" value="LOCAL"/>                
          <property name="<UAT_VALUE>" value="UAT"/>                    
          <property name="unknown" value="<DEFAULT_ENDPOINT_OR_ERROR_GROUP>"/>
        </participant>