DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Ultra-Fast Microservices: When MicroStream Meets Wildfly
  • Providing Enum Consistency Between Application and Data
  • Build a Java Microservice With AuraDB Free
  • Ultra-Fast Microservices: When Microstream Meets Payara

Trending

  • Revolutionizing Financial Monitoring: Building a Team Dashboard With OpenObserve
  • The Role of Functional Programming in Modern Software Development
  • SQL Server Index Optimization Strategies: Best Practices with Ola Hallengren’s Scripts
  • Rust and WebAssembly: Unlocking High-Performance Web Apps
  1. DZone
  2. Data Engineering
  3. Data
  4. Ultra-Fast Microservices: When MicroStream Meets Helidon

Ultra-Fast Microservices: When MicroStream Meets Helidon

In this fourth article of the ultra-fast series, learn a new database that can make your microservices scale up quickly in the Java world!

By 
Otavio Santana user avatar
Otavio Santana
DZone Core CORE ·
Jun. 05, 22 · Tutorial
Likes (5)
Comment
Save
Tweet
Share
7.9K Views

Join the DZone community and get the full member experience.

Join For Free

Microservices have become a buzzword when we talk about creating a scalable application. But is that enough? The simple answer is no. As with any software architecture decision, it has a trade-off and several challenges. Lucky for us Java developers, there is a combination of two tools to make our life easier: MicroStream and MicroProfile. This article will cover combining MicroStream and Helidon to create a microservice application that is easily stable and ultra-fast.

 Feel free to check out Part 1, Part 2, and Part 3 as well.

Microservices With Helidon

Microservices provide several challenges to software engineers, especially as a first step to facing distributed systems; but it does not mean that we're alone. Indeed there are several tools to make our life easier in the Java world, especially, MicroProfile. 

MicroProfile has a goal to optimize Enterprise Java for a Microservices Architecture. It is based on the Java EE/Jakarta EE standard plus API specifically for microservices such as Rest Client, Configuration, Open API, etc.

Helidon is a cloud-native, open‑source set of Java libraries for writing microservices that run on a fast web core powered by Netty.

Data Persistence Really Fast With MicroStream

Once we talk about microservices, we speak about the distributed system and its challenges, and this summons will be the same in the persistence layer. 

Unfortunately, we don't have enough articles that talk about it. We should have a model, even the schemaless databases when you have more uncertain information about the business. Still, the persistence layer has more issues, mainly because it is harder to change.

One of the secrets to making a scalable application is stateless, but we cannot afford it in the persistence layer. Primarily, the database aims to keep the information and its state.

One of the solutions to make your data persistence layer more natural is to integrate directly with the Java Entity as a graph. That is what MicroStream does. 

MicroStream realizes ultra-fast in-memory data processing with pure Java. It provides microsecond query time, low-latency data access, gigantic data throughput, and workloads. Thus it saves lots of CPU power, CO2 emission, and costs in the data center.

Show Me the Code

Let's combine both to make an ultra-fast microservice. Once the main goal is to show how both combine, we'll choose a smooth demo. In this sample, we'll create a simple CRUD with a product, its name, and rating and export it as Rest API.

The first step is to create the MicroProfile skeleton: it is effortless and smooth, mainly because we can identify visually with the MicroProfile starter. Set Microprofile version 3.3 with Java 11 and Helidon, as the picture shows below.


Yep, we have the skeleton of our application. The next step is to add the MicroStream and make both work together. Fortunately, there is a library to integrate both through CDI extension. Thus, any application with CDI and MicroProfile Config can work thanks to this API.

Please look at the latest version and add it to your application.

XML
 
 <dependency>
      <groupId>one.microstream</groupId>
      <artifactId>microstream-integrations-cdi</artifactId>
      <version>LAST_VERSION_HERE</version>
  </dependency>


The Skeleton is set, so let's start with the code. The model is the central part. Once it is a smooth sample, we'll create a Product entity with a few fields. The main recommendation to use MicroStream is to use immutable entities. Therefore, we'll create a Product as an immutable entity.

Java
 
public class Product {
    private final long id;
    private final String name;
    private final String description;
    private final int rating;

    @JsonbCreator
    public Product(
            @JsonbProperty("id") final long id,
            @JsonbProperty("name") final String name,
            @JsonbProperty("description") final String description,
            @JsonbProperty("rating") final int rating){
            //...
            }

}


JSON annotations only teach MicroProfile how to serialize the entity as JSON.

The next step is defining a collection of products, which we'll call Inventory. The Inventory class is a set of products with several operation methods. 

This class is the link between your entity and the MicroStream engine. The connection with MicroStream is using the Storage annotation.

Java
 
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;

import one.microstream.integrations.cdi.types.Storage;


@Storage
public class Inventory {
    private final Set<Product> products = new HashSet<>();

    public void add(final Product product) {
        Objects.requireNonNull(product, "product is required");
        this.products.add(product);
    }

    public Set<Product> getProducts() {
        return Collections.unmodifiableSet(this.products);
    }

    public Optional<Product> findById(final long id) {
        return this.products.stream().filter(this.isIdEquals(id)).limit(1).findFirst();
    }

    public void deleteById(final long id) {
        this.products.removeIf(this.isIdEquals(id));

    }

    private Predicate<Product> isIdEquals(final long id) {
        return p -> p.getId() == id;
    }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Inventory inventory = (Inventory) o;
    return Objects.equals(products, inventory.products);
  }

  @Override
  public int hashCode() {
    return Objects.hash(products);
  }

  @Override
  public String toString() {
    return "Inventory{" +
        "products=" + products +
        '}';
  }
}


With the collection ready, let's create the repository. To use our Inventory class, we can use the Inject annotation from CDI. We need to commit this operation to each operation that will change this collection. For any method that changes the inventory, there is the Store annotation that handles it automatically for us.

Java
 
ublic interface ProductRepository
{
  Collection<Product> getAll();
  
  Product save(Product item);
  
  Optional<Product> findById(long id);
  
  void deleteById(long id);
}


@ApplicationScoped
public class ProductRepositoryStorage implements ProductRepository {
    private static final Logger LOGGER = Logger.getLogger(ProductRepositoryStorage.class.getName());

    @Inject
    private Inventory inventory;
  
    @Override
    public Collection<Product> getAll() {
        return this.inventory.getProducts();
    }

    @Override
    @Store
    public Product save(final Product item) {
        this.inventory.add(item);
        return item;
    }

    @Override
    public Optional<Product> findById(final long id) {
        LOGGER.info("Finding the item by id: " + id);
        return this.inventory.findById(id);
    }

    @Override
    @Store
    public void deleteById(final long id) {
        this.inventory.deleteById(id);
    }
}


The last step is to expose this product as a Rest API. Then, we'll return with MicroProfile using the Jakarta EE API: JAX-RS. Next, we'll create Open API documentation using MicroProfile.

Java
 
@RequestScoped
@Path("products")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class ProductController
{
  @Inject
  private ProductRepository repository;
  
  // TODO don't worried about pagination
  @GET
   public Collection<Product> getAll()
  {
    return this.repository.getAll();
  }
  
  @GET
  @Path("{id}")
  @Operation(summary = "Find a product by id", description = "Find a product by id")
   public Product findById(@PathParam("id") final long id)
  {
    return this.repository.findById(id).orElseThrow(
      () -> new WebApplicationException("There is no product with the id " + id, Response.Status.NOT_FOUND));
  }
  
  @POST
  public Response insert(final Product product)
  {
    return Response.status(Response.Status.CREATED).entity(this.repository.save(product)).build();
  }
  
  @DELETE
  @Path("{id}")
   public Response delete(@PathParam("id") final long id){
    this.repository.deleteById(id);
    return Response.status(Response.Status.NO_CONTENT).build();
  }
  
}

That is it! We can test out the application running and check the result. The integration works like a charm. 

Shell
 
mvn clean package
java -jar target/helidon-example.jar

curl --location --request POST 'http://localhost:8080/products/' \
--header 'Content-Type: application/json' \
--data-raw '{"id": 1, "name": "banana", "description": "a fruit", "rating": 5}'

curl --location --request POST 'http://localhost:8080/products/' \
--header 'Content-Type: application/json' \
--data-raw '{"id": 2, "name": "watermelon", "description": "watermelon sugar ahh", "rating": 4}'


We finally have our integration between Helidon and MicroStream working. This tutorial shows how both work together and gives you a new tool to face persistence issues: MicroStream. Indeed MicroStream and Helidon are great allies when you want to create microservices to run it ultra-fast.

References and Resources

  • The code sample on GitHub

  • MicroStream documentation

  • Helidon documentation

Database application Inventory (library) Java (programming language) microservice Data Types

Opinions expressed by DZone contributors are their own.

Related

  • Ultra-Fast Microservices: When MicroStream Meets Wildfly
  • Providing Enum Consistency Between Application and Data
  • Build a Java Microservice With AuraDB Free
  • Ultra-Fast Microservices: When Microstream Meets Payara

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!