Document example implementation of ServiceInstanceStateRepository
- Add example implementation in reference docs - Include warning in javadoc and reference about using in mem implementation in production Resolves #257. Resolves #314
This commit is contained in:
committed by
Roy Clarkson
parent
082daa2925
commit
e5802e6602
@@ -26,6 +26,12 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ServiceInstanceBindingStateRepository} meant for demonstration and testing purposes
|
||||
* only.
|
||||
* <p/>
|
||||
* WARNING: This implementation is not intended for production applications!
|
||||
*/
|
||||
public class InMemoryServiceInstanceBindingStateRepository implements ServiceInstanceBindingStateRepository {
|
||||
|
||||
private final Map<BindingKey, ServiceInstanceState> states = new ConcurrentSkipListMap<>();
|
||||
|
||||
@@ -25,6 +25,11 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ServiceInstanceStateRepository} meant for demonstration and testing purposes only.
|
||||
* <p/>
|
||||
* WARNING: This implementation is not intended for production applications!
|
||||
*/
|
||||
public class InMemoryServiceInstanceStateRepository implements ServiceInstanceStateRepository {
|
||||
|
||||
private final Map<String, ServiceInstanceState> states = new ConcurrentSkipListMap<>();
|
||||
|
||||
@@ -20,10 +20,6 @@ plugins {
|
||||
|
||||
description = "Spring Cloud App Broker Documentation"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
configurations {
|
||||
docs
|
||||
}
|
||||
@@ -42,6 +38,9 @@ dependencies {
|
||||
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||
implementation("org.springframework.boot:spring-boot-starter-tomcat")
|
||||
implementation("io.projectreactor:reactor-core")
|
||||
implementation("org.springframework.boot.experimental:spring-boot-starter-r2dbc:0.1.0.M3")
|
||||
implementation("org.springframework.boot.experimental:spring-boot-starter-data-r2dbc:0.1.0.M3")
|
||||
implementation("io.r2dbc:r2dbc-h2:0.8.0.RELEASE")
|
||||
|
||||
docs("io.spring.docresources:spring-doc-resources:0.1.0.RELEASE@zip")
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
:toclevels: 3
|
||||
:sectlinks:
|
||||
|
||||
:examples-dir: ../../src/test/java/com/example/appbroker/
|
||||
:sapbr: https://cloud.spring.io/spring-cloud-app-broker/
|
||||
:sapbr-href: {sapbr}[Spring Cloud App Broker]
|
||||
:sapbr-api: https://docs.spring.io/spring-cloud-app-broker/docs/{project-version}/api/
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
:examples-dir: ../../src/test/java/com/example/appbroker/
|
||||
[[service-bindings]]
|
||||
== Service Bindings
|
||||
|
||||
@@ -12,3 +13,32 @@ The service broker application can implement the {sapbr-api}/org/springframework
|
||||
=== Deleting a Service Binding
|
||||
|
||||
The service broker application can implement the {sapbr-api}/org/springframework/cloud/appbroker/service/DeleteServiceInstanceBindingWorkflow.html[`DeleteServiceInstanceBindingWorkflow`] interface. Alternatively, the service broker application can implement the `ServiceInstanceBindingService` interface provided by Spring Cloud Open Service Broker. See {scosb-docs}/#service-bindings[Service Bindings] in the {scosb-docs}/[Spring Cloud Open Service Broker documentation].
|
||||
|
||||
=== Persisting Service Instance Binding State
|
||||
|
||||
Spring Cloud App Broker provides the {sapbr-api}/org/springframework/cloud/appbroker/state/ServiceInstanceBindingStateRepository.html[`ServiceInstanceBindingStateRepository`] interface for persisting service instance binding state. The default implementation is {sapbr-api}/org/springframework/cloud/appbroker/state/InMemoryServiceInstanceBindingStateRepository.html[`InMemoryServiceInstanceBindingStateRepository`], which uses an in memory `Map` to save state and offers an easy getting started experience. In order to use a proper database for persisting state, implement `ServiceInstanceBindingStateRepository` in your application.
|
||||
|
||||
WARNING: The `InMemoryServiceInstanceBindingStateRepository` is provided for demonstration and testing purposes only. It is not suitable for production applications!
|
||||
|
||||
==== Example Implementation
|
||||
|
||||
The following example shows a service instance binding state repository implementation:
|
||||
|
||||
[source,java,%autofit]
|
||||
----
|
||||
include::{examples-dir}/ExampleServiceInstanceBindingStateRepository.java[]
|
||||
----
|
||||
|
||||
One option for persisting service instance binding state is to use a Spring Data `CrudRepository`. The following example shows a `ReactiveCrudRepository` implementation:
|
||||
|
||||
[source,java,%autofit]
|
||||
----
|
||||
include::{examples-dir}/ServiceInstanceBindingStateCrudRepository.java[]
|
||||
----
|
||||
|
||||
A model object is necessary for persisting data with a `CrudRepository`. The following example shows a `ServiceInstanceBinding` model:
|
||||
|
||||
[source,java,%autofit]
|
||||
----
|
||||
include::{examples-dir}/ServiceInstanceBinding.java[]
|
||||
----
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
:examples-dir: ../../src/test/java/com/example/appbroker/
|
||||
[[service-instances]]
|
||||
== Service Instances
|
||||
|
||||
@@ -340,3 +341,32 @@ CAUTION: Modifying certain properties, such as disk and memory, when updating an
|
||||
=== Deleting a Service Instance
|
||||
|
||||
Spring Cloud App Broker provides the {sapbr-api}/org/springframework/cloud/appbroker/workflow/instance/AppDeploymentDeleteServiceInstanceWorkflow.html[`AppDeploymentDeleteServiceInstanceWorkflow`] workflow, which handles deleting the configured backing applications and services as illustrated in the previous sections. The service broker application can implement the {sapbr-api}/org/springframework/cloud/appbroker/service/DeleteServiceInstanceWorkflow.html[`DeleteServiceInstanceWorkflow`] interface to further modify the deployment. Multiple workflows may be annotated with `@Order` so as to process the workflows in a specific order. Alternatively, the service broker application can implement the `ServiceInstanceService` interface provided by Spring Cloud Open Service Broker. See {scosb-docs}/#service-instances[Service Instances] in the {scosb-docs}/[Spring Cloud Open Service Broker documentation].
|
||||
|
||||
=== Persisting Service Instance State
|
||||
|
||||
Spring Cloud App Broker provides the {sapbr-api}/org/springframework/cloud/appbroker/state/ServiceInstanceStateRepository.html[`ServiceInstanceStateRepository`] interface for persisting service instance state. The default implementation is {sapbr-api}/org/springframework/cloud/appbroker/state/InMemoryServiceInstanceStateRepository.html[`InMemoryServiceInstanceStateRepository`], which uses an in memory `Map` to save state and offers an easy getting started experience. In order to use a proper database for persisting state, implement `ServiceInstanceStateRepository` in your application.
|
||||
|
||||
WARNING: The `InMemoryServiceInstanceStateRepository` is provided for demonstration and testing purposes only. It is not suitable for production applications!
|
||||
|
||||
==== Example Implementation
|
||||
|
||||
The following example shows a service instance state repository implementation:
|
||||
|
||||
[source,java,%autofit]
|
||||
----
|
||||
include::{examples-dir}/ExampleServiceInstanceStateRepository.java[]
|
||||
----
|
||||
|
||||
One option for persisting service instance state is to use a Spring Data `CrudRepository`. The following example shows a `ReactiveCrudRepository` implementation:
|
||||
|
||||
[source,java,%autofit]
|
||||
----
|
||||
include::{examples-dir}/ServiceInstanceStateCrudRepository.java[]
|
||||
----
|
||||
|
||||
A model object is necessary for persisting data with a `CrudRepository`. The following example shows a `ServiceInstance` model:
|
||||
|
||||
[source,java,%autofit]
|
||||
----
|
||||
include::{examples-dir}/ServiceInstance.java[]
|
||||
----
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.example.appbroker;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.appbroker.state.ServiceInstanceBindingStateRepository;
|
||||
import org.springframework.cloud.appbroker.state.ServiceInstanceState;
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
|
||||
class ExampleServiceInstanceBindingStateRepository implements ServiceInstanceBindingStateRepository {
|
||||
|
||||
private final ServiceInstanceBindingStateCrudRepository serviceInstanceBindingStateCrudRepository;
|
||||
|
||||
ExampleServiceInstanceBindingStateRepository(
|
||||
ServiceInstanceBindingStateCrudRepository serviceInstanceBindingStateCrudRepository) {
|
||||
this.serviceInstanceBindingStateCrudRepository = serviceInstanceBindingStateCrudRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ServiceInstanceState> saveState(String serviceInstanceId, String bindingId, OperationState state,
|
||||
String description) {
|
||||
return serviceInstanceBindingStateCrudRepository
|
||||
.findByServiceInstanceIdAndBindingId(serviceInstanceId, bindingId)
|
||||
.switchIfEmpty(Mono.just(new ServiceInstanceBinding()))
|
||||
.flatMap(binding -> {
|
||||
binding.setServiceInstanceId(serviceInstanceId);
|
||||
binding.setBindingId(bindingId);
|
||||
binding.setOperationState(state);
|
||||
binding.setDescription(description);
|
||||
return Mono.just(binding);
|
||||
})
|
||||
.flatMap(serviceInstanceBindingStateCrudRepository::save)
|
||||
.map(ExampleServiceInstanceBindingStateRepository::toServiceInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ServiceInstanceState> getState(String serviceInstanceId, String bindingId) {
|
||||
return serviceInstanceBindingStateCrudRepository
|
||||
.findByServiceInstanceIdAndBindingId(serviceInstanceId, bindingId)
|
||||
.switchIfEmpty(Mono.error(new IllegalArgumentException(
|
||||
"Unknown binding: serviceInstanceId=" + serviceInstanceId + ", bindingId=" + bindingId)))
|
||||
.map(ExampleServiceInstanceBindingStateRepository::toServiceInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ServiceInstanceState> removeState(String serviceInstanceId, String bindingId) {
|
||||
return getState(serviceInstanceId, bindingId)
|
||||
.doOnNext(serviceInstanceState -> serviceInstanceBindingStateCrudRepository
|
||||
.deleteByServiceInstanceIdAndBindingId(serviceInstanceId, bindingId));
|
||||
}
|
||||
|
||||
private static ServiceInstanceState toServiceInstanceState(ServiceInstanceBinding binding) {
|
||||
return new ServiceInstanceState(binding.getOperationState(), binding.getDescription(), null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.example.appbroker;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.appbroker.state.ServiceInstanceState;
|
||||
import org.springframework.cloud.appbroker.state.ServiceInstanceStateRepository;
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
|
||||
class ExampleServiceInstanceStateRepository implements ServiceInstanceStateRepository {
|
||||
|
||||
private final ServiceInstanceStateCrudRepository serviceInstanceStateCrudRepository;
|
||||
|
||||
ExampleServiceInstanceStateRepository(ServiceInstanceStateCrudRepository serviceInstanceStateCrudRepository) {
|
||||
this.serviceInstanceStateCrudRepository = serviceInstanceStateCrudRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ServiceInstanceState> saveState(String serviceInstanceId, OperationState state, String description) {
|
||||
return serviceInstanceStateCrudRepository.findByServiceInstanceId(serviceInstanceId)
|
||||
.switchIfEmpty(Mono.just(new ServiceInstance()))
|
||||
.flatMap(serviceInstance -> {
|
||||
serviceInstance.setServiceInstanceId(serviceInstanceId);
|
||||
serviceInstance.setOperationState(state);
|
||||
serviceInstance.setDescription(description);
|
||||
return Mono.just(serviceInstance);
|
||||
})
|
||||
.flatMap(serviceInstanceStateCrudRepository::save)
|
||||
.map(ExampleServiceInstanceStateRepository::toServiceInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ServiceInstanceState> getState(String serviceInstanceId) {
|
||||
return serviceInstanceStateCrudRepository.findByServiceInstanceId(serviceInstanceId)
|
||||
.switchIfEmpty(Mono.error(new IllegalArgumentException("Unknown service instance ID " + serviceInstanceId)))
|
||||
.map(ExampleServiceInstanceStateRepository::toServiceInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ServiceInstanceState> removeState(String serviceInstanceId) {
|
||||
return getState(serviceInstanceId)
|
||||
.doOnNext(serviceInstanceState -> serviceInstanceStateCrudRepository.deleteByServiceInstanceId(serviceInstanceId));
|
||||
}
|
||||
|
||||
private static ServiceInstanceState toServiceInstanceState(ServiceInstance serviceInstance) {
|
||||
return new ServiceInstanceState(serviceInstance.getOperationState(), serviceInstance.getDescription(), null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.example.appbroker;
|
||||
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
class ServiceInstance {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String serviceInstanceId;
|
||||
|
||||
private String description;
|
||||
|
||||
private OperationState operationState;
|
||||
|
||||
public ServiceInstance() {
|
||||
|
||||
}
|
||||
|
||||
public ServiceInstance(String serviceInstanceId, String description, OperationState operationState) {
|
||||
this.serviceInstanceId = serviceInstanceId;
|
||||
this.description = description;
|
||||
this.operationState = operationState;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getServiceInstanceId() {
|
||||
return serviceInstanceId;
|
||||
}
|
||||
|
||||
public void setServiceInstanceId(String serviceInstanceId) {
|
||||
this.serviceInstanceId = serviceInstanceId;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public OperationState getOperationState() {
|
||||
return operationState;
|
||||
}
|
||||
|
||||
public void setOperationState(OperationState operationState) {
|
||||
this.operationState = operationState;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.example.appbroker;
|
||||
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
class ServiceInstanceBinding {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String bindingId;
|
||||
|
||||
private String serviceInstanceId;
|
||||
|
||||
private String description;
|
||||
|
||||
private OperationState operationState;
|
||||
|
||||
public ServiceInstanceBinding() {
|
||||
|
||||
}
|
||||
|
||||
public ServiceInstanceBinding(String bindingId, String serviceInstanceId, String description,
|
||||
OperationState operationState) {
|
||||
this.bindingId = bindingId;
|
||||
this.serviceInstanceId = serviceInstanceId;
|
||||
this.description = description;
|
||||
this.operationState = operationState;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getBindingId() {
|
||||
return bindingId;
|
||||
}
|
||||
|
||||
public void setBindingId(String bindingId) {
|
||||
this.bindingId = bindingId;
|
||||
}
|
||||
|
||||
public String getServiceInstanceId() {
|
||||
return serviceInstanceId;
|
||||
}
|
||||
|
||||
public void setServiceInstanceId(String serviceInstanceId) {
|
||||
this.serviceInstanceId = serviceInstanceId;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public OperationState getOperationState() {
|
||||
return operationState;
|
||||
}
|
||||
|
||||
public void setOperationState(OperationState operationState) {
|
||||
this.operationState = operationState;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.example.appbroker;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.data.r2dbc.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
|
||||
interface ServiceInstanceBindingStateCrudRepository extends ReactiveCrudRepository<ServiceInstanceBinding, Long> {
|
||||
|
||||
@Query("select * from service_instance_binding " +
|
||||
"where service_instance_id = :service_instance_id " +
|
||||
"and binding_id = :binding_id")
|
||||
Mono<ServiceInstanceBinding> findByServiceInstanceIdAndBindingId(
|
||||
@Param("service_instance_id") String serviceInstanceId,
|
||||
@Param("binding_id") String bindingId);
|
||||
|
||||
|
||||
@Query("delete from service_instance_binding " +
|
||||
"where service_instance_id = :service_instance_id " +
|
||||
"and binding_id = :binding_id")
|
||||
Mono<Void> deleteByServiceInstanceIdAndBindingId(
|
||||
@Param("service_instance_id") String serviceInstanceId,
|
||||
@Param("binding_id") String bindingId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.example.appbroker;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.data.r2dbc.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
|
||||
interface ServiceInstanceStateCrudRepository extends ReactiveCrudRepository<ServiceInstance, Long> {
|
||||
|
||||
@Query("select * from service_instance where service_instance_id = :service_instance_id")
|
||||
Mono<ServiceInstance> findByServiceInstanceId(@Param("service_instance_id") String serviceInstanceId);
|
||||
|
||||
@Query("delete from service_instance where service_instance_id = :service_instance_id")
|
||||
Mono<Void> deleteByServiceInstanceId(@Param("service_instance_id") String serviceInstanceId);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user