In this page of the Spray migration guide, we are told that marshalling a response looks like this:
Marshaller.of can be replaced with Marshaller.withFixedContentType.
Was:
Marshaller.of[JsonApiObject](`application/json`) { (value, contentType, ctx) =>
ctx.marshalTo(HttpEntity(contentType, value.toJson.toString))
}
Replace with:
Marshaller.withFixedContentType(`application/json`) { obj =>
HttpEntity(`application/json`, obj.toJson.compactPrint)
}
Let's look at what we are now supposed to write in more detail. Marshaller.withFixedContentType
takes two type parameters, A
and B
. The second argument list is a function A => B
. Now it's pretty obvious that the above snippet from the official documentation cannot conceivably compile - how can the compiler infer a type for obj
such that the method toJson
can be called on it? Evidently I need to supply type parameters! So: what do I supply?
Evidently I know what I am trying to marshal back to the client, let's call this a MyA
. What should B
be? Well, I should probably look to the documentation's page on marshalling, shouldn't I? Hmmm, searching this page for withFixedContentType
merely shows me how the method has been implemented. Say what? Why do I care a fig how the method was implemented? I have a MyA
and I'm trying to send it back to the client! Why is the documentation listing a bunch of methods and their implementations instead of showing me how to actually use them?
So; no help here. Well, the first example returns an HttpEntity
, so I guess B
must be HttpEntity
! Let's write my code!
Marshaller.withFixedContentType[MyA, HttpEntity](`application/json`) { myA =>
HttpEntity(`application/json`, myA.toJsonString /* whatevs */ )
}
Except nothing compiles now. The compiler complains on a line of my application:
complete(StatusCodes.OK -> myA)
I get this error:
Error:(154, 18) type mismatch;
found : (akka.http.scaladsl.model.StatusCodes.Success, oxbow.MyA)
required: akka.http.scaladsl.marshalling.ToResponseMarshallable
complete((StatusCodes.OK, myA))
OK, Now I have no clue whatsoever. This API is based on implicit conversions, evidently. These implicit conversions can obviously only take effect if I have exactly the correct imports and if I have exactly the correct types. Except the migration guide literally lists neither imports nor types for this fundamental use-case. I clearly have to figure this out from first principles.
Back to the guide to akka marshalling - I peruse the section on Predefined Marshallers, and alight on the following:
T
, if aToEntityMarshaller[T]
is available
OK! This is it! I need a ToEntityMarshaller
! Let's find mentions of ToEntityMarshaller on this page and all will become clear! Oh, hang on, a ToEntityMarshaller[T]
is just a type alias for Marshaller[T, MessageEntity]
: didn't I already provide one of those? Oh, no, I didn't - I provided a Marshaller[MyA, HttpEntity]
. Hmmm, how does an HttpEntity
correspond to a MessageEntity
?
A few more mouse-clicks around the source code reveals that MessageEntity
is a type alias for RequestEntity
which is (in turn) a sub-class of HttpEntity
. So how do I return a RequestEntity
and why does the documentation not seem to return one of those but instead an HttpEntity
? I guess that - just possibly - there may be some other implicit conversion in scope. With a promise to the documentation gods that I will sacrifice a lesser mammal, I change my marshaller definition to:
Marshaller.withFixedContentType[MyA, MessageEntity](`application/json`) { myA =>
HttpEntity(`application/json`, myA.toJsonString /* whatevs */ )
}
IT COMPILES!!! IT ACTUALLY COMPILES
I break down in tears of joy at this point. Until, that is, I remember my promise of sacrifice.
The lack of the correct type annotations and imports in the Spray Documentation guide has just lost me half a day. "Hang, on, how did this take half a day?" I hear you ask; "I just read this whole thing in under five minutes!" Well, this is merely one amongst many issues I hit - causing a biblical quantity of compilation errors. Wading through them all was complicated - there were many wrong turns I made before alighting on the correct solution.