Welcome!
Create a Reactive Spring Single Entity Application
Do you want to create a reactive Spring project? Then, you're at the right place!
This scenario builds on a previous scenario that sets up the front end API controller. If you haven't already done so, you may want to check it out.
In this scenario, we'll learn how to:
- Set up an Astra (Cassandra as a Service) database
- Create the reactive code to access the database
- Connect the database access code to the API controller
- Use Swagger UI to access the API
This scenario is a subset of the full Spring Pet Clinic Reactive project that focuses on a single entity. Note that Reactive programming is a bit more advanced, so it may be helpful to review the basic Spring Pet Clinic example in preparation for this scenario. Here's an architectural diagram.

This scenario is also available on our datastax.com/dev site, where you can find many more resources to help you succeed with Apache Cassandra™.
ver 0.003
Congratulations!
You've completed the scenario!
Scenario Rating
We just created a Spring Reactive REST API using a single entity.
In this scenario, we learned how to:
- Set up an Astra (Cassandra as a Service) database
- Create the reactive code to access the database
- Connect the database access code to the API controller
- Use Swagger UI to access the API
This scenario focused on a single entity of the Reactive Spring Pet Clinic example to isolate and identify the necessary components. Check out the other scenarios in the Reactive Spring Pet Clinic course for further Spring Reactive ideas.
Your environment is currently being packaged as a Docker container and the download will begin shortly. To run the image locally, once Docker has been installed, use the commands
cat scrapbook_datastax_spring-reactive-pet-clinic/single-entity-backend_container.tar | docker load
docker run -it /datastax_spring-reactive-pet-clinic/single-entity-backend:
Oops!! Sorry, it looks like this scenario doesn't currently support downloads. We'll fix that shortly.

Steps
Create a Reactive Spring Single Entity Application
Try Out Swagger
In the previous scenario, we created a stubbed-out API controller that uses only a Hashtable
as a backing store.
In this scenario, we'll use that controller as a foundation and add a Cassandra reactive backend.
Let's start by running the controller from the previous scenario. Click the following.
export JAVA_HOME="/usr/lib/jvm/default-java"
cd /root/spring-petclinic-reactive
mvn spring-boot:run
You can read about, and exercise, this API using Swagger UI.
What is Swagger UI?
Swagger UI is a tool that describes the API and allows us to interact with it. You can read more here.Launch Swagger UI in a separate browser tab by clicking the following.
Expand the Owners API by clicking as shown.

From here, you can see the various REST operations. We'll start by retrieving all Owners (which is an empty list because we haven't added any Owners yet), just to see how the API works.
Expand the Get API by clicking as shown.

Click on Get's Try it out button as shown.

Click on the Execute button.

You see that the query returns an empty result set - as expected.

Let's add a record so we can see how that works.
Scroll down to the post button and click as shown.

Click the Try it out button as shown.

Edit the values within the Request body by changing the five "string" sections to "The value of your choice". Be sure to only edit the values, not the keys (e.g., "address", "city", etc.). Also, be sure to keep double quotes surrounding the values. Finally, don't change the ID value.
NOTE: If you inspect the createOwner
method in the OwnerReactiveController
class, you will notice that the method assigns a randomly generated UUID
to the newly created Owner
. However, we still need to supply a valid UUID when we post the Owner
. The response body contains the newly generated UUID
value
When you're ready, click Execute as shown.

You can now scroll up to the Get section and re-execute that query to retrieve the new record from the service.
Take some time to try out the other API operations.
When you need a UUID
value, remember to use the one from the Post response body and not the value from the Post request body.
Great! We have the controller running!
Launch the Database
The service layer of the API controller does the heavy-lifting in terms of storing and retrieving data. So far, the services layer is only using a hashtable. We want it to use a Cassandra database instead.

Let's set up an Apache Cassandra™ database.
Why use Cassandra for the database?
Apache Cassandra™ is a world-class database. It offers linear scalability that is geographically distributed and is multi-cloud.We'll use Apache Cassandra™ as a service on Astra because it's easy to set up and it's free. If you don't have an Astra account, take 30 seconds to set one up.
To deploy the database, open a tab in your browser to astra.datastax.com.
NOTE: If you already have an Astra database, you can just use it. Or, create a new keyspace. We'll show you in the following steps how to customize the app for existing Astra database settings.
When you log in the first time you'll find yourself looking at the main Astra dashboard screen that looks like the image below. click on the Add Database button.
Configure your database by selecting the Free plan.
Next, select a provider.
Now, select a region near you for your database and click the Configure button.
Fill in the Configure and Create Database fields with the following values, then click the Create Database button.
- Database name: petclinic
- Keyspace name: spring_petclinic
- Database username: astra
- Database password: astra2020
You will see the dashboard with your newly created database. While the database is initializing, the CONNECT button is inactive, but becomes active once the database is ready.
It may take a minute for the database to deploy, but you'll get an email when it's ready.
Wow, it's really easy to set up Cassandra using Astra!
Modify pom.xml
In this step, we'll modify the pom.xml file to give our project all the necessary components to access Cassandra. Start by opening the pom.xml file.
spring-petclinic-reactive/pom.xml
Take a moment to review the dependencies in pom.xml. After Spring Initializr created the pom.xml file, we added a few more things in the previous scenario. For example, we added dependencies for Swagger UI, logging and a Lombok plugin.
Now, we need to add some additional properties to specify the versions of the various tools we will be using. Click below to add the properties.
<cassandra-java-driver.version>4.8.0</cassandra-java-driver.version> <cassandra-native-protocol.version>1.4.11</cassandra-native-protocol.version> </properties>
Next, we'll add some dependencies for the Cassandra Java driver and mapper. Click below to add the dependencies.
<dependency> <groupId>com.datastax.oss</groupId> <artifactId>java-driver-core</artifactId> <version>${cassandra-java-driver.version}</version> <exclusions> <exclusion> <groupId>org.apache.tinkerpop</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.datastax.oss</groupId> <artifactId>java-driver-query-builder</artifactId> <version>${cassandra-java-driver.version}</version> </dependency> <dependency> <groupId>com.datastax.oss</groupId> <artifactId>java-driver-mapper-runtime</artifactId> <version>${cassandra-java-driver.version}</version> </dependency> <dependency> <groupId>com.datastax.oss</groupId> <artifactId>native-protocol</artifactId> <version>${cassandra-native-protocol.version}</version> </dependency> </dependencies>
Finally, we'll add the plugins for the Cassandra driver.
NOTE: Lombok must run before the Java driver mapper, so it is important that the Lombok annotation processor path precedes the mapper path.
Click below to add the plugins.
<path> <groupId>com.datastax.oss</groupId> <artifactId>java-driver-mapper-processor</artifactId> <version>${cassandra-java-driver.version}</version> </path> </annotationProcessorPaths>
We're set! We have the stuff we need to build our Cassandra backend!
Create the Persistent Entity
It's a best practice to decouple the presentation layer (i.e., the Owner) from the persistence entity. So next, let's build the persistent entity.

We'll store all the classes related to persisting the entity in their own directory (named db) within the Pet Clinic project. Click the following to create the directory.
cd /root/spring-petclinic-reactive
mkdir /root/spring-petclinic-reactive/src/main/java/org/springframework/samples/petclinic/owner/db
We'll create a new file, named OwnerEntity.java, to hold the code for the persistent entity. Click the following to create the file.
spring-petclinic-reactive/src/main/java/org/springframework/samples/petclinic/owner/db/OwnerEntity.java
You can add the code for the entity by clicking the following.
package org.springframework.samples.petclinic.owner.db; import java.util.UUID; import lombok.NoArgsConstructor; import lombok.Data; import com.datastax.oss.driver.api.mapper.annotations.CqlName; import com.datastax.oss.driver.api.mapper.annotations.Entity; import com.datastax.oss.driver.api.mapper.annotations.PartitionKey; import org.springframework.samples.petclinic.owner.Owner; /** * Simple JavaBean entity object representing an owner */ @NoArgsConstructor @Data @Entity @CqlName(OwnerEntity.OWNER_TABLE) public class OwnerEntity { public static final String OWNER_TABLE = "petclinic_owner"; public static final String OWNER_ATT_ID = "id"; public static final String OWNER_ATT_LASTNAME = "last_name"; public static final String OWNER_ATT_FIRSTNAME = "first_name"; public static final String OWNER_ATT_ADDRESS = "address"; public static final String OWNER_ATT_CITY = "city"; public static final String OWNER_ATT_TELEPHONE = "telephone"; @PartitionKey @CqlName(OWNER_ATT_ID) private UUID id; @CqlName(OWNER_ATT_FIRSTNAME) private String firstName; @CqlName(OWNER_ATT_LASTNAME) private String lastName; @CqlName(OWNER_ATT_ADDRESS) private String address; @CqlName(OWNER_ATT_CITY) private String city; @CqlName(OWNER_ATT_TELEPHONE) private String telephone; public OwnerEntity(UUID uid) { this.id = uid; } public OwnerEntity(String uid) { this(UUID.fromString(uid)); } public OwnerEntity(Owner wb) { this.id = wb.getId(); this.address = wb.getAddress(); this.city = wb.getCity(); this.firstName = wb.getFirstName(); this.lastName = wb.getLastName(); this.telephone = wb.getTelephone(); } public Owner asOwner() { Owner wb = new Owner(); wb.setAddress(getAddress()); wb.setCity(getCity()); wb.setFirstName(getFirstName()); wb.setLastName(getLastName()); wb.setTelephone(getTelephone()); wb.setId(getId()); return wb; } }
You see that this class looks a lot like the Owner
presentation class.
Notice that we also use Lombok to supply accessor methods and constructors.
However, one significant difference between this class and the Owner
class is the use of mapper annotations.
These annotations (e.g., @ParitionKey
and @CqlName
) tell the Cassandra Java driver mapper how to map the entity to the table.
Notice also that the annotations reference the table and column names we defined at the top of the class.
At the bottom of the class, you also see a constructor that has an Owner parameter. You also see a method that creates an Owner from the entity. We'll use these methods to convert between the presentation layer and the persistence entity.
Huh! It looks like the mapper will do all of the O/R mapping for us!
Declare the DAO Interface
With the database set up and the OwnerEntity
defined, let's set up the actual database access mechanism using the Java driver mapper.
We are using Java driver mapper, instead of Spring Data Cassandra, to get a finer grain access to the database.
We do this by defining two interfaces; one interface (DAO) to perform the database access, and a second interface as a factory of the first.

Let's start by creating a file to contain the DAO. Click the following to create the file.
spring-petclinic-reactive/src/main/java/org/springframework/samples/petclinic/owner/db/OwnerReactiveDao.java
Here is the interface code. Copy the code to the file by clicking the following.
package org.springframework.samples.petclinic.owner.db; import static com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy.DO_NOT_SET; import java.util.UUID; import com.datastax.dse.driver.api.core.cql.reactive.ReactiveResultSet; import com.datastax.dse.driver.api.mapper.reactive.MappedReactiveResultSet; import com.datastax.oss.driver.api.mapper.annotations.Dao; import com.datastax.oss.driver.api.mapper.annotations.DefaultNullSavingStrategy; import com.datastax.oss.driver.api.mapper.annotations.Delete; import com.datastax.oss.driver.api.mapper.annotations.Select; import com.datastax.oss.driver.api.mapper.annotations.Update; import static org.springframework.samples.petclinic.owner.db.OwnerEntity.OWNER_ATT_ADDRESS; import static org.springframework.samples.petclinic.owner.db.OwnerEntity.OWNER_ATT_CITY; import static org.springframework.samples.petclinic.owner.db.OwnerEntity.OWNER_ATT_FIRSTNAME; import static org.springframework.samples.petclinic.owner.db.OwnerEntity.OWNER_ATT_ID; import static org.springframework.samples.petclinic.owner.db.OwnerEntity.OWNER_ATT_LASTNAME; import static org.springframework.samples.petclinic.owner.db.OwnerEntity.OWNER_ATT_TELEPHONE; import static org.springframework.samples.petclinic.owner.db.OwnerEntity.OWNER_TABLE; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import static com.datastax.oss.driver.api.querybuilder.SchemaBuilder.createIndex; import static com.datastax.oss.driver.api.querybuilder.SchemaBuilder.createKeyspace; import static com.datastax.oss.driver.api.querybuilder.SchemaBuilder.createTable; import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.cql.SimpleStatement; import com.datastax.oss.driver.api.core.type.DataTypes; import com.datastax.oss.driver.api.querybuilder.QueryBuilder; @Dao @DefaultNullSavingStrategy(DO_NOT_SET) /** * Data access interface - the mapper will implement this for us */ public interface OwnerReactiveDao { /** * CREATE TABLE IF NOT EXISTS petclinic_owner ( * id uuid, * first_name text, * last_name text, * address text, * city text, * telephone text, * PRIMARY KEY ((id)) *); */ default void createSchema(CqlSession cqlSession) { cqlSession.execute(createTable(OWNER_TABLE).ifNotExists() .withPartitionKey(OWNER_ATT_ID, DataTypes.UUID) .withColumn(OWNER_ATT_FIRSTNAME, DataTypes.TEXT) .withColumn(OWNER_ATT_LASTNAME, DataTypes.TEXT) .withColumn(OWNER_ATT_ADDRESS, DataTypes.TEXT) .withColumn(OWNER_ATT_CITY, DataTypes.TEXT) .withColumn(OWNER_ATT_TELEPHONE, DataTypes.TEXT) .build()); } @Select MappedReactiveResultSet<OwnerEntity> findByIdReactive(UUID ownerid); @Select MappedReactiveResultSet<OwnerEntity> findAllReactive(); @Update ReactiveResultSet updateReactive(OwnerEntity owner); @Delete ReactiveResultSet deleteReactive(OwnerEntity owner); }
Notice that we have annotated the interface with several mapper annotations.
The @DAO
annotation tells mapper to create a DAO implementation for this interface.
The @SELECT
, @UPDATE
and @DELETE
annotations indicate to mapper which operations the methods perform.
It's really that simple with mapper - you create the interface with annotations and mapper does the rest.
Also, we added a default
method at the top, which we will use to create the table if necessary.
Hey! Using mapper to perform the O/R mapping is pretty easy!
Declare the DAO Factory Interface
We need to create a factory interface for the mapper.

Start by creating the empty file to contain the interface code by clicking the following.
spring-petclinic-reactive/src/main/java/org/springframework/samples/petclinic/owner/db/OwnerReactiveDaoMapper.java
Now, copy the interface code to the file by clicking the following.
package org.springframework.samples.petclinic.owner.db; import com.datastax.oss.driver.api.core.CqlIdentifier; import com.datastax.oss.driver.api.mapper.annotations.DaoFactory; import com.datastax.oss.driver.api.mapper.annotations.DaoKeyspace; import com.datastax.oss.driver.api.mapper.annotations.Mapper; @Mapper /** * DAO factory interface - the mapper will implement this for us */ public interface OwnerReactiveDaoMapper { @DaoFactory OwnerReactiveDao ownerDao(@DaoKeyspace CqlIdentifier keyspace); }
We see that this code has two annotations to help mapper (i.e., @Mapper
and @DaoFactory
).
Based on these annotations, mapper will create an implementation class (OwnerReactiveDaoMapperBuilder
).
Cool! That's all there is to using mapper!
Set Up the Database Config
We need a couple more classes to complete the database access. The first of these classes accesses database metadata (like keyspace name, username and password, etc.) and uses the DAO mapper framework we have just created.

We'll put this in a configuration directory. Click the following to create the directory.
mkdir /root/spring-petclinic-reactive/src/main/java/org/springframework/samples/petclinic/conf
As usual, let's start by creating an empty file to contain the class by clicking the following.
spring-petclinic-reactive/src/main/java/org/springframework/samples/petclinic/conf/CassandraReactiveConfig.java
Now, copy the class code to the file by clicking the following.
package org.springframework.samples.petclinic.conf; import java.net.InetSocketAddress; import java.time.Duration; import java.util.List; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.samples.petclinic.owner.db.OwnerReactiveDao; import org.springframework.samples.petclinic.owner.db.OwnerReactiveDaoMapperBuilder; import com.datastax.oss.driver.api.core.ConsistencyLevel; import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.config.DriverConfigLoader; import com.datastax.oss.driver.api.core.config.OptionsMap; import com.datastax.oss.driver.api.core.config.TypedDriverOption; /** * Using keys from the `application.yaml` to initialize a session with the driver. * * @author Cedrick LUNVEN (@clunven) */ @Configuration public class CassandraReactiveConfig { /** Logger for the class. */ private static final Logger LOGGER = LoggerFactory.getLogger(CassandraReactiveConfig.class); /** Spring Data Keys when autoconfiguration is OK (no AbstractReactiveCassandraConfiguration). **/ @Value("${spring.data.cassandra.keyspace-name}") private String keyspace; @Value("${spring.data.cassandra.schema-action}") private String schemaAction; @Value("${spring.data.cassandra.local-datacenter:datacenter1}") private String dc; @Value("${spring.data.cassandra.username}") private String username; @Value("${spring.data.cassandra.password}") private String password; @Value("${spring.data.cassandra.port:9042}") private int port; @Value("#{'${spring.data.cassandra.contact-points}'.split(',')}") private ListcontactPoints; @Value("${spring.data.cassandra.astra.enabled:true}") private boolean useAstra; @Value("${spring.data.cassandra.astra.secure-connect-bundle}") private String secureConnectBundle; @Bean public CqlSession cqlSession() { LOGGER.info("Initializing connection to Cassandra..."); OptionsMap om = OptionsMap.driverDefaults(); om.put(TypedDriverOption.SESSION_KEYSPACE, keyspace); om.put(TypedDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(20)); om.put(TypedDriverOption.CONNECTION_INIT_QUERY_TIMEOUT, Duration.ofSeconds(20)); om.put(TypedDriverOption.CONNECTION_SET_KEYSPACE_TIMEOUT, Duration.ofSeconds(20)); om.put(TypedDriverOption.CONTROL_CONNECTION_AGREEMENT_TIMEOUT, Duration.ofSeconds(20)); om.put(TypedDriverOption.REQUEST_CONSISTENCY, ConsistencyLevel.LOCAL_QUORUM.name()); LOGGER.info("Connection to Datastax Astrax:"); om.put(TypedDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, secureConnectBundle); om.put(TypedDriverOption.AUTH_PROVIDER_CLASS, "PlainTextAuthProvider"); om.put(TypedDriverOption.AUTH_PROVIDER_USER_NAME, username); om.put(TypedDriverOption.AUTH_PROVIDER_PASSWORD, password); CqlSession cqlSession = CqlSession.builder().withConfigLoader(DriverConfigLoader.fromMap(om)).build(); LOGGER.info("[OK] Connection established to keyspace '{}'", keyspace); return cqlSession; } /** * Initialized {@link OwnerReactiveDao} as a Spring Singleton. */ @Bean public OwnerReactiveDao ownerDao(CqlSession cqlSession) { OwnerReactiveDao reactiveDao = new OwnerReactiveDaoMapperBuilder(cqlSession) .build().ownerDao(cqlSession.getKeyspace().get()); reactiveDao.createSchema(cqlSession); return reactiveDao; } }
The first part of this class uses @Value
annotations to inject configuration settings.
We'll create the actual values for these configuration settings in the next step.
Then, the class has some methods to set up the connection to the database, including the session and the DAO.
Alright! We see how to wire up the Cassandra configuration settings!
Bind Database Config Values
In the previous step, we referenced configuration settings. In this step we will provide the values for those settings.
We could provide values using either application.properties or application.yml - it's a personal preference. Since we are more comfortable with yaml files, we'll choose the latter. Delete the application.properties file that the Spring Initializr created for us by clicking the following.
rm src/main/resources/application.properties
Now, let's create the application.yml file by clicking on the following.
spring-petclinic-reactive/src/main/resources/application.yml
Below is the content for the file. We see settings for keyspace and credentials. These reference environment variables that we will set up as the last step before we launch the service. Copy the contents to the file by clicking the following.
# Expose API through this port (setup the UI accordingly) # Spring Configuration spring: # Persistence to Apache Cassandra data: cassandra: keyspace-name: ${ASTRA_DB_KEYSPACE} username: ${ASTRA_DB_USERNAME} password: ${ASTRA_DB_PASSWORD} schema-action: CREATE_IF_NOT_EXISTS # When using Astra astra: enabled: true secure-connect-bundle: ${ASTRA_DB_BUNDLE} # When using local Cassandra (docker) contact-points: localhost #port: 9042 #local-datacenter: datacenter1
You may be wondering about the secure-connect-bundle
value.
This is an easy way to securely connect to your Astra database.
We'll set the path to the ASTRA_DB_BUNDLE
in a later step.
Wonderful! It looks like we are practically connected to Astra.
Build the Reactive Service
Finally, let's refactor the services class to use Cassandra instead of the hashtable.

Click on the following to open the file for the services class.
spring-petclinic-reactive/src/main/java/org/springframework/samples/petclinic/owner/OwnerReactiveServices.java
Here is the reactive code for the service. Notice the reactive style that uses Flux types along with lambda expressions (learn more here). Click the following to copy the code to the file.
package org.springframework.samples.petclinic.owner.db; import java.util.HashSet; import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.function.Supplier; import org.springframework.samples.petclinic.owner.Owner; import org.springframework.stereotype.Component; import org.springframework.samples.petclinic.owner.db.OwnerEntity; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @Component public class OwnerReactiveServices { private OwnerReactiveDao ownerDao; public OwnerReactiveServices(OwnerReactiveDao oDao) { this.ownerDao = oDao; } public Flux<Owner> findAllOwners() { return Flux.from(ownerDao.findAllReactive()) .map(OwnerEntity::asOwner); } public Mono<Owner> findOwnerById(String ownerId) { Objects.requireNonNull(ownerId); return Mono.from(ownerDao.findByIdReactive(UUID.fromString(ownerId))) .map(OwnerEntity::asOwner) .flatMap(this::populateOwner); } public Mono<Owner> createOwner(Owner owner) { Objects.requireNonNull(owner); OwnerEntity entity = new OwnerEntity(owner); return Mono.from(ownerDao.updateReactive(entity)) .map(rr -> entity) .map(OwnerEntity::asOwner); } public Mono<Owner> updateOwner(Owner owner) { Objects.requireNonNull(owner); OwnerEntity entity = new OwnerEntity(owner); return Mono.from(ownerDao.updateReactive(entity)) .map(rr -> entity) .map(OwnerEntity::asOwner); } public Mono<Boolean> deleteOwner(String ownerId) { Objects.requireNonNull(ownerId); return Mono.from(ownerDao.deleteReactive(new OwnerEntity(UUID.fromString(ownerId)))) .map(rr -> rr.wasApplied()); } private Mono<Owner> populateOwner(Owner wbo) { return Mono.just(wbo); } }
Outstanding! You are ready to launch the service!
Set Up the Environment
It's time to launch the REST service. We need to set up some environment variables with credentials, etc.
We'll start with Astra's secure connection bundle, which you will want to download. Here's the command, but notice you will need to replace <paste link here> with a link to the secure bundle. Copy this command and paste it in the terminal window, but DO NOT EXECUTE THE COMMAND YET!!!!!!
curl -L "<paste link here>" > creds.zip
To get the link to the secure connection bundle, on the Astra dashboard, click on the CONNECT button.
Now, select the Driver Connection Method. Then, right-click on the Download Secure Connection button and select Copy Link Address. This places the link to the secure connection bundle on the clipboard, which you will now paste into the curl command. Note that this link is time-sensitive, so you need to complete the next couple of steps without delay.
Now, go back to the terminal tab.
Paste the link (the one you just copied) into the curl
command as indicated - be sure to include the double quotes.
The curl command with the link will look something like this.
Once you have pasted the link, execute the curl
command.
Let's stop the server so we can configure it to use the database. Click the following.
echo "Stopping the server with Ctrl-C"
As you may recall, we need to create an environment variable that has the path of the secure connection bundle you just downloaded. To do this, click the following.
export ASTRA_DB_BUNDLE='/root/spring-petclinic-reactive/creds.zip'
Now, let's configure the backend to use our Astra database by setting up three more environment variables. If you followed the recommendations when you set up your database, you can just execute the following to create the necessary environment variables. Otherwise, create your own export statements for your database configuration.
Set the value for your keyspace. Click the following.
export ASTRA_DB_KEYSPACE=spring_petclinic
Set the value of your database username. Click the following.
export ASTRA_DB_USERNAME=astra
Set the value of your database password. Click the following.
export ASTRA_DB_PASSWORD=astra2020
Verify the settings are correct by clicking the following and reviewing the output.
echo $ASTRA_DB_KEYSPACE
echo $ASTRA_DB_USERNAME
echo $ASTRA_DB_PASSWORD
Launch the backend API server (this can take a minute, so please be patient). Click the following.
mvn spring-boot:run
Woot! The Reactive Spring Pet Clinic backend API server is ready!
Exercise the Reactive API
We can test the APIs using Swagger UI - the same way we did in the first step. Launch Swagger UI in a separate browser tab by clicking the following.
If you feel confident in your Swagger chops, feel free to experiment on your own. Otherwise, you can follow the guided tour described by this step.
Expand the Owners API by clicking as shown.

From here you can see the various REST operations. We'll start by retrieving all Owners (which is none because we haven't added any yet), just to see how the API works.
Expand the Get API by clicking as shown.

Click on Get's Try it out button as shown.

Click on the Execute button.

You see that the query returns an empty result set - as expected.

Let's add a record so we can see how that works.
Scroll down to the post button and click as shown.

Click the Try it out button as shown.

Edit the values within the Request body by changing the five "string" sections to "The value of your choice". Be sure to only edit the values, not the keys (e.g., "address", "city", etc.). Also, be sure to keep double quotes surrounding the values. Finally, don't change the ID value.
When you're ready, click Execute as shown.

You can now scroll up to the Get section and re-execute that query to retrieve the new record from the database.
Take some time to try out the other API operations. Note that from the Get results, you can copy the ID value when you need it in other operations such as Delete.