Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat= Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page.

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Accessibility testing is a crucial aspect to ensure that your application is usable for everyone and meets accessibility standards that are required in many countries.

By automating these tests, teams can quickly detect issues related to screen reader compatibility, keyboard navigation, color contrast, and other aspects that could pose a barrier to using the software effectively for people with disabilities.

Learn how to automate accessibility testing with Selenium and the LambdaTest cloud-based testing platform that lets developers and testers perform accessibility automation on over 3000+ real environments:

Automated Accessibility Testing With Selenium

Partner – LambdaTest – NPI (cat= Testing)
announcement - icon

Accessibility testing is a crucial aspect to ensure that your application is usable for everyone and meets accessibility standards that are required in many countries.

By automating these tests, teams can quickly detect issues related to screen reader compatibility, keyboard navigation, color contrast, and other aspects that could pose a barrier to using the software effectively for people with disabilities.

Learn how to automate accessibility testing with Selenium and the LambdaTest cloud-based testing platform that lets developers and testers perform accessibility automation on over 3000+ real environments:

Automated Accessibility Testing With Selenium

1. Overview

When writing automated tests for software that uses JSON, we often need to compare JSON data with some expected value.

In some cases, we can treat the actual and expected JSON as strings and perform string comparison, but this has many limitations.

In this tutorial, we’ll look at how to write assertions and comparisons between JSON values using ModelAssert. We’ll see how to construct assertions on individual values within a JSON document and how to compare documents. We’ll also cover how to handle fields whose exact values cannot be predicted, such as dates or GUIDs.

2. Getting Started

ModelAssert is a data assertion library with a syntax similar to AssertJ and features comparable to JSONAssert. It’s based on Jackson for JSON parsing and uses JSON Pointer expressions to describe paths to fields in the document.

Let’s start by writing some simple assertions for this JSON:

{
   "name": "Baeldung",
   "isOnline": true,
   "topics": [ "Java", "Spring", "Kotlin", "Scala", "Linux" ]
}

2.1. Dependency

To start, let’s add ModelAssert to our pom.xml:

<dependency>
    <groupId>uk.org.webcompere</groupId>
    <artifactId>model-assert</artifactId>
    <version>1.0.0</version>
    <scope>test</scope>
</dependency>

2.2. Assert a Field in a JSON Object

Let’s imagine that the example JSON has been returned to us as a String, and we want to check that the name field is equal to Baeldung:

assertJson(jsonString)
  .at("/name").isText("Baeldung");

The assertJson method will read JSON from various sources, including StringFilePath, and Jackson’s JsonNode. The object returned is an assertion, upon which we can use the fluent DSL (domain-specific language) to add conditions.

The at method describes a place within the document where we wish to make a field assertion. Then, isText specifies that we expect a text node with the value Baeldung.

We can assert a path within the topics array by using a slightly longer JSON Pointer expression:

assertJson(jsonString)
  .at("/topics/1").isText("Spring");

While we can write field assertions one by one, we can also combine them into a single assertion:

assertJson(jsonString)
  .at("/name").isText("Baeldung")
  .at("/topics/1").isText("Spring");

2.3. Why String Comparison Doesn’t Work

Often we want to compare a whole JSON document with another. String comparison, though possible in some cases, often gets caught out by irrelevant JSON formatting issues:

String expected = loadFile(EXPECTED_JSON_PATH);
assertThat(jsonString)
  .isEqualTo(expected);

A failure message like this is common:

org.opentest4j.AssertionFailedError: 
expected: "{
    "name": "Baeldung",
    "isOnline": true,
    "topics": [ "Java", "Spring", "Kotlin", "Scala", "Linux" ]
}"
but was : "{"name": "Baeldung","isOnline": true,"topics": [ "Java", "Spring", "Kotlin", "Scala", "Linux" ]}"

2.4. Comparing Trees Semantically

To make a whole document comparison, we can use isEqualTo:

assertJson(jsonString)
  .isEqualTo(EXPECTED_JSON_PATH);

In this instance, the string of the actual JSON is loaded by assertJson, and the expected JSON document – a file described by a Path – is loaded inside the isEqualTo. The comparison is made based on the data.

2.5. Different Formats

ModelAssert also supports Java objects that can be converted to JsonNode by Jackson, as well as the yaml format.

Map<String, String> map = new HashMap<>();
map.put("name", "baeldung");

assertJson(map)
  .isEqualToYaml("name: baeldung");

For yaml handling, the isEqualToYaml method is used to indicate the format of the string or file. This requires assertYaml if the source is yaml:

assertYaml("name: baeldung")
  .isEqualTo(map);

3. Field Assertions

So far, we’ve seen some basic assertions. Let’s look at more of the DSL.

3.1. Asserting at Any Node

The DSL for ModelAssert allows nearly every possible condition to be added against any node in the tree. This is because JSON trees may contain nodes of any type at any level.

Let’s look at some assertions we might add to the root node of our example JSON:

assertJson(jsonString)
  .isNotNull()
  .isNotNumber()
  .isObject()
  .containsKey("name");

As the assertion object has these methods available on its interface, our IDE will suggest the various assertions we can add the moment we press the “.” key.

In this example, we have added lots of unnecessary conditions since the last condition already implies a non-null object.

Most often, we use JSON Pointer expressions from the root node in order to perform assertions on nodes lower down the tree:

assertJson(jsonString)
  .at("/topics").hasSize(5);

This assertion uses hasSize to check that the array in the topic field has five elements. The hasSize method operates on objects, arrays, and strings. An object’s size is its number of keys, a string’s size is its number of characters, and an array’s size is its number of elements.

Most assertions we need to make on fields depend on the exact type of the field. We can use the methods numberarraytextbooleanNode, and object to move into a more specific subset of the assertions when we’re trying to write assertions on a particular type. This is optional but can be more expressive:

assertJson(jsonString)
  .at("/isOnline").booleanNode().isTrue();

When we press the “.” key in our IDE after booleanNode, we only see autocomplete options for boolean nodes.

3.2. Text Node

When we’re asserting text nodes, we can use isText to compare using an exact value. Alternatively, we can use textContains to assert a substring:

assertJson(jsonString)
  .at("/name").textContains("ael");

We can also use regular expressions via matches:

assertJson(jsonString)
  .at("/name").matches("[A-Z].+");

This example asserts that the name starts with a capital letter.

3.3. Number Node

For number nodes, the DSL provides some useful numeric comparisons:

assertJson("{count: 12}")
  .at("/count").isBetween(1, 25);

We can also specify the Java numeric type we’re expecting:

assertJson("{height: 6.3}")
  .at("/height").isGreaterThanDouble(6.0);

The isEqualTo method is reserved for whole tree matching, so for comparing numeric equality, we use isNumberEqualTo:

assertJson("{height: 6.3}")
  .at("/height").isNumberEqualTo(6.3);

3.4. Array Node

We can test the contents of an array with isArrayContaining:

assertJson(jsonString)
  .at("/topics").isArrayContaining("Scala", "Spring");

This tests for the presence of the given values and allows the actual array to contain additional items. If we wish to assert a more exact match, we can use isArrayContainingExactlyInAnyOrder:

assertJson(jsonString)
   .at("/topics")
   .isArrayContainingExactlyInAnyOrder("Scala", "Spring", "Java", "Linux", "Kotlin");

We can also make this require the exact order:

assertJson(ACTUAL_JSON)
  .at("/topics")
  .isArrayContainingExactly("Java", "Spring", "Kotlin", "Scala", "Linux");

This is a good technique for asserting the contents of arrays that contain primitive values. Where an array contains objects, we may wish to use isEqualTo instead.

4. Whole Tree Matching

While we can construct assertions with multiple field-specific conditions to check out what’s in the JSON document, we often need to compare a whole document against another.

The isEqualTo method (or isNotEqualTo) is used to compare the whole tree. This can be combined with at to move to a subtree of the actual before making the comparison:

assertJson(jsonString)
  .at("/topics")
  .isEqualTo("[ \"Java\", \"Spring\", \"Kotlin\", \"Scala\", \"Linux\" ]");

Whole tree comparison can hit problems when the JSON contains data that is either:

  • the same, but in a different order
  • comprised of some values that cannot be predicted

The where a method is used to customize the next isEqualTo operation to get around these.

4.1. Add Key Order Constraint

Let’s look at two JSON documents that seem the same:

String actualJson = "{a:{d:3, c:2, b:1}}";
String expectedJson = "{a:{b:1, c:2, d:3}}";

We should note that this isn’t strictly JSON format. ModelAssert allows us to use the JavaScript notation for JSON, as well as the wire format that usually quotes the field names.

These two documents have exactly the same keys underneath “a”, but they’re in a different order. An assertion of these would fail, as ModelAssert defaults to strict key order.

We can relax the key order rule by adding a where configuration:

assertJson(actualJson)
  .where().keysInAnyOrder()
  .isEqualTo(expectedJson);

This allows any object in the tree to have a different order of keys from the expected document and still match.

We can localize this rule to a specific path:

assertJson(actualJson)
  .where()
    .at("/a").keysInAnyOrder()
  .isEqualTo(expectedJson);

This limits the keysInAnyOrder to just the “a” field in the root object.

The ability to customize the comparison rules allows us to handle many scenarios where the exact document produced cannot be fully controlled or predicted.

4.2. Relaxing Array Constraints

If we have arrays where the order of values can vary, then we can relax the array ordering constraint for the whole comparison:

String actualJson = "{a:[1, 2, 3, 4, 5]}";
String expectedJson = "{a:[5, 4, 3, 2, 1]}";

assertJson(actualJson)
  .where().arrayInAnyOrder()
  .isEqualTo(expectedJson);

Or we can limit that constraint to a path, as we did with keysInAnyOrder.

4.3. Ignoring Paths

Maybe our actual document contains some fields that are either uninteresting or unpredictable. We can add a rule to ignore that path:

String actualJson = "{user:{name: \"Baeldung\", url:\"http://www.baeldung.com\"}}";
String expectedJson = "{user:{name: \"Baeldung\"}}";

assertJson(actualJson)
  .where()
    .at("/user/url").isIgnored()
  .isEqualTo(expectedJson);

We should note that the path we’re expressing is always in terms of the JSON Pointer within the actual.

The extra field “url” in the actual is now ignored.

4.4. Ignore Any GUID

So far, we’ve only added rules using at in order to customize comparison at specific locations in the document.

The path syntax allows us to describe where our rules apply using wildcards. When we add an at or path condition to the where of our comparison, we can also provide any of the field assertions from above to use in place of a side-by-side comparison with the expected document.

Let’s say we had an id field that appeared in multiple places in our document and was a GUID that we couldn’t predict.

We could ignore this field with a path rule:

String actualJson = "{user:{credentials:[" +
  "{id:\"a7dc2567-3340-4a3b-b1ab-9ce1778f265d\",role:\"Admin\"}," +
  "{id:\"09da84ba-19c2-4674-974f-fd5afff3a0e5\",role:\"Sales\"}]}}";
String expectedJson = "{user:{credentials:" +
  "[{id:\"???\",role:\"Admin\"}," +
  "{id:\"???\",role:\"Sales\"}]}}";

assertJson(actualJson)
  .where()
    .path("user","credentials", ANY, "id").isIgnored()
  .isEqualTo(expectedJson);

Here, our expected value could have anything for the id field because we’ve simply ignored any field whose JSON Pointer starts “/user/credentials” then has a single node (the array index) and ends in “/id”.

4.5. Match Any GUID

Ignoring fields we can’t predict is one option. It’s better instead to match those nodes by type, and maybe also by some other condition they must meet. Let’s switch to forcing those GUIDs to match the pattern of a GUID, and let’s allow the id node to appear at any leaf node of the tree:

assertJson(actualJson)
  .where()
    .path(ANY_SUBTREE, "id").matches(GUID_PATTERN)
  .isEqualTo(expectedJson);

The ANY_SUBTREE wildcard matches any number of nodes between parts of the path expression. The GUID_PATTERN comes from the ModelAssert Patterns class, which contains some common regular expressions to match things like numbers and date stamps.

4.6. Customizing isEqualTo

The combination of where with either path or at expressions allows us to override comparisons anywhere in the tree. We either add the built-in rules for an object or array matching or specify specific alternative assertions to use for individual or classes of paths within the comparison.

Where we have a common configuration, reused across various comparisons, we can extract it into a method:

private static <T> WhereDsl<T> idsAreGuids(WhereDsl<T> where) {
    return where.path(ANY_SUBTREE, "id").matches(GUID_PATTERN);
}

Then, we can add that configuration to a particular assertion with configuredBy:

assertJson(actualJson)
  .where()
    .configuredBy(where -> idsAreGuids(where))
  .isEqualTo(expectedJson);

5. Compatibility with Other Libraries

ModelAssert was built for interoperability. So far, we’ve seen the AssertJ style assertions. These can have multiple conditions, and they will fail on the first condition that’s not met.

However, sometimes we need to produce a matcher object for use with other types of tests.

5.1. Hamcrest Matcher

Hamcrest is a major assertion helper library supported by many tools. We can use the DSL of ModelAssert to produce a Hamcrest matcher:

Matcher<String> matcher = json()
  .at("/name").hasValue("Baeldung");

The json method is used to describe a matcher that will accept a String with JSON data in it. We could also use jsonFile to produce a Matcher that expects to assert the contents of a File. The JsonAssertions class in ModelAssert contains multiple builder methods like this to start building a Hamcrest matcher.

The DSL for expressing the comparison is identical to assertJson, but the comparison isn’t executed until something uses the matcher.

We can, therefore, use ModelAssert with Hamcrest’s MatcherAssert:

MatcherAssert.assertThat(jsonString, json()
  .at("/name").hasValue("Baeldung")
  .at("/topics/1").isText("Spring"));

5.2. Using With Spring Mock MVC

While using response body verification in Spring Mock MVC, we can use Spring’s built-in jsonPath assertions. However, Spring also allows us to use Hamcrest matchers to assert the string returned as response content. This means we can perform sophisticated content assertions using ModelAssert.

5.3. Use With Mockito

Mockito is already interoperable with Hamcrest. However, ModelAssert also provides a native ArgumentMatcher. This can be used both to set up the behavior of stubs and to verify calls to them:

public interface DataService {
    boolean isUserLoggedIn(String userDetails);
}

@Mock
private DataService mockDataService;

@Test
void givenUserIsOnline_thenIsLoggedIn() {
    given(mockDataService.isUserLoggedIn(argThat(json()
      .at("/isOnline").isTrue()
      .toArgumentMatcher())))
      .willReturn(true);

    assertThat(mockDataService.isUserLoggedIn(jsonString))
      .isTrue();

    verify(mockDataService)
      .isUserLoggedIn(argThat(json()
        .at("/name").isText("Baeldung")
        .toArgumentMatcher()));
}

In this example, the Mockito argThat is used in both the setup of a mock and the verify. Inside that, we use the Hamcrest style builder for the matcher – json. Then we add conditions to it, converting to Mockito’s ArgumentMatcher at the end with toArgumentMatcher.

6. Conclusion

In this article, we looked at the need to compare JSON semantically in our tests.

We saw how ModelAssert can be used to build an assertion on individual nodes within a JSON document as well as whole trees. Then we saw how to customize tree comparison to allow for unpredictable or irrelevant differences.

Finally, we saw how to use ModelAssert with Hamcrest and other libraries.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat = Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)