Practical Reactor Operations: Retrieve Cloud Foundry App Details
You can use Reactor, or rather the CF-Java-Client library built on it, get access to Cloud Foundry's Cloud Controller API to obtain, transform, and combine data.
Join the DZone community and get the full member experience.
Join For FreeCF-Java-Client is a library that enables programmatic access to a Cloud Foundry Cloud Controller API. It is built on top of Project Reactor, an implementation of the Reactive Streams specification, and it is a fun exercise to use this library to do something practical in a Cloud Foundry environment.
Consider a sample use case: Given an application ID, I need to find a little more detail on this application — more details of the application along with the details of the organization and the space that it belongs to.
To start with, the basis of all API operations with CF-Java-Client is a type unsurprisingly called the CloudFoundryClient(org.cloudfoundry.client.CloudFoundryClient). CF-Java-Client's GitHub page
has details on how to get ahold of an instance of this type.
Given a CloudFoundryClient instance, the details of an application given its id can be obtained as follows:
Mono<GetApplicationResponse> applicationResponseMono = this.cloudFoundryClient
.applicationsV2().get(GetApplicationRequest.builder().applicationId(applicationId).build());
Note that the API returns a reactor "Mono"
type, this is in general the behavior of all the API calls of cf-java-client.
- If an API returns one item then typically a Mono type is returned
- If the API is expected to return more than one item then a Flux type is returned, and
- If the API is called purely for side effects — say printing some information then it returns a Mono<Void> type
The next step is to retrieve the space identifier from the response and make an API call to retrieve the details of the space. That looks like this:
Mono<Tuple2<GetApplicationResponse, GetSpaceResponse>> appAndSpaceMono = applicationResponseMono
.and(appResponse -> this.cloudFoundryClient.spaces()
.get(GetSpaceRequest.builder()
.spaceId(appResponse.getEntity().getSpaceId()).build()));
Here, I am using an "and"
operator to combine the application response with another Mono that returns the space information. The result is a "Tuple2"
type holding both pieces of information — the application detail and the detail of the space that it is in.
Finally, to retrieve the organization that the app is deployed in:
Mono<Tuple3<GetApplicationResponse, GetSpaceResponse, GetOrganizationResponse>> t3 =
appAndSpaceMono.then(tup2 -> this.cloudFoundryClient.organizations()
.get(GetOrganizationRequest.builder()
.organizationId(tup2.getT2().getEntity()
.getOrganizationId())
.build())
.map(orgResp -> Tuples.of(tup2.getT1(), tup2.getT2(),
orgResp)));
Here, a "then"
operation is being used to retrieve the organization detail. Using the ID from the previous step and the result added onto the previous tuple, we create a Tuple3
type holding the "Application Detail," "Space Detail," and the "Organization Detail". "Then" is the equivalent of a
flatMap operator familiar in the Scala and ReactiveX world.
This essentially covers the way you would typically deal with the CF-Java-Client library and use the fact that it is built on the excellent Reactor library, and its collection of very useful operators, to get results together.
Now, we move onto the final step of transforming the result to a type that may be more relevant to your domain (handling any errors along the way):
Mono<AppDetail> appDetail =
t3.map(tup3 -> {
String appName = tup3.getT1().getEntity().getName();
String spaceName = tup3.getT2().getEntity().getName();
String orgName = tup3.getT3().getEntity().getName();
return new AppDetail(appName, orgName, spaceName);
}).otherwiseReturn(new AppDetail("", "", ""));
If you are interested in trying out a working sample, I have an example available in my GitHub repo here.
And the code shown in the article is available here.
Published at DZone with permission of Biju Kunjummen, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments