San Jaisy
San Jaisy

Reputation: 17048

Microstream data is not persisted when application restart using micronaut 3.9.4

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

Upvotes: 0

Views: 122

Answers (1)

saw303
saw303

Reputation: 9072

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;
}

Upvotes: 0

Related Questions