Class Envelope
An envelope is immutable. The engine derives a new one rather than mutating an existing one, which is what makes an attempt counter trustworthy when the same message is delivered several times.
This is a value type. It would be a record, but the published bytecode targets
Java 11 so that Spring Boot 2.7 applications can consume the library; see ADR-015.
- See Also:
-
Nested Class Summary
Nested Classes -
Method Summary
Modifier and TypeMethodDescriptionage()Returns the age of the message, measured from its first publish.intattempt()Returns a builder for a message caused by this one.claim()Where the payload is, when the application stores it outside the message.booleanerror()Why this message was dead-lettered or parked.inthashCode()headers()id()Returns a copy of this envelope representing the next delivery attempt.static Envelope.BuilderStarts a new envelope for the given logical message type.origin()intWhere this message was replayed from, when it was.route()Where this message is going, when it is travelling a pipeline.toString()type()intversion()
-
Method Details
-
of
Starts a new envelope for the given logical message type.- Parameters:
type- logical message type, for exampleorder.placed- Returns:
- a builder with an identifier and timestamp already generated
-
id
- Returns:
- the unique message identifier, also the default idempotency key
-
type
- Returns:
- the logical message type
-
version
public int version()- Returns:
- the payload schema version, at least 1
-
correlationId
- Returns:
- the business correlation identifier, defaulting to
id()
-
causationId
- Returns:
- the identifier of the message that caused this one, if any
-
attempt
public int attempt()- Returns:
- the delivery attempt number, starting at 1 for a first delivery
-
firstSeen
- Returns:
- when this message was first published, used for age-based give-up
-
origin
- Returns:
- the publishing process, conventionally
service@host, if known
-
error
Why this message was dead-lettered or parked.Present only on a message read back from a dead-letter or parking queue. It is an envelope field rather than an ordinary header because AceMQ owns the
x-acemq-namespace: were it left as a header it would be filtered out ofheaders()and become invisible to the very code that needs it most.- Returns:
- the failure reason recorded when the message was given up on
-
claim
Where the payload is, when the application stores it outside the message.An optional field an application may set to tell an operator reading a dead-letter queue where a payload went — conventionally a URI. AceMQ neither writes nor interprets it; it is carried, like
origin(), because the name is reserved and a header in thex-acemq-namespace would otherwise be stripped before a handler could see it.Not the claim-check pattern.
ClaimCheckCodecframes the reference in the body and sets no header at all, deliberately: a header can be stripped by a shovel or a federation link, and a present-or-absent header cannot say whether a payload travelled inline. That is unchanged and is not what this field is for.Java reserved this name and materialised nothing, so a claim set by a Go, .NET, Python or Ruby publisher was dropped on the way in with nothing reporting the loss. All five now read and write it.
- Returns:
- where the payload is, when the publisher said so
-
replayedFrom
Where this message was replayed from, when it was.Set by
mq.replay(...)when a message is moved back out of a dead-letter queue or parking lot. On the wire this isacemq-replayed-from, in the shared namespace rather than the reserved one, so it reaches a handler's headers as well as this field — the one piece of evidence that a message has been round the loop before is of no use to the code handling it if the engine strips it on the way in.- Returns:
- the queue it came back from, when it is a replay
-
replayedAt
- Returns:
- when it was last replayed, when it is a replay
-
replayCount
public int replayCount()- Returns:
- how many times this message has been replayed; zero for one that never has.
Distinct from
attempt(), which a replay resets — a message on its fifth trip through a dead-letter queue would otherwise look brand new
-
route
Where this message is going, when it is travelling a pipeline.A field rather than a header, for the same reason the error is one: the AceMQ prefix is closed to application headers, so a slip put there by hand would be silently dropped on the way in. A step reads its route from here.
- Returns:
- the routing slip, or empty when the message is not part of a pipeline
-
headers
- Returns:
- application headers, excluding the AceMQ-owned ones; never
null
-
age
Returns the age of the message, measured from its first publish.Retry policies use this to abandon a message that has been circulating too long, regardless of how many attempts remain.
- Returns:
- elapsed time since
firstSeen()
-
nextAttempt
Returns a copy of this envelope representing the next delivery attempt.Everything else is preserved, so
firstSeen()continues to measure from the original publish rather than from the retry.- Returns:
- a new envelope with
attempt()incremented by one
-
causing
Returns a builder for a message caused by this one.The correlation identifier is carried across so a whole flow can be followed, and the causation identifier is set to this message's identifier so the immediate parent is recorded. The attempt counter restarts, because the new message is a first publish.
- Parameters:
type- logical message type of the new message- Returns:
- a builder pre-wired for causation tracking
-
toBuilder
- Returns:
- a builder initialised with every value from this envelope
-
equals
-
hashCode
public int hashCode() -
toString
-