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

1. Introduction

In this article, we’ll discuss what ObjectId is, how we can generate it, and possible ways of ensuring its uniqueness.

2. ObjectId General Information

Let’s start by explaining what an ObjectId is. An ObjectId is a 12-byte hexadecimal value and one of the possible datatypes in BSON specification. BSON is a binary serialization of a JSON document. Moreover, MongoDB uses ObjectId as its default identifier for the _id field in documents. There is also a default unique index on the _id field set up when a collection is created.

This prevents users from inserting two documents having the same _id. Moreover, the _id index can not be dropped from the collection. However, it’s possible to have a single document with the same _id inserted into two collections.

2.1. ObjectId Structure

ObjectId can be divided into three different parts. Considering ObjectId of 6359388c80616b1fc6d7ec71, the first part would consist of 4 bytes – 6359388c. Those 4 bytes represent time in seconds since the Unix Epoch. The second part consists of the next 5 bytes, which are 80616b1fc6. Those bytes represent a random value generated once per process. The random value is unique to the machine and process. The last part is 3 bytes d7ec71, and it represents an incrementing counter which starts from a random value.

It’s also worth mentioning that the above structure is valid for MongoDB in version 4.0 and above. Before that, there were four parts of which the ObjectId was constructed. The first 4 bytes represent seconds since the Unix Epoch, and the next three are for the machine identifier.

Next 2 bytes for the process id and the last 3 bytes for the counter start from a random value.

2.2. ObjectId Uniqueness

The most important thing, which is also mentioned in the MongoDB documentation, is that the ObjectId is highly likely considered to be unique when generated. That being said, there is a very slim possibility of generating a duplicate ObjectId. Looking at the structure of ObjectId, we can see that there are over 1,8×10^19 possibilities for ObjectId to be generated within one second.

Even if all ids were generated within the same second on the same machine within the same process, that would be over 17 million possibilities just for the counter itself.

3. ObjectId Creation

There are multiple ways of creating ObjectId in Java. It can be done either with non-parameters or parametrized constructors.

3.1. ObjectId Creation With Non-parameterized Constructors

The first and one of the easiest ones is via a new keyword with the non-parametrized constructor:

ObjectId objectId = new ObjectId();

The second is simply calling a static method get() on an ObjectId class. Not directly calling the non-parametrized constructors. However, the implementation of the get() method consists of creating ObjectId the same as in the first example – through the new keyword:

ObjectId objectId = ObjectId.get();

3.2. ObjectId Creation With Parameterized Constructors

The rest of the examples use parametrized constructors. We can create an ObjectId by passing the Date class as a parameter or both the Date class and int counter. If we try to create ObjectId with the same Date in both methods, we’ll get a different ObjectId for new ObjectId(date) vs. new ObjectId(date, counter).

However, if we create two ObjectId through new ObjectId(date, counter) in the same second, we’ll get a duplicate ObjectId since it was generated in the same second, on the same machine, and with the same counter. Let’s see an example:

@Test
public void givenSameDateAndCounter_whenComparingObjectIds_thenTheyAreNotEqual() {
    Date date = new Date();
    ObjectId objectIdDate = new ObjectId(date); // 635981f6e40f61599e839ddb
    ObjectId objectIdDateCounter1 = new ObjectId(date, 100); // 635981f6e40f61599e000064
    ObjectId objectIdDateCounter2 = new ObjectId(date, 100); // 635981f6e40f61599e000064

    assertThat(objectIdDate).isNotEqualTo(objectIdDateCounter1);
    assertThat(objectIdDate).isNotEqualTo(objectIdDateCounter2);

    assertThat(objectIdDateCounter1).isEqualTo(objectIdDateCounter2);
}

Additionally, it’s possible to create ObjectId by providing a hexadecimal value straight as a parameter:

ObjectId objectIdHex = new ObjectId("635981f6e40f61599e000064");

There’re a few more possibilities to create an ObjectId. We can pass byte[] or ByteBuffer class. If we create an ObjectId by passing an array of bytes to a constructor, we should get the same ObjectId by creating it through ByteBuffer class using the same array of bytes.

Let’s see an example:

@Test
public void givenSameArrayOfBytes_whenComparingObjectIdsCreatedViaDifferentMethods_thenTheObjectIdsAreEqual(){
    byte[] bytes = "123456789012".getBytes();
    ObjectId objectIdBytes = new ObjectId(bytes);

    ByteBuffer buffer = ByteBuffer.wrap(bytes);
    ObjectId objectIdByteBuffer = new ObjectId(buffer);

    assertThat(objectIdBytes).isEqualTo(objectIdByteBuffer);
}

The last possible method would be to create an ObjectId by passing a timestamp and a counter to a constructor.

4. Pros and Cons of ObjectId

As with all things, there are pros and cons worth knowing about.

4.1. Benefits of ObjectId

Since ObjectId is 12-byte long, it’s smaller than the 16-byte UUID. That being said, if we have a lot of documents in the database using ObjectId rather than UUID, we’ll save some space. Around 26500 usages of ObjectId will save about 1MB compared to UUID. This seems to be a minimal amount.

Still, if the database is large enough and it’s also possible that a single document will have more than one occurrence of the ObjectId, then the gain of disk space and RAM might be significant since the documents, in the end, will be smaller. Secondly, as we learned before, a timestamp is embedded into the ObjectId, which might be useful in some cases.

For instance, to determine which ObjectId was created first, assuming all of them were autogenerated and not created by manipulating the Date class into the parametrized constructor as we’ve seen before.

4.2. Drawbacks of ObjectId

On the other hand, there are some identifiers even smaller than a 12-byte ObjectId, which again would save even more disk space and RAM. Furthermore, since ObjectId is just a generated hexadecimal value, this means there is a possibility of having a duplicate id. It’s very slim, but it’s still possible.

5. Ensuring the Uniqueness of ObjectId

If we have to ensure that the generated ObjectId is unique, we can try to program a bit around it to make it 100% sure it’s not a duplicate.

5.1. Try Catch DuplicateKeyException

Suppose we insert a document with a field _id already in the database. In that case, we can catch a DuplicateKeyException and retry the inserting operation until it’s successful. This method will only work on fields that have a unique index created.

Let’s see an example of that. Considering a User class:

public class User {
    public static final String NAME_FIELD = "name";

    private final ObjectId id;
    private final String name;

    // constructor
    // getters
}

We’ll insert a User into the database and then try to insert another one with the same ObjectId. This will cause DuplicateKeyException to be thrown. We can catch that and retry the insert operation of User. However, this time, we’ll generate another ObjectId. For the purpose of this test, we’ll use an embedded MongoDB library and Spring Data with MongoDB.

Let’s see an example:

@Test
public void givenUserInDatabase_whenInsertingAnotherUserWithTheSameObjectId_DKEThrownAndInsertRetried() {
    // given
    String userName = "Kevin";
    User firstUser = new User(ObjectId.get(), userName);
    User secondUser = new User(ObjectId.get(), userName);

    mongoTemplate.insert(firstUser);

    // when
    try {
        mongoTemplate.insert(firstUser);
    } catch (DuplicateKeyException dke) {
        mongoTemplate.insert(secondUser);
    }

    // then
    Query query = new Query();
    query.addCriteria(Criteria.where(User.NAME_FIELD)
      .is(userName));
    List<User> users = mongoTemplate.find(query, User.class);
    assertThat(users).usingRecursiveComparison()
      .isEqualTo(Lists.newArrayList(firstUser, secondUser));
}

5.2. Find and Insert

Another approach, probably not recommended, could be to find a document with a given ObjectId to see if it exists. If it doesn’t exist, we could insert it. Otherwise, throw an error or generate another ObjectId and try again. This method is also unreliable since there is no atomic find and insert option in MongoDB, which could lead to inconsistencies.

It’s a common approach to autogenerate ObjectId and try to insert a document without ensuring its uniqueness. It seems to be overkill to on each insert try catch DuplicateKeyException and retry the operation. The number of edge cases is very limited, and it’s tough to reproduce such a case without seeding ObjectId with either Date, counter or timestamp in the first place.

However, if, for some reason, we can’t afford to have a duplicate ObjectId due to those edge cases, then we’d consider using the above method to ensure global uniqueness.

5. Conclusion

In this article, we learned what an ObjectId is, how it’s built, how we can generate it, and possible ways of ensuring its uniqueness. In the end, it seems to be the best idea to trust the autogeneration of ObjectIds.

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

Partner – MongoDB – NPI (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

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