Cloud Foundry Java Client

repository·main·Indexed 43 days ago

https://github.com/cloudfoundry/cf-java-client

A modular Java library for interacting with Cloud Foundry instances. It provides low-level REST API mappings via cloudfoundry-client and high-level CLI-like operations through cloudfoundry-operations. The library utilizes a reactive design pattern with Project Reactor, exposing responses as Mono and Flux.

Tokens
2.8K
Snippets
9
Records
13
Agent score
6%

What's inside Cloud Foundry Java Client

  1. Overview of Cloud Foundry Java Client components

    main

    The cf-java-client project provides Java bindings for interacting with Cloud Foundry. It is modularized into several components depending on the required level of abstraction:

    • cloudfoundry-client: Contains interfaces, request, and response objects that map to the Cloud Foundry REST APIs. It is an API-only module and does not contain an implementation.
    • cloudfoundry-client-reactor: The default implementation of cloudfoundry-client, built using Reactor Netty HttpClient.
    • cloudfoundry-operations: Provides an API and implementation that corresponds to the Cloud Foundry CLI operations. It builds on top of cloudfoundry-client and has a single implementation.
  2. How the Reactive design pattern works in cf-java-client

    main
    Both the cloudfoundry-operations and cloudfoundry-client projects follow a Reactive design pattern. All responses are exposed using Project Reactor Monos (for single values) and Fluxes (for streams of values). When using the API, you must use reactive operators like .map(), .flatMap(), or .subscribe() to handle the data.
  3. Configure ConnectionContext and TokenProvider

    main

    The lowest-level building blocks are ConnectionContext and TokenProvider. These are intended to be shared between client instances. You can instantiate them using their respective builders. In Spring applications, these should be defined as @Beans.

    DefaultConnectionContext.builder()
        .apiHost(apiHost)
        .build();
    
    PasswordGrantTokenProvider.builder()
        .password(password)
        .username(username)
        .build();
  4. Install Cloud Foundry Java Client dependencies

    main

    To use the client, you typically need both the Operations API and a Client API implementation. Most projects should include cloudfoundry-client-reactor and cloudfoundry-operations.

    Maven

    Add the following to your pom.xml:

    <dependencies>
        <dependency>
            <groupId>org.cloudfoundry</groupId>
            <artifactId>cloudfoundry-client-reactor</artifactId>
            <version>latest.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.cloudfoundry</groupId>
            <artifactId>cloudfoundry-operations</artifactId>
            <version>latest.RELEASE</version>
        </dependency>
    </dependencies>

    If you need snapshot artifacts, add the Spring snapshot repository:

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

    Gradle

    Add the following to your build.gradle:

    dependencies {
        compile 'org.cloudfoundry:cloudfoundry-client-reactor:<latest>.RELEASE'
        compile 'org.cloudfoundry:cloudfoundry-operations:<latest>.RELEASE'
    }

    For snapshots, configure the repository:

    repositories {
        maven {
            url 'https://repo.spring.io/snapshot'
        }
    }
    <dependencies>
        <dependency>
            <groupId>org.cloudfoundry</groupId>
            <artifactId>cloudfoundry-client-reactor</artifactId>
            <version>latest.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.cloudfoundry</groupId>
            <artifactId>cloudfoundry-operations</artifactId>
            <version>latest.RELEASE</version>
        </dependency>
    </dependencies>
  5. Migrate from Doppler recent-logs to Log Cache

    main

    Since version 6.0.x, DopplerClient.recentLogs() and its related types (RecentLogsRequest, LogMessage) have been removed because the underlying Loggregator Doppler endpoint was removed.

    Migration Path: Replace DopplerClient.recentLogs() calls with LogCacheClient.read() using the org.cloudfoundry.logcache.v1 package.

    Key Differences:

    FeatureDoppler (org.cloudfoundry.doppler)Log Cache (org.cloudfoundry.logcache.v1)
    Return typeFlux<Envelope>Mono<ReadResponse> (unpack via response.getEnvelopes().getBatch())
    Log accessenvelope.getLogMessage() $\rightarrow$ LogMessageenvelope.getLog() $\rightarrow$ Log
    Message textlogMessage.getMessage()log.getPayloadAsText()
    Message typeMessageType.OUT / ERRLogType.OUT / ERR
    Source metadatalogMessage.getSourceType(), .getSourceInstance()envelope.getTags().get("source_type"), envelope.getInstanceId()
    // Before (deprecated)
    dopplerClient.recentLogs(RecentLogsRequest.builder()
        .applicationId(appId)
        .build());
    
    // After
    logCacheClient.read(ReadRequest.builder()
        .sourceId(appId)
        .envelopeTypes(EnvelopeType.LOG)
        .build());
  6. Run integration tests

    main

    Integration tests can be run using the Maven wrapper.

    WARNING: Integration tests require admin access and are destructive. They should only be run against an empty Cloud Foundry instance as they affect nearly everything on the instance. It is strongly recommended to take a snapshot of your VMs before running them to allow for quick rollbacks.

    To run all integration tests:

    $ ./mvnw -Pintegration-test clean test

    To run a specific integration test class or method, use the -Dtest flag:

    ./mvnw -Pintegration-test clean test -Dtest=org.cloudfoundry.client.v3.ServiceBrokersTest#update

    To run tests with HTTP trace output enabled:

    CLIENT_LOGGING_LEVEL=trace ./mvnw -Pintegration-test clean test
  7. Build the Cloud Foundry Java Client from source

    main

    To build the project from source and install it to your local Maven cache, ensure you have Java 8 installed and have initialized submodules. Note that because the project uses Immutables, you must have an enabled annotation processor in your IDE (Eclipse or IntelliJ) for successful compilation.

    $ git submodule update --init --recursive
    $ ./mvnw clean install
  8. Debug cf-java-client requests and responses

    main

    If you encounter issues, you can capture request and response information by adjusting the logging levels. For Spring Boot applications, use the following configuration:

    • To capture basic request/response info: set logging.level.cloudfoundry-client=debug.
    • To perform a wire capture (full trace): set logging.level.cloudfoundry-client.wire=trace.
  9. Use CloudFoundryClient for low-level organization listing

    main

    The CloudFoundryClient provides more granular control over requests, such as pagination. The following example demonstrates how to request the first page of organizations and map the raw response resources to OrganizationSummary objects.

    cloudFoundryClient.organizations()
        .list(ListOrganizationsRequest.builder()
            .page(1)
            .build())
        .flatMapIterable(ListOrganizationsResponse::getResources)
        .map(resource -> OrganizationSummary.builder()
            .id(resource.getMetadata().getId())
            .name(resource.getEntity().getName())
            .build());
  10. Use CloudFoundryOperations to list organizations

    main

    Once you have a CloudFoundryOperations instance, you can perform high-level tasks. The following example lists all organizations the user belongs to, extracts their names, and prints them to the console using reactive operators.

    cloudFoundryOperations.organizations()
        .list()
        .map(OrganizationSummary::getName)
        .subscribe(System.out::println);
  11. Configure CloudFoundryOperations

    main

    While the clients provide direct access to raw REST APIs, most users should work at the CloudFoundryOperations layer. This layer provides a higher level of abstraction. The default implementation is DefaultCloudFoundryOperations.

    Note: You do not need to provide all clients. If a client is missing, the first invocation of a method requiring that specific client will return an error.

    DefaultCloudFoundryOperations.builder()
        .cloudFoundryClient(cloudFoundryClient)
        .dopplerClient(dopplerClient)
        .uaaClient(uaaClient)
        .organization("example-organization")
        .space("example-space")
        .build();
  12. Instantiate ReactorCloudFoundryClient, ReactorDopplerClient, and ReactorUaaClient

    main

    The CloudFoundryClient, DopplerClient, and UaaClient are interfaces. To use them, you must instantiate their Reactor-based implementations using builders. These builders require a ConnectionContext and a TokenProvider.

    ReactorCloudFoundryClient.builder()
        .connectionContext(connectionContext)
        .tokenProvider(tokenProvider)
        .build();
    
    ReactorDopplerClient.builder()
        .connectionContext(connectionContext)
        .tokenProvider(tokenProvider)
        .build();
    
    ReactorUaaClient.builder()
        .connectionContext(connectionContext)
        .tokenProvider(tokenProvider)
        .build();