2

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>
Sanjok
  • 341
  • 1
  • 9

2 Answers2

1

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>
Andrés Alcarraz
  • 1,570
  • 1
  • 12
  • 21
  • I want my context key to be the value of field Id 3. If I do `` participant is likely to search the group name with the whole object reference which doesn't exist. – Sanjok Apr 23 '23 at 05:33
  • 1
    In that case, I think you will need a "scripting" participant, like `JSParticipant` or BSHParticipant` whether to extract the field to the context and then use this, or by implementing the group selector in it. I will update my response, but you should include that info in the question. Also, can you specify the motive of why you don't use or don't want to use jPOS-EE? With that you could use `GroovyParticipant` also. – Andrés Alcarraz Apr 25 '23 at 12:38
  • @Sanjok, I added details of how to implement what you need using `JSParticipant` and `BSHGroupSelector`. Hope this helps. – Andrés Alcarraz Apr 25 '23 at 16:29
  • hi @Andrés Alcarraz, I am happy using the `JSParticipant` based solution you provided. Actually, I am doing technical research for the development of an ISO-compliant PSP solution for a startup company in Nepal. The company is not willing to go for the paid solution like JPOS-EE at least for 2-3 yrs. This is only the reason to avoid `GroovyParticipant` – Sanjok Apr 27 '23 at 11:59
  • @Sanjok I'm glad it worked for you, but AFAIK jPOS-EE has the same licensing model than jPOS, so if you can use one you can use the other. In fact, for using jPOS in a commercial production environment, one have to pay the license. And if I'm not wrong, that license enables you to use jPOS-EE components. – Andrés Alcarraz Apr 27 '23 at 13:23
0

You can take advantage of jPOS environment variables and add the enabled attribute.

You can have a couple of environment variables, i.e:uat.enabledand local.enabled that you can configure like this:

<participant name="LOCAL" class="com.sanjok.qbean.RestParticipant" enabled="${local.enabled}"> 
    ...
    ...
</participant>
<participant name="UAT" class="com.sanjok.qbean.RestParticipant" enabled-"${uat.enabled}">  
   ...
   ...
</participant>
  

The you can either use YAML configurations or just environment variables (LOCAL_ENABLED and UAT_ENABLED).

This is documented in jPOS Programmer's Guide section 3.3.

apr
  • 1,288
  • 7
  • 8