API : Exposition une ressource au sein d'une autre ressource sans exposition autonome

API : Exposition une ressource au sein d'une autre ressource sans exposition autonome
0
Tags: #<Tag:0x00007f768f1cb120>

Bonjour
j’ai 5 objets métiers liés selon le diagramme suivant :

Notre client ayant besoin de voir à partir d’un product la liste des structural units auxquel il est lié, nous avons créé un “raccourci”. Ce raccourci est un objet métier “IT4ITProductStructuralUnit” de type select qui remonte les informations product id, product name, structural unit id, structural unit name.

Lors de la création de l’api, on souhaite que le get sur un product retourne le product avec la liste de ses structuralUnit.

		addObject("structuralUnits", "IT4ITStructuralUnit");
		addField("structuralUnits", "id", "row_id");
		addField("structuralUnits", "identifier", "it4itGenIdentifier");
		addField("structuralUnits", "name", "it4itGenName");

		addObject("products", "IT4ITProduct");
		addField("products", "id", "row_id");
		addField("products", "identifier", "it4itGenIdentifier");
		addField("products", "name", "it4itGenName");
		addField("products", "status", "it4itProStatus");
		addField("products", "description", "it4itGenDescription");
		addField("products", "isRD", "it4itGenRD");
		addField("products", "creationDate", "it4itGenCreationDate");
		addField("products", "type", "it4itProType");
		addField("products", "function", "it4itGenFunction");

		addObject("productsStructuralUnits", "IT4ITProductStructuralUnit");
		addField("productsStructuralUnits", "id", "row_id");
		addRefField("productsStructuralUnits", "productId", "productId", "it4itGenProductId", "Id of the product");
		addField("productsStructuralUnits", "productIdentifier", "it4itGenProductId.it4itGenIdentifier", "Identifier of the product", null);
		addField("productsStructuralUnits", "productName", "it4itGenProductId.it4itGenName", "Name of the product", null);
		addRefField("productsStructuralUnits", "structuralUnitId", "structuralUnitId", "it4itStructuralUnitId", "Id of the structural unit where belongs the delivery team");
		addField("productsStructuralUnits", "structuralUnitIdentifier", "it4itStructuralUnitId.it4itGenIdentifier", "Identifier of the structural unit where belongs the delivery team", null);
		addField("productsStructuralUnits", "structuralUnitName", "it4itStructuralUnitId.it4itGenName", "Name of the structural unit where belongs the delivery team", null);
		addRefField("productsStructuralUnits", "products", "productId", "it4itGenProductId", "belongsTo", true, "Structural unit where the product belongs");

Dans la génération du swagger, l’objet IT4ITProductStructuralUnit expose 2 méthodes GET et GET/{id}.

Nous ne souhaiterions pas qu’il soit possible d’accéder directement à l’objet IT4ITProductStructuralUnit .
Existe-t’il une façon de masquer les 2 méthodes ?
Si non, nous serions obligé de modifier le swagger. Existe-t’il un hook que nous pourrions appeler pendant ou après la génération du swagger afin de le modifier ?

Merci d’avance

[Platform]
Status=OK
Version=4.0.P24
BuiltOn=2020-02-26 22:59 (revision ff84cba0fa5c6a06fda80f27b41502439d1ac3a0)
Encoding=UTF-8
EndpointIP=172.17.0.16
EndpointURL=http://af5bb7d86a98:8080
TimeZone=Europe/Paris
SystemDate=2020-02-28 16:58:02

Je n’ai pas encore pris le temps d’analyser en détail votre demande mais une chose est sûre il ne faut pas “bricoler” à la main ou via un hypothétique hook le schéma Swagger car celui-ci doit être le reflet exact des services exposés.

Si vous en arrivez à envisager de le faire c’est forcément que vous n’abordez pas votre besoin métier de la bonne manière.

Le besoin métier est “simple” : les utilisateurs veulent récupérer les StructuralUnit directement depuis le Product sans avoir toutes la chaine ProductInitiative/DeliveryTeam/StructuralUnit. Nous avons donc créé un objet select ProductStructuralUnit.
Nous sommes obligés de l’exposer pour qu’il apparaissent dans l’objet product mais il ne devrait pas être considéré comme une ressource autonome.

Notre api référent souhaiterait que notre swagger soit un contrat d’interface de service et non pas de “base de données” --> notre service est le référentiel des product et donc expose les product avec toutes les informations associées (càd les StructuralUnit). En revanche puisque l’objet ProductStructuralUnit est une construction, nous ne souhaitons pas que des actions soient possibles dessus (même pas le GET all) car il n’y a pas de besoin métier d’accéder directement à cet objet.

Avez vous une solution autre que le modification manuelle du swagger ?

Merci d’avance

Non il n’y a pas, en l’état, de manière de dire qu’un objet mappé doit être caché du schema d’interface

J’ai requalifié en feature request, on va regarder quels seraient les impacts d’avoir un mécanisme pour cela. On vous tiendra au courant.

Par contre vous pourriez trouver des manière détournées de répondre à votre besoins sans exposer un objet métier dénué de sens métier: genre via un attribut JSON non persistant calculé à la volée, etc.

OK pour faire simple, car c’est un besoin très spécifique, on va ajouter une constante pour un libellé description “magique” qui permettra de rendre un objet ou un attribut invisible dans le schéma tout en étant toujours utilisable.

Cette évolution sera backportée en P24

C’est fait et disponible sur les images Docker. La constante “magique” pour masquer des objets ou des attributs au niveau du schema OpenAPI/Swagger est DESC_HIDDEN_FROM_SCHEMA, à mettre à la place de la description dans le mapping:

Object:

addObject("orders", "DemoOrder", DESC_HIDDEN_FROM_SCHEMA);

Field:

addField("products", "supplierCode", "demoPrdSupId.demoSupCode", DESC_HIDDEN_FROM_SCHEMA, null);