-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
150: ModelServer API v2 #151
Conversation
- introduce V2 API interfaces (server and client) - Provide a V2 version of the JsonCodec - replace "eClass": with "$type": - replace "@id": with "$id": - Add support for Transactions, to replace or complement custom commands - Distinguish "modelserver.patch" for changes executed with the Json Patch format, from "modelserver.emfcommand" for changes executed with the CCommand format (Equivalent to V1) - In V2, resolve relative CCommand URIs against the workspace root URI (In V1, URIs were expected to be absolute). - Generate patch by comparing the previous model state and the new model state, after converting both to Json Contributed on behalf of STMicroelectronics. refs /issues/150 Co-authored-by: Christian W. Damus <[email protected]> Signed-off-by: Camille Letavernier <[email protected]>
Note: this is a draft PR. Some pieces are still missing (especially, we need to improve the support for Json Patch operations. Currently, only 'replace' is implemented). The ModelServer should still support the V1 endpoints, but using both V1 and V2 endpoints at the same time (for different clients) may cause unexpected issues (Especially regarding Command execution/notifications). |
The PR includes some library for manipulating Json Patch on the server. The library is The libraries are included in the |
- Add support for add and remove patch operations refs /issues/150 Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
Added implementation & (integration) tests for Add (Create) and Remove operations. Move and Test are still unsupported. |
refs /issues/150 Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
- Add an M2 Dependency to json-tools - Only repackage the libraries when doing a P2 build - Add json-patch bundles to the Model Server feature refs /issues/150 Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
- Update copyrights headers to match Checkstyle regex refs /issues/150 Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
0944710
to
d76147b
Compare
- Update copyrights headers to match Checkstyle regex - Fix additional warnings refs /issues/150 Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
- Fix additional warnings refs /issues/150 Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
- undo stack was not getting an undoable command when all edits in a transaction were JSON patches - add support for undo/redo (and execution results) of commands generated from JSON patches that do not have client commands - do not perform live validation of the model if there are no listeners interested in it Contributed on behalf of STMicroelectronics. Signed-off-by: Christian W. Damus <[email protected]>
- Support Adding elements that are already present in the model (= Reparent or Reference) - Support Adding attribute values (Primitives, Enums...) to a multi-valued EAttribute Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
execution - When modifying the model via the PATCH models endpoint, attach the Json Patch diff to the result Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
The new commit attaches the Json Patch node to the result, after executing a Command/Patch operation. The "data" field is modified to support both a message and a patch. V1 Result:
V2 Result:
(Note: the same thing needs to be done for 'undo' and 'redo' endpoints; but at the moment these endpoints are shared between V1 and V2, so they'll need to be split) |
Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
- ensure that v2 subscribers get JSON Patch delta notifications on undo/redo - unify v1 and v2 incremental change notification so that both v1 and v2 subscribers get deltas of their flavour from command or patch execute/undo/redo (in the case of JSON Patches v1 subscribers don't get a source command) - defer calculation of JSON Patch delta so that it won't be computed if it is not needed Contributed on behalf of STMicroelectronics. Signed-off-by: Christian W. Damus <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks great thank you.
I have mainly comments about creating follow up issues and some possible generic improvements.
...odelserver.client/src/org/eclipse/emfcloud/modelserver/client/AbstractModelServerClient.java
Show resolved
Hide resolved
...odelserver.client/src/org/eclipse/emfcloud/modelserver/client/AbstractModelServerClient.java
Show resolved
Hide resolved
...odelserver.client/src/org/eclipse/emfcloud/modelserver/client/AbstractModelServerClient.java
Show resolved
Hide resolved
...odelserver.client/src/org/eclipse/emfcloud/modelserver/client/AbstractModelServerClient.java
Outdated
Show resolved
Hide resolved
...odelserver.client/src/org/eclipse/emfcloud/modelserver/client/AbstractModelServerClient.java
Show resolved
Hide resolved
....emfcloud.modelserver.emf/src/org/eclipse/emfcloud/modelserver/emf/util/JsonPatchHelper.java
Show resolved
Hide resolved
....emfcloud.modelserver.emf/src/org/eclipse/emfcloud/modelserver/emf/util/JsonPatchHelper.java
Outdated
Show resolved
Hide resolved
....emfcloud.modelserver.emf/src/org/eclipse/emfcloud/modelserver/emf/util/JsonPatchHelper.java
Outdated
Show resolved
Hide resolved
pom.xml
Outdated
@@ -297,7 +298,7 @@ | |||
<groupId>org.eclipse.emfcloud.modelserver</groupId> | |||
<artifactId>org.eclipse.emfcloud.modelserver.parent</artifactId> | |||
<classifier>releng/org.eclipse.emfcloud.modelserver.releng.target/targetplatform</classifier> | |||
<version>${project.version}</version> | |||
<version>0.7.0-SNAPSHOT</version> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not use the project version anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the introduction of external libraries, which are not versioned as "0.7.0", the target platform couldn't resolve. The alternative would be to override the target platform definition for these bundles that use a different version, but I think having a single target platform is more consistent (rather than assuming we'll have a target platform version per bundle version).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this still the case with the move of libs to the lib folder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this isn't required anymore. Although I still think this is better this way :) If we have a single target platform module, there's really no reason to introduce a variable version to it (The problem with ${project.version}
is that it references the built project's version, and not the target platform version, so it only works if we assume that all modules use the same version).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just as a small sidetrack here: For us it is in general easier if we stick to the variable when we want to publish a release (candidate) as we can then use our scripts to adapt the versions without having to check manually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the target platform itself is not published, you can achieve the same result by using a fixed version (There's no need to ever change the target platform version; you can set it to 1.0.0
or 0.0.1
and forget about it).
Alternatively, you can use an explicit version Property (instead of the predefined ${project.version}
), to keep the Target Platform versioned. This way, the Target Platform can still inherit the version from the parent, but projects referencing the target platform may be versioned separately (while still using this shared target platform at a specific version).
The idea is really that the target platform should have its own version, rather than reuse the version from the project referencing it.
- include the patch in the undo/redo response - add test case - refactor patch helper as an injected dependency for testability (and consistency with everything else) Contributed on behalf of STMicroelectronics. Signed-off-by: Christian W. Damus <[email protected]>
#150: Delta patch notifications on undo/redo
We could use the maven support for target files, but we would need to get rid of the tpd files then ... . I think adding them to the lib folder is fine. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for this valuable contribution! I have some rather general remarks/questions on the PR, please see below.
-
Directory
libs
- Why is it necessary to store them in a separate directory? Could we include them in the existing
bundles/org.eclipse.emfcloud.modelserver.lib
? - If they should remain as separate projects, please update their project settings, project files and classpaths according to the README as they cause file changes on import.
- Why is it necessary to store them in a separate directory? Could we include them in the existing
-
General remarks/questions
- Please take a look at the new warnings in the workspace and remove them if possible
- For newly added files, the header should only contain
2022
and not a year range. Also, some of those newly added files have aEclipseSource
header and some aSTMicroelectronics
header. Should they be unified? - Why exactly do we need the
targetplatform-dev.target
? Would the additional dependencies hurt too much in the main targetplatform? However, it makes the development setup a little bit more complex imo, so if it needs to stay, we should at least mention that in the README. - Will this story include API documentation as well (@eneufeld/@sdirix)? In general, the current documentation should be improved anyhow. It would be great to offer API documentation for example via OpenAPI and V2 would be definitely a great starting point to do so.
I didn't realize we already had a lib bundle. The approach I took is probably closer to the typical Orbit approach (keeping the original names), but adding all libs to the same bundle would definitely work, too. And it would be more consistent with the current ModelServer approach.
Actually, these files are not "newly added", they're forked/duplicated from existing classes. So, I kept the original Copyright in these cases. I double-checked yesterday, and all copyrights should be consistent: new files have the ST-2022 Copyright; existing and forked files have the ES-xxxx-2022 Copyright.
This looks like a mistake. I played with target platforms a bit during development, but the current -dev platform is definitely not necessary. I'll remove it.
That definitely makes sense. However, I think it's still a bit early for that, as some APIs and use cases are not clearly defined yet (Especially URI handling, which Json Patches we support, how responses/notifications are sent, and how to handle multi-resources use cases). But we should probably start working on an initial version soon. |
- We no longer have modules with a different version; restore the ${project.version} property
Updates to the transaction protocol to align with the shape of JSON patch responses to edit/undo/redo requests: - update CCommand execution to respond to the client with a success message that embeds a JSON patch update message - fix the JSON Patch application to embed the JSON patch within the new message shape in the reply message Contributed on behalf of STMicroelectronics. Signed-off-by: Christian W. Damus <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, I suggest to remove the draft flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again Camille and Christian for the updates! 🎉
Looks good to me so far, however I still have a few minor comments:
Some of theEdit 2021-02-18: This was a problem on my side and I couldn't reproduce it anymore.org.eclipse.emfcloud.modelserver.emf.tests
are failing and they also produce one one warning in the workspace. The*.emf.tests
are not executed in the p2 build currently (please see Allow EMF Tests to run in p2 build #167) but in Eclipse and for the m2 build they should be fixed. Could you please have another look?- The README should be updated before we merge this independently form the API documentation. It would be fine by me to create a section with the updated V2 API and put the V1 in a collapsible section or sth like that.
Will this story include API documentation as well?
That definitely makes sense. However, I think it's still a bit early for that, as some APIs and use cases are not clearly defined yet (Especially URI handling, which Json Patches we support, how responses/notifications are sent, and how to handle multi-resources use cases). But we should probably start working on an initial version soon.
That sounds reasonable - could you please create an follow-up issue for the documentation story?
...d.modelserver.client/src/org/eclipse/emfcloud/modelserver/client/ModelServerClientApiV2.java
Show resolved
Hide resolved
.../src/main/java/org/eclipse/emfcloud/modelserver/example/client/ExampleModelServerClient.java
Outdated
Show resolved
Hide resolved
- The v2 Java client is not ready yet; keep using v1 for the java example - Update readme to include v2 EMF Commands and Json Patches examples - Fix deprecation warning in the tests - Use a property for java-json-tools dependency version in the pom Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
Conflicts: README.md bundles/org.eclipse.emfcloud.modelserver.client/src/org/eclipse/emfcloud/modelserver/client/ModelServerClient.java bundles/org.eclipse.emfcloud.modelserver.common/META-INF/MANIFEST.MF bundles/org.eclipse.emfcloud.modelserver.emf/src/org/eclipse/emfcloud/modelserver/emf/common/DefaultModelController.java bundles/org.eclipse.emfcloud.modelserver.emf/src/org/eclipse/emfcloud/modelserver/emf/common/ModelServerRoutingV1.java bundles/org.eclipse.emfcloud.modelserver.emf/src/org/eclipse/emfcloud/modelserver/emf/common/util/ContextRequest.java bundles/org.eclipse.emfcloud.modelserver.lib/META-INF/MANIFEST.MF bundles/org.eclipse.emfcloud.modelserver.lib/build.properties releng/org.eclipse.emfcloud.modelserver.releng.target/targetplatform.target tests/org.eclipse.emfcloud.modelserver.client.tests/build.properties tests/org.eclipse.emfcloud.modelserver.common.tests/build.properties tests/org.eclipse.emfcloud.modelserver.edit.tests/build.properties tests/org.eclipse.emfcloud.modelserver.emf.tests/build.properties tests/org.eclipse.emfcloud.modelserver.emf.tests/src/org/eclipse/emfcloud/modelserver/emf/common/DefaultModelControllerTest.java
- Use /{id} syntax instead of /:id for endpoint parameters, since we moved to Javalin 4 - Enable custom routing example on both v1 and v2 APIs Contributed on behalf of ST Microelectronics Signed-off-by: Camille Letavernier <[email protected]>
I've merged the Log4J changes from master into the branch to solve conflicts (That was a big batch of conflicts). I've also fixed the custom 'counter' endpoint example, which was only registered for the v2 API, and not for v1 anymore. Now, it's available on both versions. This adresses a bug reported on the client side (The custom example menus use v1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot Camille for the quick fixes and the rebasing!
Special thanks for the great README update! 🥇
To me it looks good and ready to merge. Still I will add @martin-fleck-at as a final reviewer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general the change looks good to me and from what I can see V1 still works as expected. So thank you very much for that great work which must not have been easy!
I tested it as far as I could with the v1 Theia client and the v1 Java client but I could not find any good way to test the v2 API. From the code point of view, it looks good but I do have a few comments and one question: How do we plan to proceed with V1? Some code suggests more a dual approach where both APIs can be used independent from each other but other classes mix their implementation together. I thought we could split the V1 vs V2 based on the server modules that are created, i.e., that there will be a V2 DefaultSessionController etc. which are bound in a V2 DefaultModelServerModule so that adopters can either choose that server module as their base or the V1 one. For instance, the current approach leads to the DefaultSessionController having a method called subscribeV2
and two maps that store the listeners based on the version. It just strikes me as a bit odd so I am curious, what was the reasoning behind this?
...cloud.modelserver.client/src/org/eclipse/emfcloud/modelserver/client/TransactionContext.java
Outdated
Show resolved
Hide resolved
throws JsonPatchTestException { | ||
boolean isValid = true; | ||
// TODO ... implement actual test | ||
// Should we throw an exception, or return an UnexecutableCommand? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just from my point of view, UnexecutableCommand feels like the way to go but I am not sure. Maybe we can create a task to reference and track this? I don't think we want test support anyway but who knows what will happen in the future ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Exception gives us more flexibility, to generate e.g. a more detailed client reply. "UnexecutableCommand" doesn't say anything about why it didn't work; an Exception can hold more valuable information (And we probably want to return a different result based on this exception: e.g. a specific error code/message, rather than "OK but nothing changed" or a generic "Can't execute. Try something else.")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that in general an exception may have more information but this exception really does not ;-) Also currently we do not even through an exception. @CamilleLetavernier Could you maybe add a task to track adding this feature? As otherwise this TODO just seems like we were too lazy to do it instead of consciously postponing the implementation.
...lserver.common/src/org/eclipse/emfcloud/modelserver/common/patch/JsonPatchTestException.java
Show resolved
Hide resolved
...se.emfcloud.modelserver.edit/src/org/eclipse/emfcloud/modelserver/edit/util/CommandUtil.java
Outdated
Show resolved
Hide resolved
...loud.modelserver.emf/src/org/eclipse/emfcloud/modelserver/emf/common/codecs/JsonCodecV2.java
Show resolved
Hide resolved
...ud.modelserver.emf/src/org/eclipse/emfcloud/modelserver/emf/common/ModelServerRoutingV2.java
Outdated
Show resolved
Hide resolved
...odelserver.emf/src/org/eclipse/emfcloud/modelserver/emf/common/DefaultSessionController.java
Show resolved
Hide resolved
- remove unused code in the CommandUtil - remove incomplete and unsupported client API for transactions - document internal transaction endpoint in the readme Contributed on behalf of STMicroelectronics. Signed-off-by: Christian W. Damus <[email protected]>
Thanks for your review, Martin! You raise several good questions.
In the short term, it is expected that applications will continue to use the v1 API if it works for them. Of course, early adopters of v2 can help to shake things out there, but for now it may still undergo some churn as use cases are fleshed out and gaps in the functionality filled. In the longer term, the intent is that the v1 API can be deprecated and eventually phased out. On the matter of how the API split is realized in the server, there is so much commonality in the shape and behaviour of these two API versions that it seemed most practical to share the bulk of the implementation and distinguish the divergent behaviour where necessary as in this case in the |
150: Trim client API and update readme
Commit 9751305 adds changes to address specific review comments:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CamilleLetavernier @cdamus I had a final look at the changes and with clarifications you both gave and the additional "removal" of the transactions from the API, I am more than happy with this change. Thank you very much for your great work!
In the short term, it is expected that applications will continue to use the v1 API if it works for them. Of course, early adopters of v2 can help to shake things out there, but for now it may still undergo some churn as use cases are fleshed out and gaps in the functionality filled. In the longer term, the intent is that the v1 API can be deprecated and eventually phased out.
[...]
Thank you very much for the detailed reasoning behind this. In that sense, V2 is more of an extension of V1 than an actual standalone version which is fine for me. We can definitely leave the separation of versions in modules for another day - if ever - since V1 still works and will be deprecated sometime in the (near) future anyway. It just caught me by surprise since in my mental model it was more of an either/or situation.
ed8c0ff
to
9751305
Compare
Introduce a new version for the ModelServer API (V2). This version removes some of the EMFisms from the API:
At the moment, supported types are "modelserver.emfcommand" (V1 CCommand) and "modelserver.jsonpatch" (V2 Json Patch).
Contributed on behalf of STMicroelectronics.