How do services work in EK9 for REST and HTTP?

← Classes and OOP · Ref: Q112

EK9 has a built-in service construct for REST/HTTP endpoints. Services map HTTP methods to operators and named methods, with URI binding and parameter extraction built into the language.

SERVICE CONSTRUCT

Define a service with its URI:

  defines service
    Items :/items

URI MAPPING

The service name maps to a base URI path. Methods map to sub-paths:

  listAll() :/             maps to GET /items
  byId() as GET for :/{id}  maps to GET /items/{id}

HTTP METHOD MAPPING

EK9 maps operators to HTTP verbs semantically:

  operator += :/           POST (add to collection)
  operator -= :/{id}       DELETE (remove from collection)
  operator :~: :/{id}      PATCH (merge/partial update)
  operator :^: :/{id}      PUT (replace)
  Named methods default to GET.

PATH AND CONTENT BINDING

  -> id as String                         PATH parameter (assumed)
  -> content as String :=: CONTENT        request body
  -> request as HTTPRequest :=: REQUEST   full request object

HTTPRESPONSE TRAIT

Service methods return HTTPResponse. Use dynamic classes to implement it inline with trait delegation.

APPLICATION REGISTRATION

Register the service in an application:

  register Items()

See Q111 for components. See Q106 for traits. See Q96 for operator semantics. See Q114 for aspects. See Q199 for REST GET endpoints. See Q200 for CRUD operator mapping. See Q201 for building HTTPResponse. See Q203 for application wiring.

See Q325 for @Component/@Service equivalent.

Example

defines module qa.oop.services

  defines text for "en"

    ServiceContent
      welcome()
        "Welcome to the EK9 Service"

  defines service

    Info :/info open

      welcome() as GET for :/welcome
        <- response as HTTPResponse: () with trait HTTPResponse
          content <- ServiceContent("en")

          override cacheControl() as pure
            <- rtn as String: "no-store"
          override contentType() as pure
            <- rtn as String: "text/plain"
          override contentLanguage() as pure
            <- rtn as String: "en"
          override content()
            <- rtn as String: content.welcome()
          override status() as pure
            <- rtn as Integer: 200
          default operator ?

  defines application

    ServiceApp
      register Info()

  defines program

    ServiceDemo()
      stdout <- Stdout()

      // === SERVICE CONSTRUCT ===
      // Services are defined with 'defines service'
      // and registered in applications

      stdout.println("Service registered in application")
      stdout.println("HTTP methods map to operators:")
      stdout.println("  += is POST, -= is DELETE")
      stdout.println("  :~: is PATCH, :^: is PUT")
      stdout.println("  Named methods default to GET")

Common mistakes

E05120 — When implementing HTTPResponse trait methods in a dynamic class, the 'override' keyword is required for each method. Omitting it triggers E05120. See ek9 -h E05120 for details.

Incorrect:

content()

Correct:

override content()

E05110 — The HTTPResponse trait method is 'status()', not 'getStatus()'. Using 'override' with a non-existent method name triggers E05110 — false override claim. EK9 does not use Java-style getter naming. See ek9 -h E05110 for details.

Incorrect:

override getStatus() as pure
            <- rtn as Integer: 200

Correct:

override status() as pure
            <- rtn as Integer: 200

E50060 — EK9 does not have a toString() method. Use the $ operator or call the appropriate method directly. See ek9 -h E50060 for details.

Incorrect:

content.toString()

Correct:

content.welcome()
Other ways to ask this
  • How do I create a REST service in EK9?
  • What is the service construct in EK9?
  • How does EK9 map HTTP methods to operators?

Coming from another language?

Java: JAX-RS @GET/@POST annotations or Spring @RestController with @RequestMapping, annotation-driven. Python: Flask/Django with @app.route decorators, framework-dependent. Rust: actix-web or axum with handler functions and extractors. Go: net/http handlers with manual routing or gorilla/mux. Kotlin: Ktor routing DSL or Spring Boot annotations. EK9: language-level 'defines service' with operator-to-HTTP mapping, URI binding in declaration, parameter binding with PATH/CONTENT/REQUEST keywords.

Keywords: delete, patch, service, endpoint, rest, object-oriented, http, post, put, get, operator, uri