Exercise - Set up your Java app by using Maven
This module requires a sandbox to complete. A sandbox gives you access to free resources. Your personal subscription will not be charged. The sandbox may only be used to complete training on Microsoft Learn. Use for any other reason is prohibited, and may result in permanent loss of access to the sandbox.
Microsoft provides this lab experience and related content for educational purposes. All presented information is owned by Microsoft and intended solely for learning about the covered products and services in this Microsoft Learn module.
In this unit, you'll create a basic console app by using an IDE of your choice to edit code. You'll optionally use the terminal of your choice to run the code.
Create Azure Cosmos DB resources
For completing this lab, Microsoft Learn provides a free Azure sandbox in which you can create accounts and resources. You'll set up an Azure Cosmos DB account in this subscription and then create a database and container.
- Sign in to the Azure portal by using the same account that you activated the sandbox with.
- By using the Azure portal, create an Azure Cosmos DB account with the name of your choice. When the opportunity arrives to choose a resource group for your account, find the resource group
[Sandbox resource group] and select that. - In your Azure Cosmos DB account, create a database called Users.
- In the Users database, create a container called WebCustomers with a partition key of /userId. Provision 400 RU/s for WebCustomers.
Create your working directory
We provide a template for your Java application. Clone the template repo onto your system.
git clone https://github.com/MicrosoftDocs/mslearn-cosmos-java-sql.git
Open Windows File Explorer and go to the cloned repo. Enter the java_lab subdirectory.
Important
All of your work for this module will be under the java_lab subdirectory.
The template contains a Maven pom.xml file that already pulls in the required dependencies for your project. Open this file and examine it to find the following dependency:
XML<dependency> <groupId>com.azure</groupId> <artifactId>azure-cosmos</artifactId> <version>LATEST</version> </dependency>
This dependency pulls in the latest version of the Azure Cosmos DB Java SDK. You can close this file.
Next, you'll build and run Hello World. By using your IDE or the terminal, open this project. Depending on your IDE, there might be an option to open the pom.xml file in the java subdirectory as a project.
After the project is open, go to src/main/java/com/azure/cosmos/examples/mslearnbasicapp and open CosmosApp.java, which is a template for the Java application that we'll develop. It should look something like this:
Javaimport org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class CosmosApp { /** For application to log INFO and ERROR. */ private static Logger logger = LoggerFactory.getLogger(CosmosApp.class.getSimpleName()); private CosmosApp() { // not called } /** * Main. * @param args Command line arguments */ public static void main(final String[] args) { logger.info("Hello World."); } }
As is, the application code implements a simple "Hello World."
If your IDE offers tools to build and run your Maven application: Build and run your application by using the IDE, and confirm that the application logs
Hello World
to the terminal.If you'll use the terminal to build and run your Maven application: Use the following command to build the Maven project:
Bashmvn clean package
Then run:
Bashmvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
Confirm that the application logs the following output to the terminal:
OutputINFO: Hello World.
Connect the app to Azure Cosmos DB
Within the
CosmosApp
class, create the following static class variables for your Azure Cosmos DB connection details:Java/** Azure Cosmos DB endpoint URI. */ private static String endpointUri = "<your-cosmosdb-hostname>"; /** Azure Cosmos DB primary key. */ private static String primaryKey = "<your-cosmosdb-master-key>";
Return to the Azure portal, go to the Keys pane, and copy/paste your Azure Cosmos DB endpoint URI and primary key into the preceding variable definitions.
For example, if your URI is
https://cosmosacct.documents.azure.com:443/
, your new variable assignment will look like this:private static String endpointUri = "https://cosmosacct.documents.azure.com:443/";
. If your primary key iselzirrKCnXlacvh1CRAnQdYVbVLspmYHQyYrhx0PltHi8wn5lHVHFnd1Xm3ad5cn4TUcH4U0MSeHsVykkFPHpQ==
, your new variable assignment will look like this:private static String primaryKey = "elzirrKCnXlacvh1CRAnQdYVbVLspmYHQyYrhx0PltHi8wn5lHVHFnd1Xm3ad5cn4TUcH4U0MSeHsVykkFPHpQ==";
.
Create the CosmosAsyncClient instance
Now it's time to create an instance of CosmosAsyncClient
, which is the client-side representation of the Azure Cosmos DB service. This client is used to configure and execute requests against the service.
In CosmosApp.java, add the following static variable declaration to the
CosmosApp
class:Java/** Azure Cosmos DB client instance. */ private static CosmosAsyncClient client; /** Azure Cosmos DB database instance. */ private static CosmosAsyncDatabase database; /** Azure Cosmos DB container instance. */ private static CosmosAsyncContainer container;
Most likely, the
client
,database
, andcontainer
classes are not yet imported into your Java file. So it's a good time to take care of that now. Some IDEs might allow you to automatically import dependencies based on the code you type, and that can be useful here. In general, expect that when we give you a block of code to paste in, you might need to add someimport
statements in order for it to work.Create a
private void
method calledbasicOperations
with no arguments in the class.Add the following code to create a
CosmosAsyncClient
instance in thebasicOperations
method, and include code to check whether the Users database exists.Javaclient = new CosmosClientBuilder() .endpoint(endpointUri) .key(primaryKey) .consistencyLevel(ConsistencyLevel.EVENTUAL) .directMode() .contentResponseOnWriteEnabled(true) .buildAsyncClient(); database = client.getDatabase("Users"); container = database.getContainer("WebCustomers"); logger.info("Database and container validation complete"); client.close();
At this point, your
basicOperations
method contains the code to interact with Azure Cosmos DB. However, this method is not called inmain
, so our application still serves to print "Hello World." As a check, build and run CosmosApp.java in the IDE or run the program in the terminal by using:Bashmvn clean package mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
Confirm that the app still logs the following output to the terminal:
OutputINFO: Hello World.
Copy and paste the following code into the
main
method, overwriting the currentlogger.info("Hello World.");
line.Javatry { CosmosApp p = new CosmosApp(); p.basicOperations(); } catch (CosmosException e) { logger.error("Failed while executing app.", e); } finally { logger.info("End of demo, press any key to exit."); }
This will trigger the Azure Cosmos DB code in our application.
Build and run CosmosApp.java in the IDE, or run the program in the terminal by using:
Bashmvn clean package mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
You might see a large number of log messages in the terminal, some of which are generated by the SDK itself. Read through and confirm that the app logs the following output to the terminal:
OutputINFO: Database and container validation complete
In this unit, you set up the groundwork for your Azure Cosmos DB Java application. You set up your Maven application, created a basic "Hello World" project, and extended it to connect the project to the Azure Cosmos DB endpoint.
We provide you with a template for your Java application. Clone the template repo onto your system
git clone https://github.com/MicrosoftDocs/mslearn-cosmos-java-sql.git
Open the Windows Explorer and navigate to the cloned repo. Enter the spring_lab subdirectory.
Important
All of your work for this module will be under the spring_lab subdirectory.
The template contains a Maven pom.xml which already pulls in the required dependencies for your project. Open this file and examine it to find the dependency below:
XML<dependency> <groupId>com.azure</groupId> <artifactId>azure-spring-data-cosmos</artifactId> <version>LATEST</version> </dependency>
This dependency pulls in the latest version of Spring Data Azure Cosmos DB. You can close this file.
Connect the app to Azure Cosmos DB
By using your IDE or the terminal, open this project. Depending on your IDE, there might be an option to open the pom.xml file in the spring subdirectory as a project. After the project is open, navigate to src/main/resources/ using a file explorer tool. You should see a file named application.properties.rename. Spring Data emphasizes configuration files over hard-coded configuration parameters; to create the configuration file for your Spring Data project, copy application.properties.rename to application.properties and open the new application.properties file. You should see
Bashcosmos.uri=${ACCOUNT_HOST} cosmos.key=${ACCOUNT_KEY} cosmos.secondaryKey=${SECONDARY_ACCOUNT_KEY} dynamic.collection.name=spel-property-collection # Populate query metrics cosmos.queryMetricsEnabled=true
You are going to populate
${ACCOUNT_HOST}
and${ACCOUNT_KEY}
, using a method of your choice - either copy-paste the values into application.properties, or define these environment variables in your IDE. In the next step you will find the values these variables should have.Return to the Azure portal, go to the Keys pane, and copy the Azure Cosmos DB endpoint URI and primary key. As discussed in the previous step, use the method of your choice to assign your Azure Cosmos DB endpoint URI and primary key to the aforementioned variables.
For example, if your URI is
https://cosmosacct.documents.azure.com:443/
, and you choose to paste the endpoint and primary key into application.properties, the line in application.properties will subsequently look like this:cosmos.uri=https://cosmosacct.documents.azure.com:443/
. If your primary key iselzirrKCnXlacvh1CRAnQdYVbVLspmYHQyYrhx0PltHi8wn5lHVHFnd1Xm3ad5cn4TUcH4U0MSeHsVykkFPHpQ==
, then following the same process your new variable assignment will look like this:cosmos.key=elzirrKCnXlacvh1CRAnQdYVbVLspmYHQyYrhx0PltHi8wn5lHVHFnd1Xm3ad5cn4TUcH4U0MSeHsVykkFPHpQ==
.
Configure the Azure Cosmos DB client
Spring Data Azure Cosmos DB automatically instantiates the Azure Cosmos DB client at startup. The Azure Cosmos DB client is the client-side representation of the Azure Cosmos DB service, used to execute requests against the service. Your code can configure the Azure Cosmos DB client before it is instantiated, using a set of builder methods along with properties pulled from application.properties.
Open CosmosProperties.java. We have provided this file in a completed form, so just examine its contents.
Java@ConfigurationProperties(prefix = "cosmos") public class CosmosProperties { private String uri; private String key; private String secondaryKey; private boolean queryMetricsEnabled; public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getSecondaryKey() { return secondaryKey; } public void setSecondaryKey(String secondaryKey) { this.secondaryKey = secondaryKey; } public boolean isQueryMetricsEnabled() { return queryMetricsEnabled; } public void setQueryMetricsEnabled(boolean enableQueryMetrics) { this.queryMetricsEnabled = enableQueryMetrics; } }
Observe the class members
uri
,key
,secondaryKey
,queryMetricsEnabled
. Looking back at application.properties, observe that theCosmosProperties
member names correspond closely to the application.properties property names. TheCosmosProperties
class presents getters and setters for the rest of your application to access configuration settings from application.properties. Notice there is no code here to pull the config from application.properties - Spring Data understands the structure of this file and automatically sets the member variables after parsing the config file.We will leverage this setup going forward, when we configure the Azure Cosmos DB client.
In CosmosSampleConfiguration.java, examine the
CosmosSampleConfiguration
class and find the emptycosmosClientBuilder
method:Java@Bean public CosmosClientBuilder cosmosClientBuilder() { return null; }
At startup, Spring Data will automatically call this method, obtain the
CosmosClientBuilder
which this method returns, and call itsbuild()
method - at which point (under the hood) aCosmosAsyncClient
instance will be created based on the configuration settings contained within theCosmosClientBuilder
. You can use this method to configure theCosmosClientBuilder
using builder methods.Notice that we use constructor injection (rather than field injection using @Autowired) to instantiate the
properties
variable and populate its member variables with parsed values from the configuration file. This ensures all required dependencies are present when the instance of this class is created, and facilitates writing test code in the future.Java//use constructor injection for spring dependencies public CosmosSampleConfiguration(CosmosProperties properties){ this.properties = properties; }
We can use
properties
to get the uri and key for our Azure Cosmos DB account and implementcosmosClientBuilder
as shown below:Java@Bean public CosmosClientBuilder cosmosClientBuilder() { DirectConnectionConfig directConnectionConfig = DirectConnectionConfig.getDefaultConfig(); return new CosmosClientBuilder() .endpoint(properties.getUri()) .key(properties.getKey()) .directMode(directConnectionConfig); }
This implementation
- Pulls the uri and key from
properties
- Plugs them into the
endpoint
andkey
builder methods - Additionally configures the network connection to the Azure Cosmos DB service. (In direct mode your client application talks directly to the back-end Azure Cosmos DB partitions.)
- Pulls the uri and key from
Return to CosmosSampleConfiguration.java and find the
getDatabaseName
method:Java@Override protected String getDatabaseName() { return ""; }
Change the default return value to
"Users"
, the name of your database. This way, when Spring Data automatically connects to Azure Cosmos DB at startup, it will connect to the *Users database.Navigate to WebCustomer.java. You will notice that the
WebCustomer
class is preceded by an@Container
annotation:Java@Container(containerName = "", ru = "")
@Container
takes two arguments:containerName
: The name of the Azure Cosmos DB container (WebCustomers)ru
: The provisioned throughput on your container. 400 RU/s is a good default for a Microsoft Learn exercise.
Customize the
@Container
for your use-case, as shown:Java@Data @NoArgsConstructor @AllArgsConstructor @Container(containerName = "WebCustomers", ru = "400") public class WebCustomer {
At this point, your Spring Data project is set up to interact with Azure Cosmos DB. Next, you'll build and run Hello World. Go to src/main/java/com/azure/cosmos/examples/springexamples and open CosmosSample.java, which is a template for the Spring Data application that we'll develop. It should look something like this:
Java// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. package com.azure.cosmos.examples.springexamples; import com.azure.cosmos.CosmosException; import com.azure.cosmos.examples.springexamples.common.CouponsUsed; import com.azure.cosmos.examples.springexamples.common.OrderHistory; import com.azure.cosmos.examples.springexamples.common.ShippingPreference; import com.azure.cosmos.models.CosmosItemResponse; import com.azure.cosmos.models.PartitionKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @SpringBootApplication public class CosmosSample implements CommandLineRunner { private final Logger logger = LoggerFactory.getLogger(CosmosSample.class); private ReactiveWebCustomerRepository reactiveWebCustomerRepository; //constructor dependency injection public CosmosSample(ReactiveWebCustomerRepository reactiveWebCustomerRepository){ this.reactiveWebCustomerRepository = reactiveWebCustomerRepository; } public void run(String... var1) { logger.info("Hello world."); } }
As is, the application code implements a simple "Hello World."
If your IDE offers tools to build and run your Maven application: Build and run your application by using the IDE, and confirm that the application logs
Hello World
to the terminal.If you'll use the terminal to build and run your Maven application: Use the following command to build the Maven project:
Bashmvn clean package
Then run:
Bashmvn spring-boot:run
Confirm that the application logs the following output to the terminal, amidst all of the other output:
OutputINFO: Hello World.
In this unit, you set up the groundwork for your Azure Cosmos DB Java application. You customized the Maven application and extended a basic "Hello World" project to connect to an Azure Cosmos DB endpoint.