Introduction
- In this article, we will learn how we can use Spring boot and Java UUID class to generate a unique Identifier.
- Keep in mind that this is a very basic implementation that just touches upon some concepts and builds on top of that.
- In future articles, we will cover more interesting and production-level concepts and implementation around this topic.
Create Spring Boot Project
- We can create a UUID-Generator project at start.spring.io.
- We just need Spring Web and Devtools as a dependency.
Solution
- We will use the UUID class which is available for us to generate a unique identifier.
Controller
- Our controller consists of a GET endpoint that essentially returns the UUID to the rest client
package com.example.uuidgen.controller;
import com.example.uuidgen.logic.UUIDGeneratorLogic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("uuid-generator")
public class UUIDController {
@Autowired
private UUIDGeneratorLogic uuidGeneratorLogic;
@GetMapping("/new")
private String getID(){
return uuidGeneratorLogic.generateID();
}
}
Logic
- Logic class using Java UUID library to generate a unique identifier.
package com.example.uuidgen.logic;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class UUIDGeneratorLogic {
public String generateID(){
return UUID.randomUUID().toString();
}
}
- Now, let’s run the application and check if our endpoints are functioning as expected.
Postman Request
- Now when we send a request we get the UUID as result.
Check If a Unique ID was Issued Before
- We are also providing another endpoint to check if the given Unique ID was generated before, if yes then we return false, and otherwise false.
- Here we are keeping things simple and using HashSet to store any issued ID and use it to check if it was issued before.
- If our Set contains the issued key then we return true otherwise we return false.
Rest Endpoint
- We created another get endpoint “check” to check if the given id has already been issued before.
- This endpoint expects the id will be passed as a parameter.
@GetMapping("/check")
private Boolean checkID(@RequestParam("id") String id){
return uuidGeneratorLogic.checkID(id);
}
Simple Cache Logic
- Our cache is very naive that is essentially just a HashSet. We are storing the Issued ID into a set before returning it to the user.
- And during the check request, we simply check if it exists in the cache.
package com.example.uuidgen.logic;
import com.example.uuidgen.cache.Storage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class UUIDGeneratorLogic {
@Autowired
private Storage cache;
public String generateID(){
String id = UUID.randomUUID().toString();
cache.put(id);
return id;
}
public Boolean checkID(String id){
return cache.contains(id);
}
}
Logic
- The logic method is just a simple Hashset check.
public Boolean checkID(String id){
return cache.contains(id);
}
Testing
- We first generate a unique id using a postman request.
- Then we pass it using the check endpoint and it returns true since this id is already generated.
Problems with the Current Approach
UUID Generation
- In our current approach, we generate UUID which will provide a unique value every time generate/new endpoint is called. But these IDs are not in order. Generally, orderedId’s are good so that we can keep them sorted which helps with searching for the ID and getting associate value attached to the ID.
Storage
- Another problem is with Cache, which is essentially just a Set. The first thing that we need to do is to make our cache usable in a multithreaded environment. We can use synchronized or some other strategies.
- We can also use sophisticated caches like Redis or Memcache as separated and decoupled from our application.
- We also need to persist our records in some distributed and scalable database so that we can store our IDs for as long term. This is not necessarily required, because in some cases we just need to check the issued id for duplication in a given amount of time. For example, consider a use case like checking if this request was made within 24 hours (generally due to the retry mechanism), in that case, we keep data in our cache for 24 hours or so and we never require that id again.
Scaling
- We can scale the application layer by adding more instances. Since UUID is fairly enough to generate a unique id on every request.
- For the cache system, we can use Redis/Memcache as distributed cluster and scale horizontally.
Conclusion
- In this article, we cover a very basic implementation of a simple microservice that generates a unique id on each request.
- We also added a check mechanism that checks for the given id already generated before.
- In future articles, we will include all the issues mentioned in the Problems section and make our implementation more robust.
- If you want to learn spring boot 3 and spring boot 6, please check out this best seller and highest rated course. [ 38 hrs content, 4.7/5 stars, 6+ students already enrolled]