Skip to content

Split backend service templates #177

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>
}