Why does EK9 reject an HTTP access marker (:=: PATH) on a service operation's returning parameter?

← Web Services · Ref: Q1323

An HTTP access marker (:=: PATH, :=: HEADER, :=: QUERY, :=: REQUEST, :=: CONTENT, :=: CONTEXT) tells EK9 where to source an INCOMING value from the HTTP request. It is therefore only valid on the INCOMING parameters of a service operation. Putting one on a returning parameter, an aggregate property, or a plain block variable makes no sense - there is nothing to bind from the request - so EK9 raises E07690 (HTTP access verb not supported in this context) at compile time.

The fix is to bind request data only on the incoming parameter list and let the returning parameter be an ordinary HTTPResponse. The HTTP verb of the operation (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS) describes the operation; the access marker describes where each incoming argument comes from.

See Q658 for path-parameter binding. See Q202 for request parameter binding.

Example

defines module qa.webdeep.httpaccessmarker

  defines constant

    JSON_CONTENT_TYPE <- "application/json"
    ENGLISH_LANGUAGE <- "en"

  defines service

    <?-
      An HTTP access marker (:=: PATH here) is valid ONLY on an incoming
      parameter, where it binds a value from the request. The returning
      parameter is a plain HTTPResponse with NO access marker - adding one
      there would trigger E07690.
    -?>
    Items :/items open

      //CORRECT: :=: PATH on the incoming 'id' only; the return is a plain HTTPResponse.
      byId() as GET for :/{id}
        ->
          id as String :=: PATH
        <-
          response as HTTPResponse: (capturedId: id) with trait HTTPResponse
            override content()
              <- rtn as String: `{"id": "${capturedId}"}`
            override status() as pure
              <- rtn as Integer: 200
            override contentType() as pure
              <- rtn as String: JSON_CONTENT_TYPE
            override cacheControl() as pure
              <- rtn as String: "no-cache"
            override contentLanguage() as pure
              <- rtn as String: ENGLISH_LANGUAGE
            default operator ?

  defines application

    ItemsApp
      register Items()

  defines program

    HttpAccessMarkerDemo()
      stdout <- Stdout()
      stdout.println("Service registered (no E07690):")
      stdout.println("  GET /items/{id} binds {id} via :=: PATH on the incoming parameter")
      stdout.println("  the returning HTTPResponse carries no access marker")

Common mistakes

E07690 — An HTTP access marker (:=: PATH) sources an INCOMING value from the request, so it is only valid on an incoming parameter. Placing it on the returning parameter (or a property/local) has nothing to bind and triggers E07690. Remove the marker from the return and keep it only on the incoming argument. See ek9 -h E07690 for details.

Incorrect:

byId() as GET for :/{id}
  ->
    id as String :=: PATH
  <-
    response as HTTPResponse :=: PATH

Correct:

      byId() as GET for :/{id}
        ->
          id as String :=: PATH
        <-
          response as HTTPResponse: (capturedId: id) with trait HTTPResponse
Other ways to ask this
  • What triggers E07690 HTTP access verb not supported in this context?
  • Why can't I put :=: PATH or :=: HEADER on a service return value in EK9?
  • Where are HTTP access markers (PATH, HEADER, QUERY, CONTENT) allowed in an EK9 service?

Coming from another language?

Java Spring: @PathVariable / @RequestHeader can only annotate handler parameters; placing them elsewhere is simply ignored or a runtime wiring error. JAX-RS @PathParam on a return is meaningless and silently dropped. EK9 instead rejects a misplaced access marker at compile time with E07690, so request-binding can only ever describe an incoming value.

Keywords: webservice, CONTENT, HEADER, binding, access, marker, E07690, service, returning, http, QUERY, PATH