What must service method bodies contain and what is prohibited?

← Web Services · Ref: Q685

EK9 service methods must have concrete implementations, and one access modifier is restricted.

CONCRETE BODIES REQUIRED (E07740)

Every service method and operator must have a body. A method declared with no implementation is E07740 ('implementation not provided, but services cannot be abstract'): the runtime must be able to invoke every endpoint.

HELPER METHODS

A service may also have methods that are not web endpoints (no HTTP verb and path), plain or 'private', for logic shared by its endpoints. Marking such a helper 'protected' is E07240: nothing can extend a service, so 'protected' has no meaning there.

RETURN TYPE

Service methods return HTTPResponse. The response is typically created as a dynamic class implementing the HTTPResponse trait.

HTTPRESPONSE PATTERN

The standard pattern uses a dynamic class with trait implementation:

  <- response as HTTPResponse: () with trait HTTPResponse
    override content() ...
    override status() ...
    override contentType() ...

OPERATOR ENDPOINTS

Services can use operators (+=, -=, :~:, :^:) for CRUD:

  operator += for POST (create)
  operator -= for DELETE
  operator :~: for PATCH (merge)
  operator :^: for PUT (replace)

See Q657 for URI mapping. See Q660 for CRUD operator pattern. See Q684 for URI path rules.

Example

defines module qa.webdeep.methodbodies

  defines service

    <?-
      Service with fully implemented method bodies.
      Every method returns a concrete HTTPResponse.
    -?>
    StatusService :/status open

      //GET /status/health — health check endpoint
      health() as GET for :/health
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as Bytes: Bytes().withUtf8(`{"status": "healthy"}`)
          override status() as pure
            <- rtn as Integer: 200
          override contentType() as pure
            <- rtn as String: "application/json"
          override cacheControl() as pure
            <- rtn as String: "no-cache"
          override contentLanguage() as pure
            <- rtn as String: "en"
          default operator ?

      //GET /status/version — version info endpoint
      version() as GET for :/version
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as Bytes: Bytes().withUtf8(`{"version": "1.0.0"}`)
          override status() as pure
            <- rtn as Integer: 200
          override contentType() as pure
            <- rtn as String: "application/json"
          override cacheControl() as pure
            <- rtn as String: "max-age=300"
          override contentLanguage() as pure
            <- rtn as String: "en"
          default operator ?

  defines application

    StatusApp
      register StatusService()

  defines program

    ServiceMethodBodiesDemo()
      stdout <- Stdout()
      stdout.println("Service method bodies:")
      stdout.println("  GET /status/health -> concrete body with HTTPResponse")
      stdout.println("  GET /status/version -> concrete body with HTTPResponse")

Common mistakes

E50001 — The function getMethodInfo is not defined in this module. See ek9 -h E50001 for details.

Incorrect:

stdout.println(getMethodInfo())

Correct:

stdout.println("Service method bodies:")

E50001 — The function getHealthInfo is not defined in this module. See ek9 -h E50001 for details.

Incorrect:

stdout.println(getHealthInfo())

Correct:

stdout.println("  GET /status/health -> concrete body with HTTPResponse")
Other ways to ask this
  • What is E07740 service method with no body?
  • What is E07240 protected method in a service?
  • Can a service have private helper methods?
  • What restrictions apply to service method implementations?

Coming from another language?

Java: Spring @RestController methods must have bodies. Python: Flask route handlers need implementations. Go: handler functions must be concrete. Rust: handler functions must be concrete. EK9: service methods must have concrete bodies (E07740) and return HTTPResponse; non-web helper methods may be plain or private, never protected (E07240).

Keywords: service, E07740, E07240, abstract, body, HTTPResponse, concrete, method, http