|
|
# This is a preliminary tutorial set up a Connected Service to the Sharing Platform
|
|
# This is a preliminary tutorial set up a Connected Service to the Sharing Platform
|
|
|
|
|
|
|
|
(Based on Connector-Interface v0.1.2)
|
|
(Based on Connector-Interface v1.2.1)
|
|
|
|
|
|
|
|
You can download a simple sample implementation of a connected service at https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo.
|
|
You can download a simple sample implementation of a connected service at https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo.
|
|
|
|
|
|
|
|
Disclaimer: This is not yet a fully blown tutorial. It only shows the major steps. Details can be found in the sample implementation.
|
|
Disclaimer: This is not yet a fully blown tutorial. It only shows the major steps. Details can be found in the sample implementation.
|
|
|
|
|
|
|
|
## 0. SetUp Test Environment
|
|
## 0. SetUp Test Environment
|
|
|
|
|
|
|
|
To make your connected service testable, you should ask for an integration in the test sharing plattform at https://dev-exchange.codeability-austria.uibk.ac.at/.
|
|
To make your connected service testable, you should ask for an integration in the test sharing plattform at https://dev-exchange.codeability-austria.uibk.ac.at/. To configure your tests, you must make your configuration Rest service publicly available under an URL that is reachable from the sharing plattform. The `actionTransferURL` can be an internal URL valid in your local browser.
|
|
|
To configure your tests, you must make your configuration Rest service publicly available under an URL that is reachable from the sharing plattform. The ```actionTransferURL``` can be an internal URL valid in your local browser.
|
|
|
|
|
|
|
Alternatively, you can install a local version of the sharing plattform. The developer team can provide you with further information how to share the access to the test infrastructure of the gitlab and elasticsearch index via ssh tunnels.
|
|
|
Alternatively, you can install a local version of the sharing plattform. The developer team can provide you with further information how to share the access to the test infrastructure of the gitlab and elasticsearch index via ssh tunnels.
|
|
|
|
|
|
|
## 1. Dependency
|
|
|
## 1. Dependency
|
|
|
|
|
|
|
For maven include
|
|
|
For maven include
|
|
|
|
|
```xml
|
|
```xml
|
|
|
<dependency>
|
|
<dependency>
|
|
|
<groupId>org.codeability.sharing</groupId>
|
|
<groupId>org.codeability.sharing</groupId>
|
|
|
<artifactId>SharingPluginPlatformAPI</artifactId>
|
|
<artifactId>SharingPluginPlatformAPI</artifactId>
|
|
|
<version>0.1.2</version>
|
|
<version>0.1.2</version>
|
|
|
</dependency>
|
|
</dependency>
|
|
|
```
|
|
```
|
|
|
from repository
|
|
|
|
|
```xml
|
|
from repository
|
|
|
<repository>
|
|
|
|
|
<id>codabilitySharingAPIRepository</id>
|
|
```xml
|
|
|
<name>codability Sharing API Repository via git</name>
|
|
<repository>
|
|
|
<url>https://sharing-codeability.uibk.ac.at/development/sharing/codeabilitysharingpluginapi/-/raw/master/target/</url>
|
|
<id>codabilitySharingAPIRepository</id>
|
|
|
</repository>
|
|
<name>codability Sharing API Repository via git</name>
|
|
|
```
|
|
<url>https://sharing-codeability.uibk.ac.at/development/sharing/codeabilitysharingpluginapi/-/raw/master/target/</url>
|
|
|
## 2. Provide public Config Service
|
|
</repository>
|
|
|
See classes SharingSupportResource and SharingSupportResource
|
|
```
|
|
|
|
|
|
|
|
This provides a config Rest service at
|
|
## 2. Provide public Config Service
|
|
|
http://localhost:8080/api/sharingPluginConfig
|
|
|
|
|
|
|
See classes SharingSupportResource and SharingSupportResource
|
|
|
In the Demo-Example we define a rest service
|
|
|
|
|
```java
|
|
This provides a config Rest service at [http://localhost:8080/api/sharingPluginConfig](http://localhost:8080/api/sharingPluginConfig)
|
|
|
@GetMapping("/sharingPluginConfig")
|
|
|
|
|
public ResponseEntity<SharingPluginConfig> getConfig(@RequestHeader("Authorization") String bearer,
|
|
In the Demo-Example we define a rest service
|
|
|
@RequestParam String apiBaseUrl, @RequestParam String installationName) {
|
|
|
|
|
```
|
|
```java
|
|
|
|
|
@GetMapping("/sharingPluginConfig")
|
|
|
This service takes two request parameters `apiBaseUrl` and `installationName`. Additional it takes as further parameter the `Authorization`-header. The header value typically has the form `Bearer <<access key>>, and must be checked accordingly.
|
|
public ResponseEntity<SharingPluginConfig> getConfig(@RequestHeader("Authorization") String bearer,
|
|
|
|
|
@RequestParam String apiBaseUrl, @RequestParam String installationName) {
|
|
|
Ensure that this service is accessible from everywhere (or at least from the sharing platform).
|
|
```
|
|
|
For our spring boot aplication, we have to exempt this service from spring security by
|
|
|
|
|
```java
|
|
This service takes two request parameters `apiBaseUrl` and `installationName`. Additional it takes as further parameter the `Authorization`-header. The header value typically has the form \`Bearer \<\>, and must be checked accordingly.
|
|
|
web.ignoring()
|
|
|
|
|
...
|
|
Ensure that this service is accessible from everywhere (or at least from the sharing platform). For our spring boot aplication, we have to exempt this service from spring security by
|
|
|
.antMatchers("/api/sharingPluginConfig")
|
|
|
|
|
```
|
|
```java
|
|
|
|
|
web.ignoring()
|
|
|
The returned configuration is something like
|
|
...
|
|
|
```json
|
|
.antMatchers("/api/sharingPluginConfig")
|
|
|
{
|
|
```
|
|
|
"version" : "0.1",
|
|
|
|
|
"pluginName" : "Demo Sharing Plugin Connector",
|
|
The returned configuration is something like
|
|
|
"actions" : [ {
|
|
|
|
|
"actionId" : "DemoAction1",
|
|
```json
|
|
|
"actionTransferURL" : "/sharingPluginLandingPage",
|
|
{
|
|
|
"actionName" : "Transfer Collection to Demo Plugin",
|
|
"version" : "0.1",
|
|
|
"filterELExpression" : "metadata.type.externalName=='collections'"
|
|
"pluginName" : "Demo Sharing Plugin Connector",
|
|
|
}, {
|
|
"actions" : [ {
|
|
|
"actionId" : "DemoAction2",
|
|
"actionId" : "DemoAction1",
|
|
|
"actionTransferURL" : "/sharingPluginLandingPage",
|
|
"actionTransferURL" : "/sharingPluginLandingPage",
|
|
|
"actionName" : "Transfer Programming Exercise to Demo Plugin",
|
|
"actionName" : "Transfer Collection to Demo Plugin",
|
|
|
"filterELExpression" : "metadata.type.externalName=='programming exercise'"
|
|
"filterELExpression" : "metadata.type.externalName=='collections'"
|
|
|
} ]
|
|
}, {
|
|
|
}
|
|
"actionId" : "DemoAction2",
|
|
|
```
|
|
"actionTransferURL" : "/sharingPluginLandingPage",
|
|
|
|
|
"actionName" : "Transfer Programming Exercise to Demo Plugin",
|
|
|
The demo plugin provides two actions
|
|
"filterELExpression" : "metadata.type.externalName=='programming exercise'"
|
|
|
- one action for collections
|
|
} ]
|
|
|
- another action for programming exercises
|
|
}
|
|
|
|
|
```
|
|
|
Together with the request for the connector configuration the sharing platform also transfers two parameters for further info:
|
|
|
|
|
- apiBaseUrl: the base url for the call backs to the sharing plattform (e.g. ´https://sharing.codeability-austria.uibk.ac.at/api´)
|
|
The demo plugin provides two actions
|
|
|
- installationName: an informative name for the current installation (e.g. `sharing plattform (prod)`
|
|
|
|
|
|
|
- one action for collections
|
|
|
Also it optionaly transfers in the Authentication header a bearer token to identify itself as a valid sharing platform.
|
|
- another action for programming exercises
|
|
|
|
|
|
|
|
## 3. Implement a Landing Page for each action
|
|
Together with the request for the connector configuration the sharing platform also transfers two parameters for further info:
|
|
|
|
|
|
|
|
The Landing Page is invoked as e.g. http://localhost:8080/sharingPluginLandingPage/67b1f6b5-610d-4e65-a161-ab24f478ad01?returnURL=https:%2F%2Fdev-exchange.codeability-austria.uibk.ac.at&apiBaseURL=https:%2F%2Fdev-exchange.codeability-austria.uibk.ac.at%2Fapi%2FpluginIF%2Fv0.1
|
|
- apiBaseUrl: the base url for the call backs to the sharing plattform (e.g. ´https://sharing.codeability-austria.uibk.ac.at/api´)
|
|
|
|
|
- installationName: an informative name for the current installation (e.g. `sharing plattform (prod)`
|
|
|
Implement a landing page, that can analyze the URL and extract the relevant Parameters for the basket token (e.g. 67b1f6b5-610d-4e65-a161-ab24f478ad01) and the url parameters apiBaseURL and returnURL respectively.
|
|
|
|
|
|
|
Also it optionaly transfers in the Authentication header a bearer token to identify itself as a valid sharing platform.
|
|
|
An implementation example based on Angluar can be found in the plugin demo in [app-routing.module.ts](https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo/-/blob/master/src/main/webapp/app/app-routing.module.ts)
|
|
|
|
|
```typescript
|
|
## 3. Implement a Landing Page for each action
|
|
|
// ===== Sharing Import/Export =====
|
|
|
|
|
{
|
|
The Landing Page is invoked as e.g. http://localhost:8080/sharingPluginLandingPage/67b1f6b5-610d-4e65-a161-ab24f478ad01?returnURL=https:%2F%2Fdev-exchange.codeability-austria.uibk.ac.at&apiBaseURL=https:%2F%2Fdev-exchange.codeability-austria.uibk.ac.at%2Fapi%2FpluginIF%2Fv0.1
|
|
|
path: 'sharingPluginLandingPage/:basketToken',
|
|
|
|
|
loadChildren: () => import('./sharing/sharing.module' ).then((m) => m.SharingModule),
|
|
Implement a landing page, that can analyze the URL and extract the relevant Parameters for the basket token (e.g. 67b1f6b5-610d-4e65-a161-ab24f478ad01) and the url parameters apiBaseURL and returnURL respectively.
|
|
|
},
|
|
|
|
|
|
|
An implementation example based on Angluar can be found in the plugin demo in [app-routing.module.ts](https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo/-/blob/master/src/main/webapp/app/app-routing.module.ts)
|
|
|
```
|
|
|
|
|
and [sharing.component.ts](https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo/-/blob/master/src/main/webapp/app/sharing/sharing.component.ts)
|
|
```typescript
|
|
|
|
|
// ===== Sharing Import/Export =====
|
|
|
```typescript
|
|
{
|
|
|
constructor(
|
|
path: 'sharingPluginLandingPage/:basketToken',
|
|
|
private route: ActivatedRoute,
|
|
loadChildren: () => import('./sharing/sharing.module' ).then((m) => m.SharingModule),
|
|
|
public sharingInfo: SharingInfo,
|
|
},
|
|
|
private sharingDemoService: SharingDemoService,
|
|
```
|
|
|
|
|
|
|
|
) {
|
|
and [sharing.component.ts](https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo/-/blob/master/src/main/webapp/app/sharing/sharing.component.ts)
|
|
|
this.route.params.subscribe((params) => {
|
|
|
|
|
sharingInfo.basketToken = params['basketToken'];
|
|
```typescript
|
|
|
});
|
|
constructor(
|
|
|
this.route.queryParams.subscribe((qparam) => {
|
|
private route: ActivatedRoute,
|
|
|
sharingInfo.returnURL = qparam['returnURL'];
|
|
public sharingInfo: SharingInfo,
|
|
|
sharingInfo.apiBaseURL = qparam['apiBaseURL'];
|
|
private sharingDemoService: SharingDemoService,
|
|
|
this.loadShoppingBasket();
|
|
|
|
|
});
|
|
) {
|
|
|
this.shoppingBasket = {} as ShoppingBasket;
|
|
this.route.params.subscribe((params) => {
|
|
|
this.readme = new Array(10) ;
|
|
sharingInfo.basketToken = params['basketToken'];
|
|
|
}
|
|
});
|
|
|
```
|
|
this.route.queryParams.subscribe((qparam) => {
|
|
|
|
|
sharingInfo.returnURL = qparam['returnURL'];
|
|
|
## 4. Implement the connected service's functionality
|
|
sharingInfo.apiBaseURL = qparam['apiBaseURL'];
|
|
|
|
|
this.loadShoppingBasket();
|
|
|
On the backend implement a Rest Client that can retrieve the relevant basket infos from the Sharing Platform.
|
|
});
|
|
|
|
|
this.shoppingBasket = {} as ShoppingBasket;
|
|
|
In the frontend implement the relevant service calls to the backend (see e.g. [sharing-demo.service.ts](https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo/-/blob/master/src/main/webapp/app/sharing/service/sharing-demo.service.ts)).
|
|
this.readme = new Array(10) ;
|
|
|
|
|
}
|
|
|
See as example [SharingDemoService.java](https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo/-/blob/master/src/main/java/org/codeability/sharing/demo/service/SharingDemoService.java):
|
|
```
|
|
|
|
|
|
|
|
``` java
|
|
## 4. Implement the connected service's functionality
|
|
|
public Optional<ShoppingBasket> getBasketInfo(SharingInfoDTO sharingInfo) {
|
|
|
|
|
ClientConfig restClientConfig = new ClientConfig();
|
|
On the backend implement a Rest Client that can retrieve the relevant basket infos from the Sharing Platform.
|
|
|
restClientConfig.register(ShoppingBasket.class);
|
|
|
|
|
Client client = ClientBuilder.newClient(restClientConfig);
|
|
In the frontend implement the relevant service calls to the backend (see e.g. [sharing-demo.service.ts](https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo/-/blob/master/src/main/webapp/app/sharing/service/sharing-demo.service.ts)).
|
|
|
|
|
|
|
|
WebTarget target = client.target(sharingInfo.getApiBaseURL()+"/basket/"+sharingInfo.getBasketToken());
|
|
See as example [SharingDemoService.java](https://sharing-codeability.uibk.ac.at/development/sharing/sharing-plugin-demo/-/blob/master/src/main/java/org/codeability/sharing/demo/service/SharingDemoService.java):
|
|
|
|
|
|
|
|
// TODO make error proof
|
|
```java
|
|
|
ShoppingBasket shoppingBasket = target.
|
|
public Optional<ShoppingBasket> getBasketInfo(SharingInfoDTO sharingInfo) {
|
|
|
request().
|
|
ClientConfig restClientConfig = new ClientConfig();
|
|
|
accept(MediaType.APPLICATION_JSON).
|
|
restClientConfig.register(ShoppingBasket.class);
|
|
|
get(ShoppingBasket.class);
|
|
Client client = ClientBuilder.newClient(restClientConfig);
|
|
|
return Optional.of(shoppingBasket);
|
|
|
|
|
}
|
|
WebTarget target = client.target(sharingInfo.getApiBaseURL()+"/basket/"+sharingInfo.getBasketToken());
|
|
|
```
|
|
|
|
|
|
|
// TODO make error proof
|
|
|
Based on this service you can now implement your own functionality.
|
|
ShoppingBasket shoppingBasket = target.
|
|
|
|
|
request().
|
|
|
## 5. Use the search functionality
|
|
accept(MediaType.APPLICATION_JSON).
|
|
|
|
|
get(ShoppingBasket.class);
|
|
|
You can also invoke the search functionality of the sharing plattform.
|
|
return Optional.of(shoppingBasket);
|
|
|
Find an example implementation in the demo, and further info in the [documentation](technical/Connector-Interface) |
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Based on this service you can now implement your own functionality.
|
|
|
|
|
|
|
|
## 5. Use the search functionality
|
|
|
|
|
|
|
|
You can also invoke the search functionality of the sharing plattform. Find an example implementation in the demo, and further info in the [documentation](technical/Connector-Interface) |
|
|
|
\ No newline at end of file |