Closed bekee closed 2 years ago
I've tried resolving the TradeClient class but still not able to send request to the server.
import {container} from "tsyringe"; import 'reflect-metadata' import { TradeCaptureClient } from "@fix/trade-capture-client"
export class NewsController {
testNews = async (req: Request, res: Response, next: NextFunction) => {
const tradingSession = container.resolve(TradeCaptureClient)
const headline = req.params.headline
await tradingSession.sendNews(headline);
return res.status(200).send("sent")
};
}
}
@injectable()
// @singleton()
export class TradeCaptureClient extends AsciiSession {
private readonly logger: IJsFixLogger
private readonly fixLog: IJsFixLogger
private reports: Dictionary<ITradeCaptureReport>
constructor (@inject( DITokens.IJsFixConfig) public readonly config: IJsFixConfig) {
super(config)
this.logReceivedMsgs = true
this.reports = new Dictionary<ITradeCaptureReport>()
// this.fixLog = config.logFactory.plain(`jsfix.${config.description.application.name}.txt`)
this.fixLog = config.logFactory.plain(`jsfix.client.${new Date().toDateString()}.txt`)
this.logger = config.logFactory.logger(`${this.me}:TradeCaptureClient`)
}
//.....
public sendNews(headline: string){
this.send(MsgType.MarketDefinitionRequest, NewsFactory.requestNews(headline))
}
}
I keep getting the error
{
"error": "Cannot inject the dependency \"config\" at position #0 of \"TradeCaptureClient\" constructor. Reason:\n Attempted to resolve unregistered dependency token: \"IJsFixConfig\""
}
Can someone point me to the right direction
I cant look at this right now but will try to do so within next day
are you able to store the iIConfig somewhere globally for now
i.e. the idea somthing like
const sessionContainer = this.config.sessionContainer
const session = sessionContainer.resolve<FixSession>(DITokens.FixSession)
i.e in makeFactory the config object provided if you can provide this to your constructor somehow in controller then it can call resolve as above.
where session is your object created in launcher
import 'reflect-metadata'
import {
IJsFixConfig, SessionLauncher, EngineFactory,
ISessionDescription, SessionContainer, ISessionMsgFactory
} from 'jspurefix'
import { MDClient } from './md-client'
import { MDServer } from './md-server'
import { MsgFact } from './msg-fact'
class MySessionContainer extends SessionContainer {
protected makeSessionFactory (description: ISessionDescription): ISessionMsgFactory {
return new MsgFact(description)
}
}
class AppLauncher extends SessionLauncher {
public constructor (
client: string = '../../data/session/test-initiator.json',
server: string = '../../data/session/test-acceptor.json') {
super(client, server)
this.sessionContainer = new MySessionContainer()
this.root = __dirname
}
protected override makeFactory (config: IJsFixConfig): EngineFactory {
const isInitiator = this.isInitiator(config.description)
return {
makeSession: () => isInitiator ?
new MDClient(config) :
new MDServer(config)
} as EngineFactory
}
}
const l = new AppLauncher()
l.exec()
or even where you have a construction of your session
new MDClient(config)
becomes something like
const session = new MDClient(config)
const controller = new TheController(session) // just hand in session directly
// can controller then call send directly on session it is given?
The issue is that config object for the session is not being injected at all right after the launch exec function is called.
I placed the launcher script before the express route scripts, hence it can't inject into the controller.
if you look at https://github.com/TimelordUK/jspf-md-demo/blob/master/src/app/app.ts
we see the controller created and listening bound with session
2022-06-30T20:36:00.698Z [test_server:MdController] info: start
2022-06-30T20:36:00.701Z [test_server:FixSession] info: current state Idle (24) moves to WaitingForALogon (18)
2022-06-30T20:36:00.701Z [test_server:TcpAcceptor] info: insecure connection established
2022-06-30T20:36:00.702Z [test_server:MdController] info: MdController app listening on http://localhost:3000/news
import 'reflect-metadata'
import {
IJsFixConfig, SessionLauncher, EngineFactory,
ISessionDescription, SessionContainer, ISessionMsgFactory, FixSession
} from 'jspurefix'
import { MDClient } from './md-client'
import { MDServer } from './md-server'
import { MsgFact } from './msg-fact'
import { MDTokens } from './md-tokens'
import { MdController } from './md-controller'
class MySessionContainer extends SessionContainer {
protected makeSessionFactory (description: ISessionDescription): ISessionMsgFactory {
return new MsgFact(description)
}
}
class AppLauncher extends SessionLauncher {
controller: MdController
public constructor (
client: string = '../../data/session/test-initiator.json',
server: string = '../../data/session/test-acceptor.json') {
super(client, server)
this.sessionContainer = new MySessionContainer()
this.root = __dirname
}
// register a custom object with the DI container.
public makeController (c: IJsFixConfig, session: FixSession) {
const sessionContainer = c.sessionContainer
sessionContainer.register<MdController>(MDTokens.MDController, {
useFactory: () => new MdController(c, session)
})
this.controller = sessionContainer.resolve<MdController>(MDTokens.MDController)
this.controller.start()
}
stopController () {
if (this.controller != null) {
this.controller.stop()
}
}
private makeSession (config: IJsFixConfig): FixSession {
const server = new MDServer(config)
this.makeController(config, server)
return server
}
public launcher () {
const instance = this
this.run().then(() => {
instance.stopController()
console.log('finished.')
}).catch(e => {
console.error(e)
})
}
protected override makeFactory (config: IJsFixConfig): EngineFactory {
const isInitiator = this.isInitiator(config.description)
const instance = this
return {
makeSession: () => isInitiator ?
new MDClient(config) :
instance.makeSession(config)
} as EngineFactory
}
}
when i refresh browser it calls controller and sends a message
2022-06-30T20:36:06.873Z [test_server:MdController] info: got a request for a news flash
2022-06-30T20:36:06.873Z [test_server:MdController] info: sending news headline mash the buy button!
2022-06-30T20:36:06.883Z [test_client:FixSession] info: B: News
2022-06-30T20:36:06.883Z [test_client:FixSession] info: [0] 8 (BeginString) = FIX4.4, [1] 9 (BodyLength) = 0000095
[2] 35 (MsgType) = B[News], [3] 49 (SenderCompID) = accept-comp
[4] 56 (TargetCompID) = init-comp, [5] 34 (MsgSeqNum) = 3
[6] 57 (TargetSubID) = fix, [7] 52 (SendingTime) = 20220630-20:36:06.873
[8] 148 (Headline) = mash the buy button!, [9] 10 (CheckSum) = 177
2022-06-30T20:36:06.884Z [test_client:FixSession] info: ascii forwarding msgType = 'B' to application
2022-06-30T20:36:06.884Z [test_client:MDClient] info: B {
"StandardHeader": {
"BeginString": "FIX4.4",
"BodyLength": 95,
"MsgType": "B",
"SenderCompID": "accept-comp",
"TargetCompID": "init-comp",
"MsgSeqNum": 3,
"TargetSubID": "fix",
"SendingTime": "2022-06-30T20:36:06.873Z"
},
"Headline": "mash the buy button!",
"StandardTrailer": {
"CheckSum": "177"
}
}
2022-06-30T20:36:06.885Z [test_client:MDClient] info: mash the buy button!
Thanks @TimelordUK this approach worked pretty well, I was also able to inject the session into the express request using a middleware
subscribe (session: TradeCaptureClient) {
const exposeSession = async (req: any, res: Response, next: NextFunction) => {
req.session = session;
next();
};
app.use('/api', exposeSession, BaseRouter);
app.get('/news', (req: any, res: any) => {
this.logger.info('got a request for a news flash')
const msg = 'mash the buy button!'
this.logger.info(`sending news headline ${msg}`)
session.sendNews(msg)
res.send(msg)
})
}
Then called it into the controller
import 'reflect-metadata'
import { TradeCaptureClient } from "@fix/trade-capture-client"
import { NextFunction, Request, Response } from 'express';
export class NewsController2 {
testNews = async (req: any, res: Response, next: NextFunction) => {
const tradingSession = req.session as TradeCaptureClient
const headline = req.body.headline
await tradingSession.sendNews(headline);
return res.status(200).send("sent "+ headline)
};
}
export default NewsController2
Please I need help with calling the send function of the session from a controller so I can send request via api to the server. A guide or an example would be grateful.
@TimelordUK