Skip to content

Commit

Permalink
#315 Refactor base protocol (#132)
Browse files Browse the repository at this point in the history
Refactor the base communication protocol to support initializing and disposing a client session for a given language. The method parameters are encapsulated in dedicated parameter objects to provide a stable API. Refactor the existing `initializeServer` method to return an `InitializeResult` instead of a boolean and use a generic args map for custom arguments instead of a dedicated object. The `InitializeResult` also provides the information about which actionKinds are handled by the server. In addition, the protocol version that is implemented by the client is now passed as part of the `InitializeParameters`

Using the new initialize result  the server action handlers can be configured BEFORE the first action is dispatched in a diagram container, which means its no longer necessary to register certain early actions directly in the diagram server.

Refactor the standalone example to properly implement the new protocol.

Also:
- Remove no longer needs protocol actions for initializing/disposing a client session.
- Update webpack config of standalone example to properly support typescript source maps.


Part of eclipse-glsp/glsp/issues/315
  • Loading branch information
tortmayr authored Aug 16, 2021
1 parent 884f860 commit 45db2ab
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 158 deletions.
6 changes: 3 additions & 3 deletions examples/workflow-glsp/src/di.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2019 EclipseSource and others.
* Copyright (c) 2019-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -56,6 +56,7 @@ import {
openModule,
overrideViewerOptions,
paletteModule,
RectangularNodeView,
RevealNamedElementActionProvider,
RoundedCornerNodeView,
routingModule,
Expand All @@ -68,8 +69,7 @@ import {
toolsModule,
TYPES,
validationModule,
zorderModule,
RectangularNodeView
zorderModule
} from '@eclipse-glsp/client';
import { Container, ContainerModule } from 'inversify';

Expand Down
4 changes: 3 additions & 1 deletion examples/workflow-standalone/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,7 @@
"lint": "eslint -c ./.eslintrc.js --ext .ts,.tsx ./src",
"build": "tsc && webpack",
"watch": "tsc -w -p ./tsconfig.json"
}
},
"types": "lib",
"main": "lib"
}
3 changes: 2 additions & 1 deletion examples/workflow-standalone/src/di.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import { ConsoleLogger, LogLevel, TYPES } from 'sprotty';

export default function createContainer(): Container {
const container = createWorkflowDiagramContainer('sprotty');
container.bind(TYPES.ModelSource).to(GLSPDiagramServer).inSingletonScope();
container.bind(GLSPDiagramServer).toSelf().inSingletonScope();
container.bind(TYPES.ModelSource).toService(GLSPDiagramServer);
container.rebind(TYPES.ILogger).to(ConsoleLogger).inSingletonScope();
container.rebind(TYPES.LogLevel).toConstantValue(LogLevel.warn);
return container;
Expand Down
39 changes: 23 additions & 16 deletions examples/workflow-standalone/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,52 @@
import 'reflect-metadata';

import {
configureServerActions,
EnableToolPaletteAction,
GLSPDiagramServer,
InitializeClientSessionAction,
RequestTypeHintsAction
} from '@eclipse-glsp/client';
import { ApplicationIdProvider, BaseJsonrpcGLSPClient, JsonrpcGLSPClient } from '@eclipse-glsp/protocol';
import { ApplicationIdProvider, BaseJsonrpcGLSPClient, GLSPClient, JsonrpcGLSPClient } from '@eclipse-glsp/protocol';
import { join, resolve } from 'path';
import { IActionDispatcher, RequestModelAction, TYPES } from 'sprotty';

import createContainer from './di.config';

const port = 8081;
const id = 'workflow';
const diagramType = 'workflow-diagram';
const websocket = new WebSocket(`ws://localhost:${port}/${id}`);
const container = createContainer();

const loc = window.location.pathname;
const currentDir = loc.substring(0, loc.lastIndexOf('/'));
const examplePath = resolve(join(currentDir, '..', 'app', 'example1.wf'));
const clientId = ApplicationIdProvider.get() + '_' + examplePath;

const container = createContainer();
const diagramServer = container.get<GLSPDiagramServer>(TYPES.ModelSource);
diagramServer.clientId = ApplicationIdProvider.get() + '_' + examplePath;

const actionDispatcher = container.get<IActionDispatcher>(TYPES.IActionDispatcher);
diagramServer.clientId = clientId;

websocket.onopen = () => {
const connectionProvider = JsonrpcGLSPClient.createWebsocketConnectionProvider(websocket);
const glspClient = new BaseJsonrpcGLSPClient({ id, connectionProvider });
diagramServer.connect(glspClient).then(client => {
client.initializeServer({ applicationId: ApplicationIdProvider.get() });
actionDispatcher.dispatch(new InitializeClientSessionAction(diagramServer.clientId));
actionDispatcher.dispatch(new RequestModelAction({
sourceUri: `file://${examplePath}`,
diagramType: 'workflow-diagram'
}));
actionDispatcher.dispatch(new RequestTypeHintsAction('workflow-diagram'));
actionDispatcher.dispatch(new EnableToolPaletteAction());
});
initialize(glspClient);
};

async function initialize(client: GLSPClient): Promise<void> {
await diagramServer.connect(client);
const result = await client.initializeServer({ applicationId: ApplicationIdProvider.get(), protocolVersion: GLSPClient.protocolVersion });
await configureServerActions(result, diagramType, container);

const actionDispatcher = container.get<IActionDispatcher>(TYPES.IActionDispatcher);

await client.initializeClientSession({ clientSessionId: diagramServer.clientId, diagramType });
actionDispatcher.dispatch(new RequestModelAction({
sourceUri: `file://${examplePath}`,
diagramType
}));
actionDispatcher.dispatch(new RequestTypeHintsAction(diagramType));
actionDispatcher.dispatch(new EnableToolPaletteAction());
}

websocket.onerror = ev => alert('Connection to server errored. Please make sure that the server is running');

19 changes: 9 additions & 10 deletions examples/workflow-standalone/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2017 TypeFox & others
* Copyright (c) 2017-2021 TypeFox & others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -34,27 +34,26 @@ module.exports = {
path: appRoot
},
mode: 'development',
devtool: 'source-map',
devtool: 'eval-source-map',
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: ['.webpack.js', '.web.js', '.ts', '.tsx', '.js']
},
module: {
rules: [
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
{
test: /\.tsx?$/,
use: [{
loader: 'ts-loader',
options: {
configFile: path.resolve(__dirname, 'examples.tsconfig.json')
}
}]
use: ['ts-loader']
},
{
test: /\.js$/,
use: ['source-map-loader'],
enforce: 'pre'
},
{
test: /\.css$/,
exclude: /\.useable\.css$/,
loader: 'style-loader!css-loader'
use: ['style-loader', 'css-loader']
}
]
},
Expand Down
82 changes: 0 additions & 82 deletions packages/client/src/base/actions/protocol-actions.ts

This file was deleted.

35 changes: 28 additions & 7 deletions packages/client/src/base/di.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2019 EclipseSource and others.
* Copyright (c) 2019-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -15,13 +15,20 @@
********************************************************************************/
import '../../css/glsp-sprotty.css';

import { ContainerModule } from 'inversify';
import { configureActionHandler, configureCommand, SetModelCommand, TYPES } from 'sprotty';
import { InitializeResult } from '@eclipse-glsp/protocol';
import { Container, ContainerModule } from 'inversify';
import {
ActionHandlerRegistry,
configureActionHandler,
configureCommand,
ModelSource,
SetModelCommand,
TYPES
} from 'sprotty';

import { GLSPActionDispatcher } from './action-dispatcher';
import { SetEditModeAction } from './actions/edit-mode-action';
import { FocusStateChangedAction } from './actions/focus-change-action';
import { ConfigureServerHandlersAction, ConfigureServerHandlersActionHandler } from './actions/protocol-actions';
import { GLSPCommandStack } from './command-stack';
import { EditorContextService } from './editor-context';
import { FocusTracker } from './focus-tracker';
Expand Down Expand Up @@ -53,9 +60,6 @@ const defaultGLSPModule = new ContainerModule((bind, _unbind, isBound, rebind) =
configureCommand(context, FeedbackAwareUpdateModelCommand);
configureActionHandler(context, SetModelCommand.KIND, SetModelActionHandler);

// Dynamically register all server-side action/operation handlers
configureActionHandler(context, ConfigureServerHandlersAction.KIND, ConfigureServerHandlersActionHandler);

bind(TYPES.MouseListener).to(SelectionClearingMouseListener);

rebind(TYPES.ICommandStack).to(GLSPCommandStack);
Expand All @@ -73,3 +77,20 @@ const defaultGLSPModule = new ContainerModule((bind, _unbind, isBound, rebind) =
});

export default defaultGLSPModule;

/**
* Utility function to configure the {@link ModelSource}, i.e. the `DiagramServer`, as action handler for all server actions for the given diagramType.
* @param result A promise that resolves after all server actions have been registered.
* @param diagramType The diagram type.
* @param container The di container.
*/
export async function configureServerActions(result: InitializeResult, diagramType: string, container: Container): Promise<void> {
const modelSource = container.get<ModelSource>(TYPES.ModelSource);
const actionHandlerRegistry = container.get<ActionHandlerRegistry>(ActionHandlerRegistry);
const serverActions = result.serverActions[diagramType];
if (serverActions.length === 0) {
throw new Error(`No server-handled actions could be derived from the initialize result for diagramType: ${diagramType}!`);
}
serverActions.forEach(actionKind => actionHandlerRegistry.register(actionKind, modelSource));
}

2 changes: 1 addition & 1 deletion packages/client/src/features/tool-palette/di.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { configureActionHandler, EnableDefaultToolsAction, TYPES } from 'sprotty

import { EnableToolPaletteAction, ToolPalette } from './tool-palette';

const toolPaletteModule = new ContainerModule((bind, _unbind, isBound) => {
const toolPaletteModule = new ContainerModule((bind, _unbind, isBound, rebind) => {
bind(ToolPalette).toSelf().inSingletonScope();
bind(TYPES.IUIExtension).toService(ToolPalette);
configureActionHandler({ bind, isBound }, EnableToolPaletteAction.KIND, ToolPalette);
Expand Down
10 changes: 5 additions & 5 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2019 EclipseSource and others.
* Copyright (c) 2019-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -39,12 +39,12 @@ export * from './base/actions/context-actions';
export * from './base/actions/edit-mode-action';
export * from './base/actions/edit-validation-actions';
export * from './base/actions/focus-change-action';
export * from './base/actions/protocol-actions';
export * from './base/args';
export * from './base/auto-complete/auto-complete-actions';
export * from './base/auto-complete/auto-complete-widget';
export * from './base/auto-complete/validation-decorator';
export * from './base/command-stack';
export { configureServerActions } from './base/di.config';
export * from './base/drag-aware-mouse-listener';
export * from './base/editor-context';
export * from './base/focus-tracker';
Expand Down Expand Up @@ -95,21 +95,21 @@ export * from './features/tools/edge-edit-tool';
export * from './features/tools/node-creation-tool';
export * from './features/undo-redo/model';
export * from './features/validation/issue-marker';
export * from './features/validation/validate';
export * from './features/validation/marker-navigator';
export * from './features/validation/validate';
export * from './features/viewport/glsp-scroll-mouse-listener';
export * from './lib/model';
export * from './model-source/glsp-server-status';
export * from './model-source/glsp-diagram-server';
export * from './model-source/glsp-server-status';
export * from './utils/argument-utils';
export * from './utils/array-utils';
export * from './utils/marker';
export * from './utils/smodel-util';
export * from './utils/viewpoint-util';
export * from './views';

export {
validationModule, saveModule, paletteModule, toolFeedbackModule, defaultGLSPModule, modelHintsModule, glspCommandPaletteModule,
glspContextMenuModule, glspServerCopyPasteModule, copyPasteContextMenuModule, glspSelectModule, glspMouseToolModule, layoutCommandsModule, glspEditLabelModule,
glspHoverModule, toolsModule, navigationModule, markerNavigatorModule, glspDecorationModule, modelSourceWatcherModule, glspViewportModule
};

16 changes: 2 additions & 14 deletions packages/client/src/model-source/glsp-diagram-server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2019-2020 EclipseSource and others.
* Copyright (c) 2019-2021 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -27,11 +27,8 @@ import {
SwitchEditModeCommand
} from 'sprotty';

import { RequestContextActions } from '../base/actions/context-actions';
import { isSetEditModeAction, SetEditModeAction } from '../base/actions/edit-mode-action';
import { InitializeClientSessionAction } from '../base/actions/protocol-actions';
import { SourceUriAware } from '../base/source-uri-aware';
import { RequestTypeHintsAction } from '../features/hints/request-type-hints-action';
import { isServerMessageAction, ServerMessageAction } from './glsp-server-status';

const receivedFromServerProperty = '__receivedFromServer';
Expand Down Expand Up @@ -108,16 +105,7 @@ export function isReceivedFromServer(action: Action): boolean {
}

export function registerDefaultGLSPServerActions(registry: ActionHandlerRegistry, diagramServer: DiagramServer): void {
// Register the InitializeClientSessionAction as a server action. Then, the server will
// notify us about all actions it handles (Via ConfigureServerHandlersAction/Handler)
registry.register(InitializeClientSessionAction.KIND, diagramServer);

// Register some additional early actions, that will happen before the server can tell us
// which actions it handles
registry.register(RequestTypeHintsAction.KIND, diagramServer);
registry.register(RequestModelAction.KIND, diagramServer);
registry.register(RequestContextActions.KIND, diagramServer);

registry.register(ServerMessageAction.KIND, diagramServer);
registry.register(ServerStatusAction.KIND, diagramServer);

// Register an empty handler for SwitchEditMode, to avoid runtime exceptions.
Expand Down
Loading

0 comments on commit 45db2ab

Please sign in to comment.