Your Fix handler/OMS/whatever communicates with SackFix in several ways. To start with you are responsible for initialising Akka and the gardian actor - the examples show this, in the example projects.

Both initiator and acceptor applications will have a session or sessions active and the critical actor you have to deal with is the SessionActor. I would advise you to create your own actor, and implement it as in the examples. There is a BusinessCommsHandler which you must pass into SackFix. Implement the handleFix message - all messages from SackFix are subclasses of the SfBusinessFixInfo trait. This trait has a timestamp and also the sessionId associated with the connection - so you can get the compId’s etc.

val businessCommsActor = context.spawn(OMSMessageInActor(), "OMSMsgHandler")
val businessComms = new BusinessCommsHandler {
  override def handleFix(msg: SfBusinessFixInfo): Unit = {
    businessCommsActor ! msg
  }
}

As you can see, you are not forced to do your own actor - but I have above. The businessCommsHandler simply sends the message to your Actor. In the example above your business actor is called OMSMessageInActor. Note, if you cannot understand ! msg then read a little on Akka and you will understand this is simply sending a message to the actor.

The SfSessionId within the SfBusinessFixInfo tells you the following:

  case class SfSessionId(val beginString:String,
                    val senderCompId:String,
                    val senderSubId:Option[String] = None,
                    val senderLocationId:Option[String] = None,
                    val targetCompId:String,
                    val targetSubId:Option[String] = None,
                    val targetLocationId:Option[String] = None)

So at the very least you will have the beginString, senderCompId and targetCompId.

The events that can arrive from SackFix into your business object are:

// For session management
case class FixSessionOpen(sessionId: SfSessionId, sfSessionActor: ActorRef[SfSessionActorCommand]) extends SfBusinessFixInfo
case class FixSessionClosed(sessionId: SfSessionId) extends SfBusinessFixInfo

// A non session level message has arrived
case class BusinessFixMessage(sessionId: SfSessionId, sfSessionActor: ActorRef[SfSessionActorCommand], message: SfMessage) extends SfBusinessFixInfo

// When you send a message out, this will return when the message is in the tcp layer
case class BusinessFixMsgOutAck(sessionId: SfSessionId, sfSessionActor: ActorRef[SfSessionActorCommand], correlationId: String) extends SfBusinessFixInfo

// All session level rejects are forward to you - if the message rejected was
// a session level or business level message - you should get DevOps involved
// by alerting in some form.
case class BusinessRejectMessage(sessionId: SfSessionId, sfSessionActor: ActorRef[SfSessionActorCommand], message: SfMessage) extends SfBusinessFixInfo

You will note that all of these messages contain the sessionActor reference. You can send message to the other side of the fix connection or ask the session to logout by sending a message to the sessionActor.

// send this to the sessionActor, ie sessionActor ! BusinessFixMsgOut(...)
// The correlationId should be a unique id which will be returned to you in a
// BusinessFixMsgOutAck message
case class BusinessFixMsgOut(msgBody: SfFixMessageBody, correlationId: String) extends SfSessionActorCommand

// To ask for logout from the counterparty - note that this should only be done
// if disaster has struck.  When the application is bounced, providing the
// session is still in the awake time in application.conf the session will be
// re-established.
case class BusinessSaysLogoutNow(reason: String) extends SfSessionActorCommand

So, Sackfix does all of the session times, creation, message store, replay and so on. You deal with the business layer, and send messages back as you want to.

How do I send a message?

The code to create a message and send it down to the session actor is as below. Simply initialise the fields that you want to use.

fixSessionActor ! BusinessFixMsgOut(ExecutionReportMessage(
  orderIDField = OrderIDField("1"),
  execIDField = ExecIDField("exec1"),
  execTypeField = ExecTypeField(ExecTypeField.New),
  ordStatusField = OrdStatusField(OrdStatusField.New),
  instrumentComponent = InstrumentComponent(symbolField = symbol),
  sideField = side,
  leavesQtyField = LeavesQtyField(quantity),
  cumQtyField = CumQtyField(0),
  avgPxField = AvgPxField(0)), correlationId)
}

As you can see, SackFix uses strongly typed immutable fields and messages.