0

I have a below project structure

enter image description here

API

microstream:
  rest:
    enabled: true
  storage:
    order:
      root-class: 'fete.bird.entity.RootContainer'
      storage-directory: 'api/build/order-storage'

Infrastructure

@Singleton
public class OrderRepository implements IOrderRepository {
    private final RootProvider<RootContainer> rootProvider;

    public OrderRepository(RootProvider<RootContainer> rootProvider) {
        this.rootProvider = rootProvider;
    }

    @Override
    public Order create(Order order) {
        Map<UUID, Order> root = rootProvider.root().getOrders();
        root.put(order.id(), order);
        return order;
    }
}

Core

@Introspected
public interface IOrderRepository {
    Order create(Order order);
}

Controller

@Controller("/order")
public class OrderController {
private final IOrderRepository iOrderRepository;

    public OrderController(IOrderRepository iOrderRepository) {
        this.iOrderRepository = iOrderRepository;
    }

    @Post
    public Order post(Order model) {
        var result =iOrderRepository.create(model);
        return result;
    }
}

The data is not persisted when I stop the application and rerun it again, an empty map is loaded, it is not persisting the old data. A sample application https://github.com/anandjaisy/microstream-micronaut-issue

San Jaisy
  • 15,327
  • 34
  • 171
  • 290
  • is this a gradle project? I see you store the data under api/build. Is maybe the restart clearing your build folder? – saw303 Jul 02 '23 at 13:19
  • @saw303 yes it is a gradle project, even putting outside of build folder it is not persistent the data – San Jaisy Jul 03 '23 at 01:53
  • IMHO the Gradle multi module project isn't set up properly. Only the `api` module is using the Micronaut Gradle plugin. All other modules are not preprocessed by Micronaut. That's probably why it work. – saw303 Jul 03 '23 at 05:02
  • Since I think this issue is happening to your Gradle multi module configuration, I was wondering whether you have tried to implement it with a vanilla single module Micronaut application? For such a small application this module layering is a bit over engineered – saw303 Jul 03 '23 at 07:57
  • @saw303 for single module Micronaut application it is working fine, not able to find the exact issue why it is not working for multi-module. – San Jaisy Jul 03 '23 at 08:58

1 Answers1

0

Here are some issues that I found in your example project.

API Module

Controller

Unrelated to your question but I recommend to use @Body in your controller method, in order to tell Micronaut how to map the request payload.

@Post
public Order post(@Body Order model) {
   var result = iOrderRepository.create(model);
   return result;
}

Order record

Convert your Java record to a POJO since Microstream has issues with records (see https://docs.microstream.one/manual/storage/faq/java-features.html)

@Serdeable
public final class Order {
    private final UUID id;
    private final String name;
    private final String description;
    private final String productId;

    public Order(UUID id, String name, String description, String productId) {
        this.id = id;
        this.name = name;
        this.description = description;
        this.productId = productId;
    }

    public UUID getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public String getProductId() {
        return productId;
    }
}

Infrastructure Module

That module is not configured properly. No Micronaut compile-time processors are registered since you are not using the Micronauts Gradle plugin in that module. The OrderRepository is using the StoreParams annotation. This has only an effect when Micronaut preprocesses your code at compile time and generates additional code.

@StoreParams("orders")
protected Order createOrder(Map<UUID, Order> orders, Order order) {
        orders.put(order.id(), order);
        return order;
}

Therefore you need to extend the build.gradle by registering the Micronaut io.micronaut.library plugin.

plugins {
    id("io.micronaut.library") version "3.7.10"
}

// ... other code omitted

micronaut {
    runtime("netty")
    testRuntime("junit5")
    processing {
        incremental(true)
        annotations("fete.bird.*")
    }
}

Configuration

In your application.yml you are defining the storage order but in the repository implementation you are referring to orders.

microstream:
  rest:
    enabled: true
  storage:
    order: # call this orders
      root-class: 'fete.bird.entity.RootContainer'
      storage-directory: 'api/build/order-storage'
@Override
@StoreParams("orders")
public Order create(Order order) {
  rootProvider.root().getOrders().put(order.id(), order);
  return order;
}
saw303
  • 8,051
  • 7
  • 50
  • 90