Implement  Service  Broker  
with  Spring  Boot
Toshiaki  Maki  (@making)
Sr.  Solutions  Architect  @Pivotal
2016-‐‑‒06-‐‑‒01  Cloud  Foundry  Tokyo  Meetup #2
Who  am  I  ?
•Toshiaki  Maki  (@making)
•https://blog.ik.am
•Sr.  Solutions  Architect
•Spring  Framework  enthusiast
Spring
Framework
徹底⼊入⾨門
(Coming  
Soon?)
パーフェクト
Java  EE
(Coming  
Soon?)
Today's  Topic
•Service  Broker  Overview
•Spring  Boot  Overview
•Implement  Service  Broker
with  Spring  Boot
Service  Broker  Overview
Services  in  Cloud  Foundry
Application
Service  Broker
Service  Instance
User  Provided  Service
Managed  Services
MySQL
Redis
RabbitMQ ex.)  Oracle  DB
create-‐‑‒user-‐‑‒provided-‐‑‒servicecreate-‐‑‒service
bind-‐‑‒service
marketplace
Services  in  Cloud  Foundry
Application
Service  Broker
Service  Instance
User  Provided  Service
Managed  Services
MySQL
Redis
RabbitMQ ex.)  Oracle  DB
create-‐‑‒user-‐‑‒provided-‐‑‒servicecreate-‐‑‒service
bind-‐‑‒service
marketplace
👇
7  APIs  in  Service  Broker
• GET  /v2/catalog
• PUT  /v2/service_̲instances/:instance_̲id
• PATCH  /v2/service_̲instances/:instance_̲id
• DELETE  /v2/service_̲instances/:instance_̲id
• PUT  /v2/service_̲instances/:instance_̲id/service_̲bindings/:binding_̲id
• DELETE  /v2/service_̲instances/:instance_̲id/service_̲bindings/:binding_̲id
• GET  /v2/service_̲instances/:instance_̲id/last_̲operation
API  Overview (create  service)
Cloud  Controller
Service
cf create-service PUT
/v2/service_̲instances/:instance_̲id
Service  Broker
cf delete-service DELETE
/v2/service_̲instances/:instance_̲id
API  Overview  (bind  service)
Cloud  Controller
Service
cf bind-service PUT
/v2/service_̲instances/:instance_̲id
/service_̲bindings/:binding_̲id
Service  Broker
cf unbind-service
DELETE
/v2/service_̲instances/:instance_̲id
/service_̲bindings/:binding_̲id
Spring  Boot  Overview
Spring  Boot
• Super  Easy  Framework  in  Java
start.spring.io
start.spring.io
start.spring.io
👈
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringBootApplication.run(
DemoApplication.class, args);
}
@GetMapping("/")
String hello() {
return "Hello World";
}
}
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringBootApplication.run(
DemoApplication.class, args);
}
@GetMapping("/")
String hello() {
return "Hello World";
}
}
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringBootApplication.run(
DemoApplication.class, args);
}
@GetMapping("/")
String hello() {
return "Hello World!";
}
}
Implement  Service  Broker
with  Spring  Boot
API  Overview
Cloud  Controller
Service
cf create-service PUT
/v2/service_̲instances/:instance_̲id
Service  Broker
cf delete-service DELETE
/v2/service_̲instances/:instance_̲id
Implement  APIs
@SpringBootApplication @RestController
public class FakeServiceBroker {
// ...
@GetMapping("/v2/catalog")
CatalogResponse showCatalog() {/*...*/}
@PutMapping("/v2/service_instances/{instanceId}")
CreateResponse createServiceInstance(
@PathVariable String instanceId,
@RequestBody CreateRequest req) {/*...*/}
@PutMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}")
BindResponse createServiceBinding(
@PathVariable String instanceId ,
@PathVariable String bindingId ,
@RequestBody BindRequest req) {/*...*/}
// ...
}
@SpringBootApplication @RestController
public class FakeServiceBroker {
// ...
@GetMapping("/v2/catalog")
CatalogResponse showCatalog() {/*...*/}
@PutMapping("/v2/service_instances/{instanceId}")
CreateResponse createServiceInstance(
@PathVariable String instanceId,
@RequestBody CreateRequest req) {/*...*/}
@PutMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}")
BindResponse createServiceBinding(
@PathVariable String instanceId ,
@PathVariable String bindingId ,
@RequestBody BindRequest req) {/*...*/}
// ...
}
A lot  of
parameters
Need  to  handle  
Exceptions  ...
@SpringBootApplication @RestController
public class FakeServiceBroker {
// ...
@GetMapping("/v2/catalog")
Map<String, Object> showCatalog() {/*...*/}
@PutMapping("/v2/service_instances/{instanceId}")
Map<String, Object> createServiceInstance(
@PathVariable String instanceId,
@RequestBody Map<String, Object> req) {/*...*/}
@PutMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}")
Map<String, Object> createServiceBinding(
@PathVariable String instanceId ,
@PathVariable String bindingId ,
@RequestBody Map<String, Object> req) {/*...*/}
// ...
}
There  is  
a convenient  way
😎
Spring  Cloud  CloudFoundry Service  Broker
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-
service-broker</artifactId>
<version>1.0.0.RC3</version>
</dependency>
https://github.com/spring-­‐cloud/spring-­‐cloud-­‐cloudfoundry-­‐service-­‐broker
Service  Broker  API  Version: 2.8 (cf-‐‑‒release  v226+)
ServiceInstance
Controller
ServiceInstance
Service
@PutMapping
createServiceInstance
createServiceInstance
ServiceInstance
Controller
ServiceInstance
Service
@PutMapping
createServiceInstance
createServiceInstance
Provided You  implement
@Component
public class FakeServiceInstanceService
implements ServiceInstanceService {
public CreateServiceInstanceResponse createServiceInstance(
CreateServiceInstanceRequest req) {
String serviceInstanceId = req.getServiceInstanceId();
// ...
return new CreateServiceInstanceResponse();
}
public GetLastServiceOperationResponse getLastOperation(
GetLastServiceOperationRequest req) {/* ... */}
public DeleteServiceInstanceResponse deleteServiceInstance(
DeleteServiceInstanceRequest req) {/* ... */}
public UpdateServiceInstanceResponse updateServiceInstance(
UpdateServiceInstanceRequest req) {/* ... */}}
@Component
public class FakeServiceInstanceService
implements ServiceInstanceService {
public CreateServiceInstanceResponse createServiceInstance(
CreateServiceInstanceRequest req) {
String serviceInstanceId = req.getServiceInstanceId();
// ...
return new CreateServiceInstanceResponse();
}
public GetLastServiceOperationResponse getLastOperation(
GetLastServiceOperationRequest req) {/* ... */}
public DeleteServiceInstanceResponse deleteServiceInstance(
DeleteServiceInstanceRequest req) {/* ... */}
public UpdateServiceInstanceResponse updateServiceInstance(
UpdateServiceInstanceRequest req) {/* ... */}}
Corresponds  to
PUT  /v2/service_̲instances/:instance_̲id
@Component
public class FakeServiceInstanceBindingService
implements ServiceInstanceBindingService {
public CreateServiceInstanceBindingResponse createServiceInstanceBinding(
CreateServiceInstanceBindingRequest req) {
String serviceInstanceId = req.getServiceInstanceId();
String bindingId = req.getBindingId();
// ...
Map<String, Object> credentials = new HashMap<String, Object>() {{
put("url", "...");
put("username", "...");
put("password", "...");
}};
return new CreateServiceInstanceAppBindingResponse()
.withCredentials(credentials);
}
public void deleteServiceInstanceBinding(
DeleteServiceInstanceBindingRequest req) {
// ...
}
}
@Component
public class FakeServiceInstanceBindingService
implements ServiceInstanceBindingService {
public CreateServiceInstanceBindingResponse createServiceInstanceBinding(
CreateServiceInstanceBindingRequest req) {
String serviceInstanceId = req.getServiceInstanceId();
String bindingId = req.getBindingId();
// ...
Map<String, Object> credentials = new HashMap<String, Object>() {{
put("url", "...");
put("username", "...");
put("password", "...");
}};
return new CreateServiceInstanceAppBindingResponse()
.withCredentials(credentials);
}
public void deleteServiceInstanceBinding(
DeleteServiceInstanceBindingRequest req) {
// ...
}
}
Corresponds  to
PUT  /v2/service_̲instances/:instance_̲id
/service_̲bindings/:binding_̲id
@SpringBootApplication
public class FakeServiceBroker {
public static void main(String[] args) {
SpringBootApplication.run(
FakeServiceBroker.class, args);
}
@Bean
Catalog catalog() {
return new Catalog(singletonList(
new ServiceDefinition(
"fake-broker",
"p-fake",
"A fake service broker", ...)));
}
}
@SpringBootApplication
public class FakeServiceBroker {
public static void main(String[] args) {
SpringBootApplication.run(
FakeServiceBroker.class, args);
}
@Bean
Catalog catalog() {
return new Catalog(singletonList(
new ServiceDefinition(
"fake-broker",
"p-fake",
"A fake service broker", ...)));
}
}
Corresponds  to  GET  /v2/catalog
Authentication  Configuration
security.user.name=fake
security.user.password=fake
application.properties
https://github.com/making/fake-‐‑‒service-‐‑‒broker
Pivotal  Cloud  Foundry  for  Local  Development
https://docs.pivotal.io/pcf-‐‑‒dev/
Deploy  Service  Broker
to  Cloud  Foundry
$ ./mvnw clean package
$ cf push fake -p target/fake-1.0.0-SNAPSHOT.jar
$ curl http://fake.local.pcfdev.io/v2/catalog
Enable  Service  Broker
$ cf create-service-broker p-fake fake fake ¥
http://fake.local.pcfdev.io
$ cf enable-service-access p-fake
Service  Name Username Password
Enable  Service  Broker
$ cf create-service-broker p-fake fake fake ¥
http://fake.cfapp.io
Enable  Service  Broker
$ cf create-service-broker p-fake fake fake ¥
http://fake.cfapp.io
Server error, status code: 403, error code:
10003, message: You are not authorized to
perform the requested action
😫
$ cf create-service-broker p-fake fake fake ¥
http://fake.cfapps.io ¥
--space-scoped
Enable  Service  Broker
(Space  Scoped)
CF  CLI  6.16.0+
p-fake free A fake service broker
🙌
Create  &  Bind  Service
$ cf create-service p-fake free fake
$ cf bind-service demo fake
References
• https://github.com/spring-‐‑‒cloud/spring-‐‑‒cloud-‐‑‒cloudfoundry-‐‑‒service-‐‑‒broker
• https://github.com/spring-‐‑‒cloud-‐‑‒samples/cloudfoundry-‐‑‒service-‐‑‒broker
• https://github.com/making/fake-‐‑‒service-‐‑‒broker
• https://github.com/making/caffeine-‐‑‒broker
• https://github.com/pivotal-‐‑‒cf/brokerapi (similar  project  in  Golang)
Announce
http://pivotal-‐‑‒japan.connpass.com
Pivotal  Japan  Technical  Meetup
2016/06/29(Wed)  18:30-‐‑‒

Implement Service Broker with Spring Boot #cf_tokyo

  • 1.
    Implement  Service  Broker  with  Spring  Boot Toshiaki  Maki  (@making) Sr.  Solutions  Architect  @Pivotal 2016-‐‑‒06-‐‑‒01  Cloud  Foundry  Tokyo  Meetup #2
  • 2.
    Who  am  I ? •Toshiaki  Maki  (@making) •https://blog.ik.am •Sr.  Solutions  Architect •Spring  Framework  enthusiast Spring Framework 徹底⼊入⾨門 (Coming   Soon?) パーフェクト Java  EE (Coming   Soon?)
  • 3.
    Today's  Topic •Service  Broker Overview •Spring  Boot  Overview •Implement  Service  Broker with  Spring  Boot
  • 4.
  • 5.
    Services  in  Cloud Foundry Application Service  Broker Service  Instance User  Provided  Service Managed  Services MySQL Redis RabbitMQ ex.)  Oracle  DB create-‐‑‒user-‐‑‒provided-‐‑‒servicecreate-‐‑‒service bind-‐‑‒service marketplace
  • 6.
    Services  in  Cloud Foundry Application Service  Broker Service  Instance User  Provided  Service Managed  Services MySQL Redis RabbitMQ ex.)  Oracle  DB create-‐‑‒user-‐‑‒provided-‐‑‒servicecreate-‐‑‒service bind-‐‑‒service marketplace 👇
  • 7.
    7  APIs  in Service  Broker • GET  /v2/catalog • PUT  /v2/service_̲instances/:instance_̲id • PATCH  /v2/service_̲instances/:instance_̲id • DELETE  /v2/service_̲instances/:instance_̲id • PUT  /v2/service_̲instances/:instance_̲id/service_̲bindings/:binding_̲id • DELETE  /v2/service_̲instances/:instance_̲id/service_̲bindings/:binding_̲id • GET  /v2/service_̲instances/:instance_̲id/last_̲operation
  • 8.
    API  Overview (create service) Cloud  Controller Service cf create-service PUT /v2/service_̲instances/:instance_̲id Service  Broker cf delete-service DELETE /v2/service_̲instances/:instance_̲id
  • 9.
    API  Overview  (bind service) Cloud  Controller Service cf bind-service PUT /v2/service_̲instances/:instance_̲id /service_̲bindings/:binding_̲id Service  Broker cf unbind-service DELETE /v2/service_̲instances/:instance_̲id /service_̲bindings/:binding_̲id
  • 10.
  • 11.
    Spring  Boot • Super Easy  Framework  in  Java
  • 12.
  • 13.
  • 14.
  • 17.
    @SpringBootApplication @RestController public class DemoApplication{ public static void main(String[] args) { SpringBootApplication.run( DemoApplication.class, args); } @GetMapping("/") String hello() { return "Hello World"; } }
  • 18.
    @SpringBootApplication @RestController public class DemoApplication{ public static void main(String[] args) { SpringBootApplication.run( DemoApplication.class, args); } @GetMapping("/") String hello() { return "Hello World"; } }
  • 19.
    @SpringBootApplication @RestController public class DemoApplication{ public static void main(String[] args) { SpringBootApplication.run( DemoApplication.class, args); } @GetMapping("/") String hello() { return "Hello World!"; } }
  • 20.
  • 21.
    API  Overview Cloud  Controller Service cfcreate-service PUT /v2/service_̲instances/:instance_̲id Service  Broker cf delete-service DELETE /v2/service_̲instances/:instance_̲id Implement  APIs
  • 22.
    @SpringBootApplication @RestController public classFakeServiceBroker { // ... @GetMapping("/v2/catalog") CatalogResponse showCatalog() {/*...*/} @PutMapping("/v2/service_instances/{instanceId}") CreateResponse createServiceInstance( @PathVariable String instanceId, @RequestBody CreateRequest req) {/*...*/} @PutMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}") BindResponse createServiceBinding( @PathVariable String instanceId , @PathVariable String bindingId , @RequestBody BindRequest req) {/*...*/} // ... }
  • 23.
    @SpringBootApplication @RestController public classFakeServiceBroker { // ... @GetMapping("/v2/catalog") CatalogResponse showCatalog() {/*...*/} @PutMapping("/v2/service_instances/{instanceId}") CreateResponse createServiceInstance( @PathVariable String instanceId, @RequestBody CreateRequest req) {/*...*/} @PutMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}") BindResponse createServiceBinding( @PathVariable String instanceId , @PathVariable String bindingId , @RequestBody BindRequest req) {/*...*/} // ... } A lot  of parameters Need  to  handle   Exceptions  ...
  • 24.
    @SpringBootApplication @RestController public classFakeServiceBroker { // ... @GetMapping("/v2/catalog") Map<String, Object> showCatalog() {/*...*/} @PutMapping("/v2/service_instances/{instanceId}") Map<String, Object> createServiceInstance( @PathVariable String instanceId, @RequestBody Map<String, Object> req) {/*...*/} @PutMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}") Map<String, Object> createServiceBinding( @PathVariable String instanceId , @PathVariable String bindingId , @RequestBody Map<String, Object> req) {/*...*/} // ... } There  is   a convenient  way 😎
  • 25.
    Spring  Cloud  CloudFoundryService  Broker <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-cloudfoundry- service-broker</artifactId> <version>1.0.0.RC3</version> </dependency> https://github.com/spring-­‐cloud/spring-­‐cloud-­‐cloudfoundry-­‐service-­‐broker Service  Broker  API  Version: 2.8 (cf-‐‑‒release  v226+)
  • 26.
  • 27.
  • 28.
    @Component public class FakeServiceInstanceService implementsServiceInstanceService { public CreateServiceInstanceResponse createServiceInstance( CreateServiceInstanceRequest req) { String serviceInstanceId = req.getServiceInstanceId(); // ... return new CreateServiceInstanceResponse(); } public GetLastServiceOperationResponse getLastOperation( GetLastServiceOperationRequest req) {/* ... */} public DeleteServiceInstanceResponse deleteServiceInstance( DeleteServiceInstanceRequest req) {/* ... */} public UpdateServiceInstanceResponse updateServiceInstance( UpdateServiceInstanceRequest req) {/* ... */}}
  • 29.
    @Component public class FakeServiceInstanceService implementsServiceInstanceService { public CreateServiceInstanceResponse createServiceInstance( CreateServiceInstanceRequest req) { String serviceInstanceId = req.getServiceInstanceId(); // ... return new CreateServiceInstanceResponse(); } public GetLastServiceOperationResponse getLastOperation( GetLastServiceOperationRequest req) {/* ... */} public DeleteServiceInstanceResponse deleteServiceInstance( DeleteServiceInstanceRequest req) {/* ... */} public UpdateServiceInstanceResponse updateServiceInstance( UpdateServiceInstanceRequest req) {/* ... */}} Corresponds  to PUT  /v2/service_̲instances/:instance_̲id
  • 30.
    @Component public class FakeServiceInstanceBindingService implementsServiceInstanceBindingService { public CreateServiceInstanceBindingResponse createServiceInstanceBinding( CreateServiceInstanceBindingRequest req) { String serviceInstanceId = req.getServiceInstanceId(); String bindingId = req.getBindingId(); // ... Map<String, Object> credentials = new HashMap<String, Object>() {{ put("url", "..."); put("username", "..."); put("password", "..."); }}; return new CreateServiceInstanceAppBindingResponse() .withCredentials(credentials); } public void deleteServiceInstanceBinding( DeleteServiceInstanceBindingRequest req) { // ... } }
  • 31.
    @Component public class FakeServiceInstanceBindingService implementsServiceInstanceBindingService { public CreateServiceInstanceBindingResponse createServiceInstanceBinding( CreateServiceInstanceBindingRequest req) { String serviceInstanceId = req.getServiceInstanceId(); String bindingId = req.getBindingId(); // ... Map<String, Object> credentials = new HashMap<String, Object>() {{ put("url", "..."); put("username", "..."); put("password", "..."); }}; return new CreateServiceInstanceAppBindingResponse() .withCredentials(credentials); } public void deleteServiceInstanceBinding( DeleteServiceInstanceBindingRequest req) { // ... } } Corresponds  to PUT  /v2/service_̲instances/:instance_̲id /service_̲bindings/:binding_̲id
  • 32.
    @SpringBootApplication public class FakeServiceBroker{ public static void main(String[] args) { SpringBootApplication.run( FakeServiceBroker.class, args); } @Bean Catalog catalog() { return new Catalog(singletonList( new ServiceDefinition( "fake-broker", "p-fake", "A fake service broker", ...))); } }
  • 33.
    @SpringBootApplication public class FakeServiceBroker{ public static void main(String[] args) { SpringBootApplication.run( FakeServiceBroker.class, args); } @Bean Catalog catalog() { return new Catalog(singletonList( new ServiceDefinition( "fake-broker", "p-fake", "A fake service broker", ...))); } } Corresponds  to  GET  /v2/catalog
  • 34.
  • 35.
  • 36.
    Pivotal  Cloud  Foundry for  Local  Development https://docs.pivotal.io/pcf-‐‑‒dev/
  • 37.
    Deploy  Service  Broker to Cloud  Foundry $ ./mvnw clean package $ cf push fake -p target/fake-1.0.0-SNAPSHOT.jar $ curl http://fake.local.pcfdev.io/v2/catalog
  • 38.
    Enable  Service  Broker $cf create-service-broker p-fake fake fake ¥ http://fake.local.pcfdev.io $ cf enable-service-access p-fake Service  Name Username Password
  • 40.
    Enable  Service  Broker $cf create-service-broker p-fake fake fake ¥ http://fake.cfapp.io
  • 41.
    Enable  Service  Broker $cf create-service-broker p-fake fake fake ¥ http://fake.cfapp.io Server error, status code: 403, error code: 10003, message: You are not authorized to perform the requested action 😫
  • 42.
    $ cf create-service-brokerp-fake fake fake ¥ http://fake.cfapps.io ¥ --space-scoped Enable  Service  Broker (Space  Scoped) CF  CLI  6.16.0+
  • 43.
    p-fake free Afake service broker 🙌
  • 44.
    Create  &  Bind Service $ cf create-service p-fake free fake $ cf bind-service demo fake
  • 47.
    References • https://github.com/spring-‐‑‒cloud/spring-‐‑‒cloud-‐‑‒cloudfoundry-‐‑‒service-‐‑‒broker • https://github.com/spring-‐‑‒cloud-‐‑‒samples/cloudfoundry-‐‑‒service-‐‑‒broker •https://github.com/making/fake-‐‑‒service-‐‑‒broker • https://github.com/making/caffeine-‐‑‒broker • https://github.com/pivotal-‐‑‒cf/brokerapi (similar  project  in  Golang)
  • 48.