Skip to content

Commit

Permalink
Split backend service templates
Browse files Browse the repository at this point in the history
  • Loading branch information
mgerzabek committed Sep 27, 2023
1 parent f337f93 commit 3962e06
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ yo theia-extension --help
| `labelprovider` | Creates a simple extension which adds a custom label (with icon) for .my files | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/labelprovider/README.md) |
| `tree-editor` | Creates a tree editor extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/tree-editor/README.md) |
| `empty` | Creates a simple, minimal extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/empty/README.md) |
| `backend` | Creates a backend communication extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/backend/README.md) |
| `backend` | Creates a unidirectional backend communication extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/backend/README.md) |
| `backend-uni` | Creates a unidirectional backend communication extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/backend-uni/README.md) |
| `backend-bidi` | Creates a bidrectional backend communication extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/backend-bidi/README.md) |
| `diagram-editor` | Creates a diagram editor extension | [readme](https://github.com/eclipse-glsp/glsp-examples/blob/master/README.md) |


Expand Down
9 changes: 9 additions & 0 deletions templates/backend-bidi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Backend Communication Example

The example extension demonstrates how to communicate bidirectional with backend services.
It contains the `HelloBackendWithClientService`, that issues a greeting but the name parameter is not directly passed by the client. Instead, the backend services retrieves the name to say "Hello" to from the client again (`BackendClient`). This example shows how to implement call backs from the backend to the client.
Further, the example contributes one command to trigger the backend call.

## How to use the backend communication example

In the running application, trigger the command "Say hello on the backend with a callback to the client" via the command palette (F1 => "Say Hello"). A message will be printed out on the console from where you launched the application.
16 changes: 16 additions & 0 deletions templates/backend-bidi/backend-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ConnectionHandler, RpcConnectionHandler } from '@theia/core';
import { ContainerModule } from '@theia/core/shared/inversify';
import { BackendClient, HelloBackendWithClientService, HELLO_BACKEND_WITH_CLIENT_PATH } from '../common/protocol';
import { HelloBackendWithClientServiceImpl } from './hello-backend-with-client-service';

export default new ContainerModule(bind => {
bind(HelloBackendWithClientService).to(HelloBackendWithClientServiceImpl).inSingletonScope()
bind(ConnectionHandler).toDynamicValue(ctx =>
new RpcConnectionHandler<BackendClient>(HELLO_BACKEND_WITH_CLIENT_PATH, client => {
const server = ctx.container.get<HelloBackendWithClientServiceImpl>(HelloBackendWithClientService);
server.setClient(client);
client.onDidCloseConnection(() => server.dispose());
return server;
})
).inSingletonScope();
});
22 changes: 22 additions & 0 deletions templates/backend-bidi/contribution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Command, CommandContribution, CommandRegistry} from '@theia/core/lib/common';
import { inject, injectable } from '@theia/core/shared/inversify';
import { HelloBackendWithClientService } from '../common/protocol';

const SayHelloViaBackendCommandWithCallBack: Command = {
id: 'sayHelloOnBackendWithCallBack.command',
label: 'Say hello on the backend with a callback to the client',
};

@injectable()
export class <%= params.extensionPrefix %>CommandContribution implements CommandContribution {

constructor(
@inject(HelloBackendWithClientService) private readonly helloBackendWithClientService: HelloBackendWithClientService,
) { }

registerCommands(registry: CommandRegistry): void {
registry.registerCommand(SayHelloViaBackendCommandWithCallBack, {
execute: () => this.helloBackendWithClientService.greet().then(r => console.log(r))
});
}
}
22 changes: 22 additions & 0 deletions templates/backend-bidi/frontend-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CommandContribution} from '@theia/core';
import { WebSocketConnectionProvider } from '@theia/core/lib/browser';
import { ContainerModule, injectable } from '@theia/core/shared/inversify';
import { BackendClient, HelloBackendWithClientService, HELLO_BACKEND_WITH_CLIENT_PATH } from '../common/protocol';
import { <%= params.extensionPrefix %>CommandContribution} from './<%= params.extensionPath %>-contribution';

export default new ContainerModule(bind => {
bind(CommandContribution).to(<%= params.extensionPrefix %>CommandContribution).inSingletonScope();

bind(HelloBackendWithClientService).toDynamicValue(ctx => {
const connection = ctx.container.get(WebSocketConnectionProvider);
const backendClient: BackendClient = ctx.container.get(BackendClient);
return connection.createProxy<HelloBackendWithClientService>(HELLO_BACKEND_WITH_CLIENT_PATH, backendClient);
}).inSingletonScope();
});

@injectable()
class BackendClientImpl implements BackendClient {
getName(): Promise<string> {
return new Promise(resolve => resolve('Client'));
}
}
18 changes: 18 additions & 0 deletions templates/backend-bidi/hello-backend-with-client-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { injectable } from '@theia/core/shared/inversify';
import { BackendClient, HelloBackendWithClientService } from '../common/protocol';

@injectable()
export class HelloBackendWithClientServiceImpl implements HelloBackendWithClientService {
private client?: BackendClient;
greet(): Promise<string> {
return new Promise<string>((resolve, reject) =>
this.client ? this.client.getName().then(greet => resolve('Hello ' + greet))
: reject('No Client'));
}
dispose(): void {
// do nothing
}
setClient(client: BackendClient): void {
this.client = client;
}
}
12 changes: 12 additions & 0 deletions templates/backend-bidi/protocol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { RpcServer } from '@theia/core/lib/common/messaging';

export const HelloBackendWithClientService = Symbol('BackendWithClient');
export const HELLO_BACKEND_WITH_CLIENT_PATH = '/services/withClient';

export interface HelloBackendWithClientService extends RpcServer<BackendClient> {
greet(): Promise<string>
}
export const BackendClient = Symbol('BackendClient');
export interface BackendClient {
getName(): Promise<string>;
}
9 changes: 9 additions & 0 deletions templates/backend-uni/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Backend Communication Example

The example extension demonstrates how to communicate with backend services.
It contains the `HelloBackendService`, that can be called by the client to create a "Hello World" string. The client provides a name as a parameter, and the server returns the name prefixed with "Hello" (ex: "World" as a parameter returns "Hello World").
Further, the example contributes one command to trigger the backend call.

## How to use the backend communication example

In the running application, trigger the command "Say hello on the backend" via the command palette (F1 => "Say Hello"). A message will be printed out on the console from where you launched the application.
13 changes: 13 additions & 0 deletions templates/backend-uni/backend-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ConnectionHandler, RpcConnectionHandler } from '@theia/core';
import { ContainerModule } from '@theia/core/shared/inversify';
import { HelloBackendService, HELLO_BACKEND_PATH } from '../common/protocol';
import { HelloBackendServiceImpl } from './hello-backend-service';

export default new ContainerModule(bind => {
bind(HelloBackendService).to(HelloBackendServiceImpl).inSingletonScope()
bind(ConnectionHandler).toDynamicValue(ctx =>
new RpcConnectionHandler(HELLO_BACKEND_PATH, () => {
return ctx.container.get<HelloBackendService>(HelloBackendService);
})
).inSingletonScope();
});
22 changes: 22 additions & 0 deletions templates/backend-uni/contribution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Command, CommandContribution, CommandRegistry} from '@theia/core/lib/common';
import { inject, injectable } from '@theia/core/shared/inversify';
import { HelloBackendService } from '../common/protocol';

const SayHelloViaBackendCommand: Command = {
id: 'sayHelloOnBackend.command',
label: 'Say hello on the backend',
};

@injectable()
export class <%= params.extensionPrefix %>CommandContribution implements CommandContribution {

constructor(
@inject(HelloBackendService) private readonly helloBackendService: HelloBackendService,
) { }

registerCommands(registry: CommandRegistry): void {
registry.registerCommand(SayHelloViaBackendCommand, {
execute: () => this.helloBackendService.sayHelloTo('World').then(r => console.log(r))
});
}
}
14 changes: 14 additions & 0 deletions templates/backend-uni/frontend-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { CommandContribution} from '@theia/core';
import { WebSocketConnectionProvider } from '@theia/core/lib/browser';
import { ContainerModule } from '@theia/core/shared/inversify';
import { HelloBackendService, HELLO_BACKEND_PATH } from '../common/protocol';
import { <%= params.extensionPrefix %>CommandContribution} from './<%= params.extensionPath %>-contribution';

export default new ContainerModule(bind => {
bind(CommandContribution).to(<%= params.extensionPrefix %>CommandContribution).inSingletonScope();

bind(HelloBackendService).toDynamicValue(ctx => {
const connection = ctx.container.get(WebSocketConnectionProvider);
return connection.createProxy<HelloBackendService>(HELLO_BACKEND_PATH);
}).inSingletonScope();
});
9 changes: 9 additions & 0 deletions templates/backend-uni/hello-backend-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { injectable } from '@theia/core/shared/inversify';
import { HelloBackendService } from '../common/protocol';

@injectable()
export class HelloBackendServiceImpl implements HelloBackendService {
sayHelloTo(name: string): Promise<string> {
return new Promise<string>(resolve => resolve('Hello ' + name));
}
}
6 changes: 6 additions & 0 deletions templates/backend-uni/protocol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const HelloBackendService = Symbol('HelloBackendService');
export const HELLO_BACKEND_PATH = '/services/helloBackend';

export interface HelloBackendService {
sayHelloTo(name: string): Promise<string>
}

0 comments on commit 3962e06

Please sign in to comment.