Skip to content

@RemoteService methods returning replaced entities fail with MetaClass not found on the client #5574

Description

@glebfox

Environment

Jmix version: 2.8.2
Jmix Studio Plugin Version: 3.1.SNAPSHOT8066-262
IntelliJ version: IntelliJ IDEA 2026.2.1 RC

Bug Description

When a backend entity is replaced via @ReplaceEntity (so its runtime metaclass name differs from the original, e.g. Product → ReplacedProduct), a REST DataStore client cannot consume the result of a @RemoteService method that returns that entity. The client only knows the original DTO name (Product) and throws:

java.lang.IllegalArgumentException: MetaClass not found for ReplacedProduct

Regular CRUD data loading via REST DataStore works fine — only custom remote service calls that return entities (or collections of entities) are affected.

Steps To Reproduce

See demo project.

  1. In the products backend, replace Product with an extension that has a different metaclass name:
@JmixEntity
@Entity
@ReplaceEntity(Product.class)
public class ReplacedProduct extends Product {
}

(add a DTYPE discriminator column to the PRODUCT table via Liquibase so single-table inheritance starts up).

2.Add a @RestMethod to the products InventoryService that returns entities:

@RestMethod
public List<Product> getMostExpensiveProducts() {
    return dataManager.load(Product.class).all().maxResults(3).list();
}

3.Declare the same method in the orders @RemoteService interface and call it from the UI.
The products REST endpoint returns items with "_entityName": "ReplacedProduct". On the client, invoking the remote service throws MetaClass not found for ReplacedProduct.

Current Behavior

The client fails while resolving the metaclass by the entity name taken from the response.

Expected Behavior

The client should deserialize the remote service result into the locally declared entity type (Product), the same way RestDataStore load operations already do. The replacement on the backend should be transparent to the client.

Sample Project

jmix-integrated-apps-sample-repro-2026-08-06.zip

WA:
As a temporary workaround, an application can register the replaced entity name on the client (e.g. mapping remote → local metaclasses) so metadata.getClass(entityName) resolves. A built-in solution is preferable, since the replacement module on the backend may be optional/toggleable and the client should not have to know about backend-only entity names.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions