2016-07-13 3 views
1

Im allgemeinen Situationen, wenn ein Unternehmen eine Beziehung zu einem anderen hat, ich Nest REST-Ressourcen auf diese Weise:REST API-Design für Unternehmen aus verschiedenen Bereichen, aber mit gemeinsamer Beziehung

POST /user/{userId}/accounts 

Und es ist in Ordnung für Unternehmen aus dem gleiche Domain. Aber wenn es um Entitäten aus verschiedenen Domänen geht, ergibt das keinen Sinn. Zum Beispiel habe ich Buslinien (@Entity Line) und Operatoren (@Entity Operator). Jede Zeile hat einen Operator:

@ManyToOne 
@JoinColumn(name = "operator_id") 
private Operator operator; 

so, wenn ich neue Buslinie erstellen müssen i Betreiber übergeben müssen.

Es gibt kein Problem, wenn ich Zeile mit neuen Operator erstellen muss, aber wenn ich nur auf Operator verweisen möchte, muss ich Operator_id irgendwie übergeben. Einige Ideen, wie dies zu handhaben:

1. Nest Linie in Operator

POST /operators/{operatorId}/lines {name: "15B", type: "BUS"}

Es ist OK aus technischer Sicht, aber ich möchte halten Operatoren und Linien getrennt, weil Linie nicht der Fall ist wirklich "gehören" (nisten) zum Operator.

2. Pass operatorId direkt

POST /lines {name: "15B", type: "BUS", operator: 12}

Es gibt einige Probleme mit dieser Sache. Es gibt einen Fall, wenn ich neue Linie mit neuem Operator erstellt werden soll, und die Abfrage wird wie folgt aussehen:

POST /lines {name: "15B", type: "BUS", operator: {name: "SuperBUS"}}

Und ich brauche beiden Situationen. Dies bringt zusätzliche Entität (Coz Original hat Operator operator, nicht int operator) und "magische" Logik, die entscheiden wird, ob ich Zeile mit neuen Operator oder alten erstellen möchte.

Gibt es Best Practices für den Umgang mit solchen Situationen?

+1

Wenn es keine Relation anderes als ein Verein ist (Operator besitzen nicht die Linien), sollten Sie die Operator, erstellen und es dann neben irgendeine Art von ID mit Referenz, was technisch gesehen zu zwei HTTP-Anfragen führt. Siehe [DDD: Aggregate] (http://thepaulrayner.com/blog/aggregates-and-entities-in-domain-driven-design/). – cdelmas

+0

Guter Punkt. Ich war so konzentriert darauf, dass es sich um eine Ein-Anruf-Operation handelte und verpasste die offensichtliche Lösung. – ovnia

Antwort

2

Hier sind ein paar Ideen, die Ihnen nicht helfen kann oder zu entscheiden, was zu nutzen: den Client zu einem gewissen Implementierungsdetail von

Ids Passing

Passing Id s um Paare das Objekt. Dies ist in der Regel etwas zu vermeiden. Betrachten Sie den folgenden Code ein:

public Line createLine(String name, LineType lineType, int operatorId); 

Der Anrufer wissen muss über die operatorId, die in der Regel nicht Teil des Modells ist. Die id ist in der Regel nur eine Implementierung Detail der Beharrlichkeit, mit anderen Worten, ein Operator nicht wirklich hat eine id, hat es einen Namen höchstens, aber das kann tatsächlich ändern.

In "normalen" OO-Code, ist diese Methode wie diese stattdessen aussehen:

public Line createLine(String name, LineType lineType, Operator operator); 

den tatsächlichen Operator Passing stattdessen mit Hilfe einer Referenz. Was entspricht einer Objektreferenz in RESTful HTTP? Die URI natürlich. Deshalb soll man das würde uns zu:

POST /lines 
{"name": "15B", "type": "BUS", "operator": "http://something/124"} 

Es gibt jedoch ein weiteres Problem mit diesem Ansatz in Java und HTTP-API: Wir können nicht sicher sein, welche Art von Objekt, das wir bekommen. Wenn in Java Operator eine Schnittstelle ist, wissen wir nicht, welche Implementierung wir erhalten. Diese Implementierung ist möglicherweise nicht in unserer Datenbank enthalten. Das Gleiche gilt für die HTTP-API. Wenn wir eine URI akzeptieren, können wir nicht wirklich sicher sein, woher diese Ressource stammt, vielleicht unterstützt sie nicht einmal unsere media-types.

Dies ist wahrscheinlich nicht das, was Sie wollen.

Mit Context

Dies ist, was Sie "Verschachtelung" nennen. Das Nachdenken über Java-Code, ist dies gleichbedeutend mit:

public interface Operator { 
    ... 
    Line createLine(String name, LineType lineType); 
    ... 
} 

In HTTP:

POST /operator/123/lines 
{"name": "15B", "type": "BUS"} 

Dies ist wahrscheinlich besser geeignet wäre, auch wenn die Betreiber nicht wirklich "eigene" die Linien. Der Server kann nach doppelten Zeilen oder ähnlichen semantischen Regeln suchen.

Hyper

Wenn Sie wirklich die Linien wollen unabhängige Einheiten sein, müssen Sie irgendwie die Betreiber verweisen. Ids würde Kupplung vorstellen, aber bietet URI s ist zu allgemein, dann ist die einzige Lösung, Formen einzuführen.

Dies ist möglicherweise komplizierter zu implementieren. Es geht darum, Formulare ähnlich denen von HTML zu erstellen. Stellen Sie einfach die Optionen zur Verfügung, die mit Hypermedia des Kunden passen.

Etwas wie folgt aus:

GET /lines 
{"create": { 
    "operator": { 
     "type": "select", 
     "values": [ ... ] 
    } 
}, 
"lines": [ ... ] 
} 
Verwandte Themen