如何在jPOS TransactionResponse中获取多参与者响应并对比?
你碰到的这个问题其实是典型的上下文键冲突——两个查询参与者共用同一个Constants.RESPONSE_KEY存储响应,后面的调用自然会把前面的结果覆盖掉。解决思路很直接:给每个主机的响应分配独立的存储键,然后在响应组装阶段分别取出这两个响应,对比字段39后再生成最终结果。下面是具体的修改步骤:
第一步:新增独立的响应存储常量
先在你的Constants类里添加两个专属键,用来区分两个主机的响应:
public class Constants { // 保留原有常量 public static final String REQUEST_KEY = "REQUEST_KEY"; public static final String RESPONSE_KEY = "RESPONSE_KEY"; // 新增两个主机响应的专属标识 public static final String HOST1_RESPONSE_KEY = "HOST1_RESPONSE_KEY"; public static final String HOST2_RESPONSE_KEY = "HOST2_RESPONSE_KEY"; }
第二步:修改两个查询参与者的存储逻辑
分别修改FinancialTransactionQueryRemoteHost1和FinancialTransactionQueryRemoteHost2的prepare方法,把各自的响应存到专属键中,避免覆盖:
修改FinancialTransactionQueryRemoteHost1:
@Override public int prepare(long l, Serializable srlzbl) { try{ channelManager = ((ChannelManager) NameRegistrar.get("jpos-host1-adaptor")); ISOMsg reqMsg = (ISOMsg) ((Context) srlzbl).get(Constants.REQUEST_KEY); ISOMsg respMsg = channelManager.sendMsg(reqMsg); // 用HOST1专属键存储响应 ((Context) srlzbl).put(Constants.HOST1_RESPONSE_KEY, respMsg); return PREPARED; }catch(NameRegistrar.NotFoundException e){ e.printStackTrace(); return ABORTED; }catch(Throwable t){ t.printStackTrace(); return ABORTED; } }
修改FinancialTransactionQueryRemoteHost2:
@Override public int prepare(long l, Serializable srlzbl) { try{ channelManager = ((ChannelManager) NameRegistrar.get("jpos-host2-adaptor")); ISOMsg reqMsg = (ISOMsg) ((Context) srlzbl).get(Constants.REQUEST_KEY); ISOMsg respMsg = channelManager.sendMsg(reqMsg); // 用HOST2专属键存储响应 ((Context) srlzbl).put(Constants.HOST2_RESPONSE_KEY, respMsg); return PREPARED; }catch(NameRegistrar.NotFoundException e){ e.printStackTrace(); return ABORTED; }catch(Throwable t){ t.printStackTrace(); return ABORTED; } }
第三步:修改FinancialTransactionResponse的对比逻辑
现在可以在这个参与者里分别取出两个主机的响应,对比字段39,再生成最终的响应结果:
@Override public int prepare(long id, Serializable context) { Context ctx = (Context)context; // 取出两个主机的响应,注意做空指针判断 ISOMsg host1Resp = (ISOMsg)ctx.get(Constants.HOST1_RESPONSE_KEY); ISOMsg host2Resp = (ISOMsg)ctx.get(Constants.HOST2_RESPONSE_KEY); // 基于请求消息初始化最终响应(确保MTI、跟踪号等关键字段正确) ISOMsg finalResp = null; ISOMsg reqMsg = (ISOMsg)ctx.get(Constants.REQUEST_KEY); try { finalResp = (ISOMsg) reqMsg.clone(); finalResp.setResponseMTI(); // 切换为响应MTI } catch (CloneNotSupportedException e) { e.printStackTrace(); return ABORTED; } // 判断两个主机的响应状态(字段39是否为"00") boolean host1Success = (host1Resp != null && "00".equals(host1Resp.getString(39))); boolean host2Success = (host2Resp != null && "00".equals(host2Resp.getString(39))); // 根据业务规则生成最终的字段39值 if (host1Success && host2Success) { finalResp.set(39, "00"); // 两者都成功,返回成功码 } else if (host1Success || host2Success) { finalResp.set(39, "00"); // 只要一个成功就返回成功(可根据实际业务调整) } else { finalResp.set(39, "06"); // 两者都失败,返回失败码 } ctx.put(Constants.RESPONSE_KEY, finalResp); return PREPARED; }
额外注意事项
- 一定要处理响应为空的情况:如果某个主机调用失败(参与者返回
ABORTED),对应的响应键可能不存在,必须加非空判断避免空指针异常。 - 业务规则可灵活调整:比如你是要求两者都成功才算成功,还是只要一个成功即可,完全根据你的实际业务需求修改判断逻辑。
- 如果
ISOMsg克隆有问题,也可以手动创建新的响应消息,复制请求中的必要字段(如系统跟踪号、日期时间等)。
内容的提问来源于stack exchange,提问作者Dexter
相关产品推荐
相关产品推荐

