QuickFix/J发起行情请求时GUI中SessionID为null报错问题咨询
问题根源与解决方案
报错的直接原因是GUI事件回调的actionPerformed方法里用到的sessionID变量未被正确赋值,核心问题出在不同类的变量作用域和QuickFIX/J的回调线程差异上:
常见触发原因
- 变量作用域不匹配:你在应用层
QFIXApp类的onCreate/onLogon里赋值的this.sessionID/sessionID2是QFIXApp类的成员变量,而GUI的ActionListener里用到的sessionID是GUI类自己的成员变量,二者完全是两个不同的变量,没有做同步赋值,自然一直是null - 线程可见性问题:QuickFIX/J的会话回调(
onCreate/onLogon)是在独立的IO线程执行的,而GUI的代码运行在AWT事件调度线程,如果没有正确的跨线程变量同步,就算你把QFIXApp的sessionID传给GUI,也可能出现可见性问题 - 会话生命周期问题:你调用
request44的时候可能会话还没完成登录,或者已经登出,就算你之前赋值过sessionID,也可能被置空或者失效
修复步骤
- 先确认GUI类可以拿到QFIXApp的实例引用,不要自己在GUI类里单独定义sessionID变量,直接从已完成登录的QFIXApp实例里取有效sessionID
- 调用行情请求前先做空值和会话状态校验,修改
actionPerformed里的逻辑:
@Override public void actionPerformed(ActionEvent e) { userSymbol = enterSymbol.getText(); System.out.println(userSymbol); try { // 直接从QFIXApp取已经登录成功的sessionID,不要用GUI类自己的sessionID变量 SessionID validSessionId = QFIXApp.getLogonSessionId(); if (validSessionId == null || !Session.lookupSession(validSessionId).isLoggedOn()) { System.out.println("会话未登录,无法发送行情请求"); return; } System.out.println("Test" + validSessionId); QFIXApp.request44(userSymbol, validSessionId); System.out.println("Pass"); } catch (SessionNotFound e1) { e1.printStackTrace(); System.out.println("Fail"); } }
- 在QFIXApp类里加对应的get方法,同时用volatile修饰sessionID变量保证跨线程可见性:
// QFIXApp类里修改成员变量定义,加volatile保证跨线程可见 private volatile SessionID logonSessionId; public void onLogon(SessionID sessionID) { observableLogon.logon(sessionID); this.logonSessionId = sessionID; } public void onLogout(SessionID sessionID) { observableLogon.logoff(sessionID); this.logonSessionId = null; } // 对外提供获取有效会话ID的方法 public static SessionID getLogonSessionId() { // 此处如果是单例的QFIXApp,直接返回单例实例的logonSessionId即可 return qfixAppInstance.logonSessionId; }
- 额外补充修复
request44方法的隐性问题:NoMDEntryTypes组仅实例化未设置具体行情类型,会导致对方拒收请求,补充设置如下:
quickfix.fix44.MarketDataRequest.NoMDEntryTypes entry_types = new quickfix.fix44.MarketDataRequest.NoMDEntryTypes(); // 买方报价 entry_types.set(new MDEntryType(MDEntryType.BID)); request.addGroup(entry_types); // 卖方报价 entry_types = new quickfix.fix44.MarketDataRequest.NoMDEntryTypes(); entry_types.set(new MDEntryType(MDEntryType.OFFER)); request.addGroup(entry_types);
内容的提问来源于stack exchange,提问作者Beanie
相关产品推荐
相关产品推荐

