5. Service Bindings
By default, Spring Cloud App Broker does not include functionality for managing bindings to its service instances. App Broker provides interfaces that service broker authors can implement to control service bindings.
5.1. Creating a Service Binding
The service broker application can implement the CreateServiceInstanceAppBindingWorkflow
interface. Alternatively, the service broker application can implement the ServiceInstanceBindingService
interface provided by Spring Cloud Open Service Broker. See Service Bindings in the Spring Cloud Open Service Broker documentation.
5.2. Deleting a Service Binding
The service broker application can implement the DeleteServiceInstanceBindingWorkflow
interface. Alternatively, the service broker application can implement the ServiceInstanceBindingService
interface provided by Spring Cloud Open Service Broker. See Service Bindings in the Spring Cloud Open Service Broker documentation.
5.3. Persisting Service Instance Binding State
Spring Cloud App Broker provides the ServiceInstanceBindingStateRepository
interface for persisting service instance binding state. The default implementation is 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.
The InMemoryServiceInstanceBindingStateRepository is provided for demonstration and testing purposes only. It is not suitable for production applications!
|
5.3.1. Example Implementation
The following example shows a service instance binding state repository implementation:
package com.example.appbroker;
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);
}
}
One option for persisting service instance binding state is to use a Spring Data CrudRepository
. The following example shows a ReactiveCrudRepository
implementation:
package com.example.appbroker;
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);
}
A model object is necessary for persisting data with a CrudRepository
. The following example shows a ServiceInstanceBinding
model:
package com.example.appbroker;
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;
}
}