eclipse-emfcloud / emfcloud-modelserver Goto Github PK
View Code? Open in Web Editor NEWModelserver component
License: Other
Modelserver component
License: Other
I think we should add the possibility to request and subscribe to changes of "submodels", ie elements and their contained elements. For listening to changes of submodels, we may want to take a look at util code of EMF ECP, I believe there are ready-to-use classes/adapters that make it easy to listen to changes in submodels efficiently.
The DefaultServerController should send a success JsonResponse if workspace initialization is completed.
Returning no response at all will cause the following error:
ERROR Request configure failed with error: invalid json response body at http://localhost:8081/api/v1/server/configure reason: Unexpected end of JSON input FetchError: invalid json response body at http://localhost:8081/api/v1/server/configure reason: Unexpected end of JSON input
When loading a resource, the method org.eclipse.emfcloud.modelserver.emf.common.ModelResourceManager.adaptModelUri(String) gets called for fixing the URI.
As a result, the URI is normalized, replacing (for example) file:///d:/myModel.coffee
with file:/d:/myModel.coffee
.
On the other hand, when creating a command, the owner's ModelServerReferenceDescription (when using uri.toString() without the skipEncoding attribute) may look like file:///d%3A/myModel.cofee#...
which, after json decoding and EMF resolution, gives a model element from resource with URI file:///d%3A/myModel.cofee
.
The direct consequence is that the new resource is loaded and edited (in the same resource set) while the previously loaded resource is not edited. When loading element back, I hence get the original element from the non-edited resource.
Note that there may also be OS-specific factors here...
I've identified 3 ways of fixing it :
org.emfjson.jackson.module.EMFModule.setupDefaultMapper(JsonFactory)
(directly or indirectly), which use a new EMFModule. (note by the way that we do not always use the ObjectMapper bound by ModelServerModule in controllers implementations, and this looks intended...)For now, I've successfully used the 1st fix as a workaround to edit my models.
During re-initialization of the model repository, we need to notify subscribers that the existing resources were deleted. So, for each resource in the resource set, if it was loaded, send a delete notification (resources that weren't loaded by the client didn't exist anyways as far as the client is concerned).
ExampleModelServerSubscriptionClient
and document properly, such that this client can be used as a kind of beginner's tutorialWe need to improve our Logging configuration at some point. Currently, the Logger just forwards to System.Out
. Ideally, errors should be printed to System.error
so I can react in the Theia Backend by listening to the error stream. However, for now, we bypassed this problem by setting the log level to error via CLI argument.
Originally we started with the DefaultModelRepository
to manage a repository of all models and provide CRUD API. However, with the customization of resource sets and editing domains, we introduced the ModelResourceManager
. Over time the API of those two classes have very much aligned. I therefore open the discussion whether we still need both classes. I suggest to either merge the two or find a more meaningful distinction between them.
Each session needs its own ResourceSet/EditingContext in order to properly support commands.
However, we first need to define whether we make it a rule that one modelserver only serves one user (always and forever ;)) and specify the use cases that we'd like to cover. If our usecases don't require a session, we can close this issue without an implementation, but I think it is worth discussing and defining it in the course of this issue, which is why we set it to high priority.
Adding a pattern validation causes the following exception when running the "validation" endpoint:
java.lang.IllegalArgumentException: No serializer found for class org.eclipse.emf.ecore.xml.type.util.XMLTypeUtil$PatternMatcherImpl and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.Collections$UnmodifiableRandomAccessList[0]->java.util.Collections$UnmodifiableRandomAccessList[0]->org.eclipse.emf.common.util.BasicEList$UnmodifiableEList[2]->org.eclipse.emf.ecore.xml.type.util.XMLTypeUtil$PatternMatcherImpl[0])
at com.fasterxml.jackson.databind.ObjectMapper.valueToTree(ObjectMapper.java:2978)
at org.eclipse.emfcloud.modelserver.emf.common.DefaultModelValidator.validate(DefaultModelValidator.java:63)
at org.eclipse.emfcloud.modelserver.emf.common.DefaultModelController.validate(DefaultModelController.java:213)
at org.eclipse.emfcloud.modelserver.emf.common.ModelServerRoutingV1.lambda$23(ModelServerRoutingV1.java:138)
at java.base/java.util.Optional.ifPresentOrElse(Optional.java:201)
at org.eclipse.emfcloud.modelserver.emf.common.ModelServerRoutingV1.validateModel(ModelServerRoutingV1.java:137)
at io.javalin.core.security.SecurityUtil.noopAccessManager(SecurityUtil.kt:23)
at io.javalin.http.JavalinServlet$addHandler$protectedHandler$1.handle(JavalinServlet.kt:121)
at io.javalin.http.JavalinServlet$service$2$1.invoke(JavalinServlet.kt:45)
at io.javalin.http.JavalinServlet$service$2$1.invoke(JavalinServlet.kt:24)
at io.javalin.http.JavalinServlet$service$1.invoke(JavalinServlet.kt:129)
at io.javalin.http.JavalinServlet$service$2.invoke(JavalinServlet.kt:40)
at io.javalin.http.JavalinServlet.service(JavalinServlet.kt:81)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.javalin.websocket.JavalinWsServlet.service(JavalinWsServlet.kt:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:791)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:550)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
at io.javalin.core.JavalinServer$start$wsAndHttpHandler$1.doHandle(JavalinServer.kt:49)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1350)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.StatisticsHandler.handle(StatisticsHandler.java:179)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.Server.handle(Server.java:516)
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:388)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:633)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:380)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:135)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:773)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:905)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.eclipse.emf.ecore.xml.type.util.XMLTypeUtil$PatternMatcherImpl and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.Collections$UnmodifiableRandomAccessList[0]->java.util.Collections$UnmodifiableRandomAccessList[0]->org.eclipse.emf.common.util.BasicEList$UnmodifiableEList[2]->org.eclipse.emf.ecore.xml.type.util.XMLTypeUtil$PatternMatcherImpl[0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:404)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serializeContents(ObjectArraySerializer.java:252)
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:213)
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:22)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2804)
at com.fasterxml.jackson.databind.util.TokenBuffer.writeObject(TokenBuffer.java:936)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1769)
at org.eclipse.emfcloud.modelserver.emf.common.ValidationMapperModule$BasicDiagnosticSerializer.serialize(ValidationMapperModule.java:78)
at org.eclipse.emfcloud.modelserver.emf.common.ValidationMapperModule$BasicDiagnosticSerializer.serialize(ValidationMapperModule.java:1)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2804)
at com.fasterxml.jackson.databind.util.TokenBuffer.writeObject(TokenBuffer.java:936)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1769)
at org.eclipse.emfcloud.modelserver.emf.common.ValidationMapperModule$BasicDiagnosticSerializer.serialize(ValidationMapperModule.java:79)
at org.eclipse.emfcloud.modelserver.emf.common.ValidationMapperModule$BasicDiagnosticSerializer.serialize(ValidationMapperModule.java:1)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2804)
at com.fasterxml.jackson.databind.util.TokenBuffer.writeObject(TokenBuffer.java:936)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1769)
at org.eclipse.emfcloud.modelserver.emf.common.ValidationMapperModule$BasicDiagnosticSerializer.serialize(ValidationMapperModule.java:79)
at org.eclipse.emfcloud.modelserver.emf.common.ValidationMapperModule$BasicDiagnosticSerializer.serialize(ValidationMapperModule.java:1)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2804)
at com.fasterxml.jackson.databind.ObjectMapper.valueToTree(ObjectMapper.java:2973)
... 44 more
The following changes were done to the Coffee model:
<eClassifiers xsi:type="ecore:EClass" name="Machine" eSuperTypes="#//Component">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="#//String3Chars"/>
<eClassifiers xsi:type="ecore:EDataType" name="String3Chars" instanceClassName="java.lang.String">
<eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
<details key="maxLength" value="3"/>
<details key="pattern" value="[A-Z0-9_]+"/>
</eAnnotations>
</eClassifiers>
And the following model resource was created:
{
"eClass" : "http://www.eclipsesource.com/modelserver/example/coffeemodel#//Machine",
"name" : "hello"
}
Without the pattern validation, the "validation" endpoint successfully completed, and reported that the name "hello" was too long. However, with the pattern validation, the above exception was raised.
Maybe the type should be called CommandType
, the property should be called kind
or we call the type CommandTypeKind
(the "Kind" suffix is a common pattern in some modeling circles).
We can request a typeschema via a request to this url: api/v1/typeschema?modeluri=...
But the returned schema, only returns information about the direct class, but not information of the super class.
We have a test model where we have a common ecore model with interfaces, and we have 2 derived ecore models. The specific field attributes or relations defined in the derived model are returned, but the attibutes and relations in the common model are not returned even no references.
Due to that the returned typeschema is incomplete.
Either it should return a reference to these schemas or it should include it.
com.eclipsesource.workflow.glsp.server 0.0.1-SNAPSHOT FAILURE
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project com.eclipsesource.workflow.glsp.server: Compilation failure: Compilation failure:
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/model/WorkflowModelServerAccess.java:[34,35] package org.eclipse.emf.edit.domain does not exist
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/model/WorkflowModelServerAccess.java:[35,35] package org.eclipse.emf.edit.domain does not exist
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/model/WorkflowModelServerAccess.java:[66,17] cannot find symbol
[ERROR] symbol: class EditingDomain
[ERROR] location: class com.eclipsesource.workflow.glsp.server.model.WorkflowModelServerAccess
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/model/WorkflowModelServerAccess.java:[195,16] cannot find symbol
[ERROR] symbol: class EditingDomain
[ERROR] location: class com.eclipsesource.workflow.glsp.server.model.WorkflowModelServerAccess
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/handler/operation/AbstractCreateNodeHandler.java:[19,36] package org.eclipse.emf.edit.command does not exist
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/handler/operation/AbstractCreateEdgeHandler.java:[17,36] package org.eclipse.emf.edit.command does not exist
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/handler/operation/ApplyLabelEditOperationHandler.java:[17,36] package org.eclipse.emf.edit.command does not exist
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/model/WorkflowModelServerSubscriptionListener.java:[25,35] package org.eclipse.emf.edit.domain does not exist
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/model/WorkflowModelServerSubscriptionListener.java:[116,48] cannot find symbol
[ERROR] symbol: class EditingDomain
[ERROR] location: class com.eclipsesource.workflow.glsp.server.model.WorkflowModelServerSubscriptionListener
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/WorkflowGLSPModule.java:[14,37] package org.eclipse.emf.edit.provider does not exist
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/model/WorkflowModelServerAccess.java:[75,42] cannot find symbol
[ERROR] symbol: class AdapterFactoryEditingDomain
[ERROR] location: class com.eclipsesource.workflow.glsp.server.model.WorkflowModelServerAccess
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/handler/operation/AbstractCreateNodeHandler.java:[51,38] cannot find symbol
[ERROR] symbol: variable AddCommand
[ERROR] location: class com.eclipsesource.workflow.glsp.server.handler.operation.AbstractCreateNodeHandler
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/handler/operation/AbstractCreateEdgeHandler.java:[50,38] cannot find symbol
[ERROR] symbol: variable AddCommand
[ERROR] location: class com.eclipsesource.workflow.glsp.server.handler.operation.AbstractCreateEdgeHandler
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/handler/operation/ApplyLabelEditOperationHandler.java:[45,38] cannot find symbol
[ERROR] symbol: variable SetCommand
[ERROR] location: class com.eclipsesource.workflow.glsp.server.handler.operation.ApplyLabelEditOperationHandler
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/model/WorkflowModelServerSubscriptionListener.java:[65,25] cannot find symbol
[ERROR] symbol: class EditingDomain
[ERROR] location: class com.eclipsesource.workflow.glsp.server.model.WorkflowModelServerSubscriptionListener
[ERROR] /Users/Experiment/Desktop/TestCoffee/coffee-editor/backend/plugins/com.eclipsesource.workflow.glsp.server/src/main/java/com/eclipsesource/workflow/glsp/server/WorkflowGLSPModule.java:[125,59] cannot find symbol
[ERROR] symbol: class ComposedAdapterFactory
[ERROR] location: class com.eclipsesource.workflow.glsp.server.WorkflowGLSPModule
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
POST request triggers "Create new model" and should return 409 "Conflict" if tried again after model has been created successfully.
Currently the formatting preference is Eclipse specific and cannot be reused in another IDE.
We should provide the formatting rules in an IDE-independent way. (e.g. exporting them as XML)
In addition, checkstyle should validate against this rules and trigger warnings.
This is a follow-up issue from #63 where it was reported that in newer Javalin versions mockito sometimes fails when mocking Javalin classes. There are several open issues related to this:
As soon as the issues are resolved we can upgrade.
Since updating to the latest version of Kotlin in #56 the JUnit tests seem to fail sometimes with the following error:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
String cannot be returned by pathParam()
pathParam() should return Validator
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
at org.eclipse.emfcloud.modelserver.emf.common.SessionControllerTest.initializeWsMessageContext(SessionControllerTest.java:190)
at org.eclipse.emfcloud.modelserver.emf.common.SessionControllerTest.testSubscribeAndSendKeepAlive(SessionControllerTest.java:159)
After investigating that for a bit, it seems that there was a change that marked the method pathParam
with @JvmSynthetic
to might have fixed that but did not in our case: javalin/javalin@be8910b.
There are already some open issues related to this:
The problem should be investigated and fixed, either by re-writing the mocking code, downgrading to a Javalin version that works (previously we used 3.1.0) of finding another way to get the test cases to run properly.
Currently our incremental update consists of a serialized (JSON, XMI) version of the executed command on the command stack. Interpreting these commands may result in problems for generic views.
Therefore I would like to open the discussion on whether it might be more useful to simply send a list of changed model element URIs as update. Clients could then decide to generically re-query those model elements and update their representation.
To not lose any functionality, I think we can keep the subscription to the commands but maybe rename it to a subscription to the command stack instead of the models.
Currently the model server creates the editing domain, the resource set and loads the model all by itself. However, there might be cases where additional resources should be loaded in the corresponding resource set/editing domain. We therefore should provide an Interface and default implementation for the model loading that is bound in the model server module so that it can be customized. By default each resource should be loaded in a separate editing domain, see implementation provided in issue #50.
The Model Server API does not offer the capability to simply stop editing a resource without saving.
If we plug an editor to it, when we close the editor, the resource is still opened and dirty by the model server. Hence, when the user reopens it, expecting the original resource, he gets the dirty unsaved resource instead.
For such purpose, a close
resource method would be very handy, which would reset the command stack in DefaultModelRepository
(which keeps all models loaded), or even close the resource and resource set in a lazier implementation.
For the DefaultModelRepository
implementation, where all models are loaded, a workaround would would be to undo all modifications. But it would be better to have another atomic dedicated method working with other implementations.
The ModelRepository
/ ModelResourceManager
interfaces have the removeResource
/ removeModel
method, but this one is a bit too final for this purpose and deletes the model file.
Please let me know if there already is a dedicated method I've missed...
Due to consistent failure of the m2 build with the macOS 10.15 environment, we will disable it temporarily and fix it with #107 .
I just noticed that the model server does not expose a method to get the eContainer
of a loaded EObject.
This is quite necessary, because metamodels rarely specialize the eContainer
relationship. So when we get a model element with the model server API, we loose the ability to get the eContainer
like with native EMF.
Obviously, loading the whole model to find the container is not an option. For such a special relationship, a new GET method semms quite a reasonable solution.
PS : please tag as [enhancement]
In case of editing the name of an element (which also changes its SemanticUriFragment
) via a SetCommand
, the broadcasted incrementalUpdate (command) does not contain the correct element values in all cases.
Example:
EClass
with name "BrewingUnit"
-> set name "BrewingUnitNew"
-> SemanticUriFragment changes from "//BrewingUnit"
to "//BrewingUnitNew"
If the command is encoded after executing the SetCommand
, the broadcasted incrementalUpdate contains the updated element "//BrewingUnitNew"
as owner and therefore the listeners have troubles consuming that update correctly.
As we already pre-encode commands in the case of Undo/Redo (to ensure proper command values for broadcasting to all listeners) we should stick to this behaviour also for executing other commands.
As reported on Spectrum, the model server does not provide any way to add custom codecs or replace existing ones. The main reason for this is that we have a single Codecs
class that has the two by-default supported formats (XMI, JSON) hard-coded.
The goal of this task it to improve on that situation by allowing the user to register/bind new codecs or replace existing ones.
As a suggestion: Make the codecs configurable with DI:
ModelServerModule
. For this the interface could be enhanced with the extension/format the codec handles and a priority if necessary. It should be easily possible to register multiple codecs. The DefaultModelServerModule
should at least bind the two default codecs.Codecs
class offers now. The manager is then injected where necessary but might also be overwritten/rebound in a custom module.@tortmayr reused the codeformatting/checkstyle settings of this repo for GLSP and made some minor improvements. We should probably apply these changes here as well once the transition to the eclipse infrastructure is completed.
Currently the model server launcher provides some methods to add customizations, e.g., addEPackageConfigurations
. However, in other cases no such method exists, e.g., when trying to add additional routing, see [1] and [2]. I believe the API could be improved in this regard to allow easier integration of additional modules (generics in the return type of getModules
make it unnecessarily difficult) and to already provide hooks for classes which may be implemented more than once, i.e., that have a collection binding.
I believe we could discuss whether that improved customizations should be part of the ModelServerModule
itself or the ModelServerLauncher
.
[1] https://spectrum.chat/emfcloud/modelserver/model-server-api-to-return-models-of-a-specific-type~b4a27e5d-48e6-41fe-8177-f66056f8c77f
[2] 954ffed
Directly after launching the coffee editor, the following editor is reported on the console.
root INFO Theia app listening on http://localhost:3000.
root ERROR ModelServerBackendContribution: WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$2 (file:/home/lucas/Git/coffee-editor/web/coffee-server/build/workflow-modelserver-example-1.2.0-SNAPSHOT-glsp.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
During server configuration is running, resources inside the given workspaceRoot are loaded. If an incoming request fetches a model, this might lead to an error, as the initializtion might not be completed yet.
Therefore incoming requests should be processed as soon as the server configuration for initializing the model server is complete.
Since #73 the PUT request server/configure
does not deliver the expected JsonResponse (success
or error
) anymore.
Clients expect a boolean response though. Here is an example of the typescript client reacting to the missing response:
ERROR Request configure failed with error:
invalid json response body at http://localhost:8081/api/v1/server/configure
reason: Unexpected end of JSON input
edit
endpointCommandStack
that save was doneBi directional references are a bit specific, as they require creating multiple related elements. Atomically, we need to:
The problem is that until A and B are actually created on the Model Server side, it is not possible to properly define the Set command.
By default, the TypedSubscriptionListener<T>
overrides most interface methods with an empty body.
Especially in the case of onFailure
and onError
this should be improved to log the failure reason and its stack trace in any case.
At the moment the list of supported commands is fixed in the Command.ecore
metamodel. If a client sends a command matching one of the classes, it will be decoded into an EMF command, executed on the command stack and finally sent as Json or XMI to the clients as incremental update.
For some languages, however, it might be useful to integrate their own commands. At the moment this is only possible by extending the metamodel and providing a custom CommandCodec that translates the CCommand to an EMF command. The goal of this task is therefore to provide a generic "custom command" in our Command.ecore
that holds a map of key-value pairs that can be interpreted by the specific languages. Additionally, a use case for such a command should be added to our example.
Requesting all available models from the model server via "GetAll" (http://localhost:8081/api/v1/models) fails with an internal server error:
WARN io.javalin.Javalin - Uncaught exception
org.eclipse.emf.common.util.BasicEList$BasicIndexOutOfBoundsException: index=0, size=0 ...
The Github action build-m2 was temporarily disabled for MacOS 10.15. (macos-latest
) with #106 due to issues since roughly mid April.
The newer version MacOS 11.0 is not available publicly yet (see https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources).
Please re-check once the newest version is publicly available if the build-m2 issues could are resolved.
There is currently a PR ongoing to extract the coffee model definition and integrate it directly into the coffee-editor (see https://github.com/eclipse-emfcloud/coffee-editor/pull/334/files).
Therefore I think it would make sense to drop the org.eclipse.emfcloud.modelserver.coffee.model
package and consume it from the coffee editor if we want to keep the coffee examples.
The default implementation of the ModelResourceManager loads all available models on startup (DefaultModelResourceManager.initialize() => DefaultModelResourceManager.loadSourceResources(String))
This may become an issue for larger repositories, as loading everything may not scale (Both in terms of CPU time and Memory usage).
Moreover, the current implementation of DefaultModelRepository.getAllModels() only returns loaded models (So it would no longer work if we introduced lazy loading). I think this method (in its current form) is not really relevant anyway, as retrieving all model instances wouldn't scale either. It would make more sense to return an index of models (URIs only), without actually loading them, and regardless of whether these models are already load or not.
This may be (vaguely) related to Issue #86 (for the relationship between ModelRepository and ModelManager)
So I suggest the following changes:
Export missing *.util
packages (e.g. org.eclipse.emfcloud.modelserver.edit.util
) to be able to access their methods.
I wonder if the namespace URI for commands should be updated to something else.
When trying to save an unknown resource, the model server responds with success:
{ "type": "success", "data": "Model 'file:/...' successfully saved" }
This is not correct, it should return an error, just like for example the DELETE
endpoint.
{ "type": "error", "data": "Model 'file:/...' not found, cannot be deleted!" }
When executing on windows, unit tests in org.eclipse.emfcloud.modelserver.emf.tests fail. (on master branch, commit 4d383b9 )
Some are due to #63 , but there are other causes, most probably specific to the windows OS.
The following tests fail due to a difference in whitespaces characters (mainly "\n" vs "\r\n" line breaks) :
Some other tests fail with "java.lang.IllegalArgumentException: resolve against non-hierarchical or relative base". This is the case of :
Finally, these tests fail (directly or indirectly) due to differences in built URIs (difference of separator) :
To improve the undo/redo support each resource identified by the model URI should be loaded in a separate editing domain and a separate resource set. All edit operations are handled by the editing domain associated with the respective resource.
This behavior opens up the possibility to have two editing domains/resource sets loading the same model (either directly or through cross references). Therefore, after performing a save operation a notification should be sent out to all listeners of that file that the underlying content has changed.
Using an absolute full path like file:///home/destination/file.coffee
leads to the following error:
9765 [qtp1598898814-26] DEBUG DefaultModelResourceManager - Could not load resource with URI: file:///home/nina/Clients/OpenSource/emfcloud/emfcloud-modelserver/examples/org.eclipse.emfcloud.modelserver.example/.temp/workspace/SuperBrewer3000.coffee
[qtp1598898814-26] WARN io.javalin.Javalin - Uncaught exception
java.lang.NullPointerException
at org.eclipse.emfcloud.modelserver.emf.common.DefaultModelResourceManager.removeResource(DefaultModelResourceManager.java:194)
at org.eclipse.emfcloud.modelserver.emf.common.DefaultModelResourceManager.removeResourceSafe(DefaultModelResourceManager.java:186)
at org.eclipse.emfcloud.modelserver.emf.common.DefaultModelResourceManager.loadResource(DefaultModelResourceManager.java:178)
at org.eclipse.emfcloud.modelserver.emf.common.DefaultModelResourceManager.loadResource(DefaultModelResourceManager.java:165)
at org.eclipse.emfcloud.modelserver.emf.common.ModelRepository.getModel(ModelRepository.java:59)
at org.eclipse.emfcloud.modelserver.emf.common.ModelController.getOne(ModelController.java:106)
...
See attached file.
super_constraints.txt
Currently many helper methods are private, their visibility should be changed to improve customization of the ModelServerClient
.
The example project is only used in test cases and the example and should be removed from the overall repository in the long term. If the project is removed at least the following changes need to be made:
Currently, there are two places where we log errors directly to the console even though the test does not fail:
cf. also #6 about general logging configuration.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.