Hello World Service

Hello World Service is the reference template of a SmartGears 4 service. It exposes a few REST methods that show what a service gets from SmartGears: the identity and the roles of the caller, the Context of the request, the container it runs in, the methods excluded from authorization, the errors returned to the client, a custom HTTP method, plugins and the preparation of the service in each of its Contexts.

Every method is described in the REST API documentation (ReDoc and Swagger UI), reached from the menu of these pages.

Authorization

D4Science adopts OIDC (OpenID Connect) for authentication and UMA 2 (User-Managed Access) for authorization. Every request carries a JSON Web Token (JWT) access token in the Authorization header:

Authorization: Bearer <token>

The token says who the caller is, in which Context the request is made and which roles the caller has there. Instructions to obtain a token are at https://dev.d4science.org/how-to-access-resources.

The paths listed under excludes in application.yaml need no token: in this service /guest and everything under it, and /excluded, which has no method and only shows the syntax. A path listed under includes needs a token even under an excluded path: an include wins over any exclude. In this service /guest/private is included back.

excludes:
  - path: /excluded
  - path: /guest
  - path: /guest/*
includes:
  - path: /guest/private

SmartGears excludes by itself the landing page and the dashboard (/index.html, /dashboard.html, /landing/) and the documentation (/docs/, /api-docs/, /branding/). A plugin may say that its own path needs no token, as the greeter does (see Plugins).

Methods

| Method | Path | Token | Result | | — | — | — | — | | GET | /hello | required | A greeting with the caller, the Context, the infrastructure and the roles of the caller | | GET | /details | required | The Context, the caller and the container, as JSON | | GET | /auth | required | A message, for a caller with the role myRole | | GET | /auth/member | required | A message, for a caller with the role Member | | GET | /auth/org_member | required | A message, for a caller with the role OrganizationMember | | GET | /guest | none | A message | | GET | /guest/bad-request | none | Always 400 Bad Request | | GET | /guest/not-found | none | Always 404 Not Found | | PURGE | /guest/test-purge | none | Always 204 No Content | | GET | /guest/private | required | A message naming the caller: a path under /guest that needs a token | | GET | /plugins/{id}?who=<name> | as the plugin says | The greeting of the plugin id to <name> (default world); 404 Not Found for an unknown id. /plugins/greeter needs no token |

The /auth methods are restricted with the @AuthorizationControl annotation of authorization-control-library, which answers 403 Forbidden to a caller without the role. The annotation is enforced only when the project is woven with the aspectj-maven-plugin, which the pom.xml of this template keeps commented out: without it every caller with a valid token gets the message.

PURGE is not a standard HTTP method, so it is not in the REST API documentation, which knows only the standard ones. It is widely used for this action, e.g. by Varnish. The method is declared with the @PURGE annotation of the service (jakarta.ws.rs.HttpMethod("PURGE")).

Plugins

A plugin is a jar, carried in the war of the service, that adds a function to the service without changing its code. The service names the interface its plugins implement in its application.yaml:

plugins: org.gcube.service.helloworld.plugin.HelloWorldPlugin

The interface is in hello-world-plugin-api, and the war carries one plugin, hello-world-greeter-plugin, whose identifier is greeter:

curl 'https://<host>/hello-world-service/plugins/greeter?who=Luca'

The service finds its plugins with a ServiceLoader of HelloWorldPlugin and answers for each at /plugins/<id>. SmartGears finds the same plugins when the service starts and, with no code of the service:

  • describes each one from the Maven packaging of its jar, at /smartgears/hello-world-service/plugins, on the landing page of the service and in the Information System;

  • reads its configuration, hello-world-greeter-plugin.yaml for the greeter (greeting: Hello), and gives it to the plugin. The service gives it to every instance of the plugin it creates, and does not use a plugin whose configuration is missing: the greeting comes from that file;

  • gives it a row in the health of the service, with the checks of the plugin (greeter for the greeter);

  • counts its requests under its name in the metrics, with the label plugin="hello-world-greeter-plugin" (plugin="none" for the requests to the service itself).

How a plugin is written is in the documentation of hello-world-plugin-api and of hello-world-greeter-plugin.

Preparation in Each Context

A service may need to prepare itself in each Context it runs in, e.g. to read or create its configuration there. The class GreetingPreparation, annotated @ContextPreparer, does it for this service: SmartGears calls it in each Context of the node, with the secret of that Context, and shows the state of the service in each Context in its health. This service only notes when it was prepared in a Context.

Errors

An error is returned with its HTTP status and a body describing it:

{
 "success": false,
 "message": "Your request is not valid",
 "result": null
}

The most common statuses are:

  • 400 Bad Request: the request is not valid;

  • 401 Unauthorized: the request has no token, or the token cannot be verified;

  • 403 Forbidden: the caller lacks the role the method requires;

  • 404 Not Found: the requested path or instance does not exist;

  • 405 Method Not Allowed: the HTTP method is not supported for the URL; the Allow header lists the supported ones;

  • 500 Internal Server Error: a failure of the service, to be reported in the D4Science ticketing system with the request, the time it was made and how to replicate it.

SmartGears Methods

As any SmartGears service, its SmartGears methods are served by the SmartGears webapp of the container under /smartgears/hello-world-service/, e.g. /smartgears/hello-world-service/health (503 when the service is not ready) and /smartgears/hello-world-service/lifecycle. They check their callers themselves. The health has a row for each plugin and the state of the service in each Context. The metrics are the container’s, at /smartgears/metrics; the requests to the service carry the label service="hello-world-service" and the label plugin: the artifactId of the plugin whose path the request is on, or none. What each of them returns is in What a SmartGears Node Exposes; what a service declares to SmartGears, plugins included, is in What a Service Declares to SmartGears.

Postman Collection

The Postman collection of the service is at <service>/api-docs/postman/hello-world-service.postman_collection.json, with an example environment for /gcube/devsec/devVRE at <service>/api-docs/postman/hello-world-service-for-devvre.postman_environment.json. The environment is completed with the D4Science username and password of the user, to obtain the token.

Service Discovery in the Information System

SmartGears publishes the service in the Information System as an EService, identified by its SoftwareFacet. It is found with the following query, sent to the Resource Registry:

{
 "type": "EService",
 "consistsOf": [
  {
   "type": "IsIdentifiedBy",
   "target": {
    "type": "SoftwareFacet",
    "group": "org.gcube.service",
    "name": "hello-world-service"
   }
  }
 ]
}

Maven Coordinates

<groupId>org.gcube.service</groupId>
<artifactId>hello-world-service</artifactId>

Writing These Pages

This service is the reference example of the documentation of a gCube service too: its landing page, in documentation/landing/, and these pages. Writing the Documentation shows every construct the documentation site supports, with the source that produces it.