Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated based on comments #4186

Merged
merged 12 commits into from
Dec 4, 2024
95 changes: 55 additions & 40 deletions posts/2024-11-25-cloudant-with-open-liberty.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,53 @@ Reshmi Vijayan <https://github.com/revijay>
:url-prefix:
:url-about: /

Cloudant, an IBM-managed NoSQL database built on top of Apache CouchDB, provides a powerful solution for document-oriented storage with high availability and scalability. Cloudant provides a robust, flexible, and highly scalable NoSQL database solution that is tailor-made for cloud-native applications. Cloudant with Open Liberty offers a seamless way to build, deploy, and scale your Java applications with efficient, scalable data storage.
Cloudant, an IBM-managed NoSQL database built on top of Apache CouchDB, provides a robust, flexible, and highly scalable NoSQL database solution that is tailor-made for cloud-native applications. Cloudant with Open Liberty offers a seamless way to build, deploy, and scale your Java applications with efficient scalable data storage.

Using Cloudant with Open Liberty previously meant enabling the `cloudant-1.0` feature and configuring several elements in ``server.xml``. With CDI and MicroProfile Config, you can easily configure access to Cloudant with a CDI producer (for an introduction to using CDI producers, see the https://openliberty.io/guides/cdi-intro.html[Injecting Dependencies into Microservices guide]). The cloudant-1.0 feature was implemented using Java Cloudant Client library which is no longer supported, so in this demonstration we are using the new Cloudant SDK for Java.
Previously, using Cloudant with Open Liberty previously meant enabling the `cloudant-1.0` feature and configuring several elements in ``server.xml``. The `cloudant-1.0` feature was implemented using Java Cloudant Client library, which is no longer supported, so in this demonstration we are using the new Cloudant SDK for Java. With CDI and MicroProfile Config, you can easily configure access to Cloudant with a CDI producer (for an introduction to using CDI producers, see the https://openliberty.io/guides/cdi-intro.html[Injecting Dependencies into Microservices guide]).

== Bundle the Cloudant SDK for Java

Prior to implementing the functionality, make sure to configure the essential dependencies in your application. Depending on your build tool (Maven or Gradle), you can include the necessary Cloudant SDK libraries by adding the corresponding dependency.

* For Maven: Add the below dependency in pom.xml file:

[source, xml]
----
<dependency>
<groupId>com.ibm.cloud</groupId>
<artifactId>cloudant</artifactId>
<version>x.x.x</version>
</dependency>
----
Be sure to check for the latest version on link:https://central.sonatype.com/?smo=true[Maven Central].

* For Gradle: In your build.gradle file, add the following inside the dependencies block:

[source, groovy]
----
dependencies {
implementation 'com.ibm.cloud:ibm-cloud-sdk-core:x.x.x'
}
----

If you have multiple applications accessing Cloudant, instead of bundling the Cloudant SDK for Java with each application, you can configure a shared library in your `server.xml` like this:
[source, xml]
----
<library id="cloudantLib">
<file name="${shared.resource.dir}/cloudant-x.x.x.jar" />
</library>

<application contextRoot="/" location="app1.war">
<classloader sharedLibraryRef="cloudantLib"/>
</application>

<application contextRoot="/app2" location="app2.war">
<classloader sharedLibraryRef="cloudantLib"/>
</application>
----

== A CDI producer for Cloudant
With a CDI producer, you can easily provide a Cloudant client to your application by which you can inject the client into various parts of the application in a type-safe and flexible way, while leveraging the benefits of dependency injection (such as lifecycle management and configuration). Also, we are using link:{url-prefix}/guides/microprofile-config-intro.html[MicroProfile Config] to make the configuration of Cloudant driver simple.
With a CDI producer, you can easily provide a Cloudant client to your application and inject the client into various parts of the application in a type-safe and flexible way, with the benefits of dependency injection (such as lifecycle management and configuration). Also, we are using link:{url-prefix}/guides/microprofile-config-intro.html[MicroProfile Config] to simplify the configuration of the Cloudant driver.
This example demonstrates how to create a CDI producer to inject a Cloudant client:
[source, java]
----
Expand Down Expand Up @@ -59,7 +100,7 @@ public class CloudantProducer {
}
}
----
One of the advantages of using a CDI producer is that it can be tailored to your needs. For improved security,the createCloudant method uses Open Liberty's password decoding. This requires the following Maven dependency:
One advantage of using a CDI producer is that you can tailor it to your needs. For improved security, the `createCloudant` method uses Open Liberty's password decoding, which requires the following Maven dependency:
[source,xml]
----
<dependency>
Expand All @@ -68,7 +109,7 @@ One of the advantages of using a CDI producer is that it can be tailored to your
<version>1.0.95</version>
</dependency>
----
You also need to enable the feature in `server.xml`:
You must also enable the Password Utilities feature in your `server.xml`file:
[source, xml]
----
<feature>passwordUtilities-1.0</feature>
Expand All @@ -82,7 +123,7 @@ cloudant.dbname=testdb
----

Instead of using `BasicAuthentication` with a username and password, Cloudant also supports `IAM (Identity and Access Management)` authentication, which allows users and applications to authenticate using secure API keys or IAM tokens. By using IAM authentication, we can avoid the risks associated with managing passwords and ensure that only authorized entities can interact with Cloudant databases.
Follow the https://cloud.ibm.com/docs/Cloudant?topic=Cloudant-getting-started-with-cloudant&_ga=2.42518757.1165320250.1604321683-1614077795.1594908456[IBM Cloudant Setup] guide to create a Cloudant instance and API key for accessing it.
Follow the https://cloud.ibm.com/docs/Cloudant?topic=Cloudant-getting-started-with-cloudant[IBM Cloudant Setup] guide to create a Cloudant instance and API key for accessing it.

The code snippet below shows how can we create a CDI Producer to inject a Cloudant client with IAM authentication.
[source, java]
Expand All @@ -91,13 +132,9 @@ The code snippet below shows how can we create a CDI Producer to inject a Clouda
public class CloudantProducer {

@Inject
@ConfigProperty(name = "cloudant.host", defaultValue = "localhost")
@ConfigProperty(name = "cloudant.host")
String host;

@Inject
@ConfigProperty(name = "cloudant.port", defaultValue = "5984")
String port;

@Inject
@ConfigProperty(name = "cloudant.apikey")
String apikey;
Expand All @@ -109,7 +146,7 @@ public class CloudantProducer {
.build();

Cloudant service = new Cloudant("cloudant", authenticator);
service.setServiceUrl("http://" + host + ":" + port);
service.setServiceUrl("https://" + host);

return service;
}
Expand Down Expand Up @@ -184,42 +221,20 @@ public String remove(@PathParam("id") String id) {
.getResult();
}
----
In the above example:
In the previous example:

* The `GetDocumentOptions` class is used to configure parameters for retrieving a document from a Cloudant database. It allows you to specify the database name, document ID, and optional parameters like the document revision, whether to include attachments, conflicts, or deleted information in the response. The class uses the builder pattern to set these options before making the request to Cloudant.
* The `DeleteDocumentOptions` class is used to configure parameters for deleting a document from a Cloudant database. It allows you to specify the database name, the document ID, and the revision (_rev) of the document to ensure that the correct version is deleted (to prevent race conditions). This class uses the builder pattern to set options before sending the delete request to Cloudant.
* The `DeleteDocumentOptions` class is used to configure parameters for deleting a document from a Cloudant database. It allows you to specify the database name, the document ID, and the revision (`_rev`) of the document to ensure that the correct version is deleted and prevent race conditions. This class uses the builder pattern to set options before sending the delete request to Cloudant.

== No need for a Cloudant feature
Previously, using Cloudant required enabling the `cloudant-1.0` feature. Even if the Cloudant SDK for Java's API changes, simple updates to your CDI producer will allow it to continue to work. You should remove the `cloudant-1.0` feature from your `server.xml` when using the new Cloudant SDK for Java.
Previously, integrating Cloudant into your application required enabling the `cloudant-1.0` feature in the `server.xml` file. The CDI producer now automates the integration process, allowing you to inject Cloudant resources directly into your application without needing to explicitly enable the `cloudant-1.0` feature.

The Cloudant SDK for Java should be bundled in your application. To do this with Maven you can use a dependency:
What makes this approach even more flexible is that, even if the Cloudant SDK for Java’s API undergoes changes in the future, you won’t need to make extensive updates to your application code, meaning that simple updates to the producer itself will be sufficient to ensure continued compatibility with newer versions of the SDK.

[source, xml]
----
<dependency>
<groupId>com.ibm.cloud</groupId>
<artifactId>cloudant</artifactId>
<version>x.x.x</version>
</dependency>
----
If you have multiple applications accessing Cloudant, instead of bundling the Cloudant SDK for Java with each application, you can configure a shared library in your `server.xml` like this:
[source, xml]
----
<library id="cloudantLib">
<file name="${shared.resource.dir}/cloudant-x.x.x.jar" />
</library>

<application contextRoot="/" location="app1.war">
<classloader sharedLibraryRef="cloudantLib"/>
</application>

<application contextRoot="/app2" location="app2.war">
<classloader sharedLibraryRef="cloudantLib"/>
</application>
----
As a result, when migrating to the new Cloudant SDK for Java, it is recommended that you remove the `cloudant-1.0` feature from your server.xml file. This not only streamlines your configuration but also aligns with the new, simplified approach of using the Cloudant CDI producer for integration.

== Summary
In this blog post, we explored how easy it is to create a CDI producer for Cloudant, and configure it with MicroProfile Config to help integrate Cloudant into an Open Liberty-based Java application, leveraging the power of Cloudant's NoSQL database with the flexibility of Open Liberty’s lightweight, cloud-native architecture.
The full sample is available on GitHub here: link:https://github.com/OpenLiberty/sample-cloudant[https://github.com/OpenLiberty/sample-cloudant].
The full sample is available link:https://github.com/OpenLiberty/sample-cloudant[on GitHub].

By combining the strengths of Cloudant and Open Liberty, developers can create powerful, cloud-native applications that are both flexible and scalable, with minimal infrastructure management. This integration ensures real-time data access, robust data storage, and seamless scaling—all essential for modern, data-driven applications in the cloud.