Skip to content
mandubian edited this page Jul 13, 2012 · 2 revisions

IMPORTANT NOTE : this set of tools doesn't pretend to solve SOAP problems everywhere and to respect any SOAP standards. It's just a tool to manipulate SOAP frames while making clients believe this is a real SOAP server. Anyone not happy with the way ersatz deals with SOAP is welcome to contribute more standard formats :D

What is a SOAP frame for ersatz?

SOAP Envelope

It's an envelope with a body (header not managed yet) and the soapenv namespace...

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header/>
  <soapenv:Body>
     <yoursoapmessage>blabla</yoursoapmessage>
  </soapenv:Body>
</soapenv:Envelope>

Note The Header is empty right and not used now because I don't need it yet...

SOAP Fault

Where there are errors, you can replace the content of the body by a fault having following format:

 <soapenv:Fault>
   <faultcode>{ fault.faultcode }</faultcode>
   <faultstring>{ fault.faultstring }</faultstring>
   <faultactor>{ fault.faultactor }</faultactor>
   <detail><yourerrordetail>yourerror</yourerrordetail></detail>
 </soapenv:Fault>

ESOAP object

object ESOAP {
  def toSOAP[T](t: T, ns: NamespaceBinding, base: xml.Elem)(implicit r: XMLWriter[T]): xml.NodeSeq
  def toSOAP[T](t: T)(implicit r: XMLWriter[T], ns: NamespaceBinding): xml.NodeSeq
  def toSOAP[T](t: T, ns: NamespaceBinding)(implicit r: XMLWriter[T]): xml.NodeSeq

  def fromSOAP[T](x: xml.NodeSeq)(implicit r: XMLReader[T]): Option[T]

  val SoapNS = xml.NamespaceBinding("soapenv", "http://schemas.xmlsoap.org/soap/envelope/", xml.TopScope)
}
  • SoapNS is the default Namespace for Soap envelopes
  • toSOAP[T](t: T, ns: NamespaceBinding) function allow managing custom namespace to your SOAP envelopes if required.

For ex:

 implicit val ns = NamespaceBinding(
   prefix = "test", 
   uri = "http://test.com/",
   parent = ESOAP.SoapNS
 )

 val env = toSOAP(Foo(...)) 
 assert( env == <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="http://test.com">...</soapenv> )

ESOAP.toSOAP(Foo(...)) is just an equivalent to EXML.toXML(SoapEnvelope(Foo(...)))

ESOAP classes

SoapEnvelope

case class SoapEnvelope[T](t: T)(implicit _namespace: NamespaceBinding = ESOAP.SoapNS) {
  def namespace = _namespace
}

Note namespace is implicit and by default set to default Soap namespace. But it means that you can define your own implicit namespace in your scope and it will be used in the SoapEnvelope

SoapFault

case class SoapFault[T](
   faultcode: String,
   faultstring: String,
   faultactor: String,
   detail: T
)

faultCode

A text code used to indicate a class of errors. The possible values are standardized and defined in SoapFault object:

object SoapFault {
// Found an invalid namespace for the SOAP Envelope element
val FAULTCODE_VERSION_MISMATCH = "SOAP-ENV:VersionMismatch" 
// An immediate child element of the Header element, with the mustUnderstand attribute set to "1", was not understood
val FAULTCODE_MUST_UNDERSTAND = "SOAP-ENV:MustUnderstand"
// The message was incorrectly formed or contained incorrect information
val FAULTCODE_CLIENT = "SOAP-ENV:Client"
// There was a problem with the server so the message could not proceed
val FAULTCODE_SERVER = "SOAP-ENV:Server"
}

faultString

A text message explaining the error

faultActor

A text string indicating who caused the fault. This is useful if the SOAP message travels through several nodes in the SOAP message path, and the client needs to know which node caused the error. A node that does not act as the ultimate destination must include a faultActor element.

detail

An element used to carry application-specific error messages. The detail element can contain child elements, called detail entries. Naturally, you must provide the implicit XMLReader[T]/XMLWriter[T]

SOAPFault usage

To generate a SOAPFault frame, you can simply do:

implicit FooErreurFormatter extends XMLFormatter[FooErreur] {
   ...
}
ESOAP.toSoap(
  SoapFault(
    faultcode = SoapFault.FAULTCODE_CLIENT,
    faultstring = "invalid",
    faultactor = "actor",
    detail = FooErreur(1, "erreur")
  )
)

Soap Formatters

SoapEnvelopeReader[T]/SoapEnvelopeWriter[T]

This provides default XML reader/writer for SoapEnvelope[T]

SoapFaultReader[T]/SoapFaultWriter[T]

This provides default XML reader/writer for SoapFault[T]