Search code examples
javablaze-persistence

Entity view with a collection inside not working with Blaze persistance


I have a problem with entity views using blaze persistence library. I want to retrieve a list of Suppliers, each one with a list of Products but I'm getting an exception while creating Entity views model.

Setup

  • Blaze persistence core 1.6.6
  • Blaze persistence Entity View 1.6.6
  • Spring Data JPA 2.5.6
  • Hibernate 5.4.27

I'm using Blaze base configuration shown here.

Model

This is my model (I have removed some fields to be more clear):

@Entity(name = "suppliers")
public class Supplier extends BaseEntity {
    @Column(nullable = false, length = 100)
    private String businessName;

    @OneToMany(mappedBy = "supplier")
    private List<Product> products;
}

@Entity(name = "products")
public class Product extends BaseEntity {
    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private Integer price;

    @ManyToOne
    private Supplier supplier;
}

Entity views

@EntityView(Supplier.class)
public interface SupplierWithProductsView {
    Integer getId();
    String getBusinessName();

    List<ProductView> getProducts();
}

@EntityView(Product.class)
public interface ProductView {
    Integer getId();
    String getName();
    Integer getPrice();
}

Exceptions

The exception I get at startup is the following:

Caused by: java.lang.IllegalArgumentException: Illegal occurence of [products] in path chain resolver!
    at com.blazebit.persistence.parser.PathTargetResolvingExpressionVisitor.invalid(PathTargetResolvingExpressionVisitor.java:562) ~[blaze-persistence-core-parser-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.parser.PathTargetResolvingExpressionVisitor.visit(PathTargetResolvingExpressionVisitor.java:468) ~[blaze-persistence-core-parser-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.parser.expression.EntityLiteral.accept(EntityLiteral.java:50) ~[blaze-persistence-core-parser-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.MetamodelUtils.isIndexedList(MetamodelUtils.java:125) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.MetamodelUtils.isIndexedList(MetamodelUtils.java:120) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.AttributeMapping.determineIndexed(AttributeMapping.java:333) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.attribute.AbstractMethodListAttribute.<init>(AbstractMethodListAttribute.java:61) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodListAttribute.<init>(MappingMethodListAttribute.java:35) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.MethodAttributeMapping.getMethodAttribute(MethodAttributeMapping.java:757) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImpl.<init>(ManagedViewTypeImpl.java:319) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.FlatViewTypeImpl.<init>(FlatViewTypeImpl.java:41) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.ViewMappingImpl.getManagedViewType(ViewMappingImpl.java:892) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.MetamodelBuildingContextImpl.getManagedViewType(MetamodelBuildingContextImpl.java:234) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.metamodel.ViewMetamodelImpl.<init>(ViewMetamodelImpl.java:88) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.EntityViewManagerImpl.<init>(EntityViewManagerImpl.java:271) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    ... 60 common frames omitted

I tried to take some tests by debugging and investigating in the library code and I found that if I add @MappingIndex to the products list in the view, the exception thrown seems more clear. I haven't fully understood how the mapping index works but maybe it is correlated. The following is the new exception:

Caused by: java.lang.IllegalArgumentException: There are error(s) in entity views!
The resolved possible types [java.util.List] are not assignable to the given expression type 'java.util.Collection<my.package.Product>' of the mapping expression declared by the attribute products[my.package.SupplierWithProductsView.getProducts]!
    at com.blazebit.persistence.view.impl.EntityViewManagerImpl.<init>(EntityViewManagerImpl.java:285) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at com.blazebit.persistence.view.impl.EntityViewConfigurationImpl.createEntityViewManager(EntityViewConfigurationImpl.java:206) ~[blaze-persistence-entity-view-impl-1.6.6.jar:1.6.6]
    at my.package.configurations.BlazePersistenceConfig.createEntityViewManager(BlazePersistenceConfig.java:44) ~[main/:na]

... other lines omitted

Anyone has any idea how to solve my problem?

Thanks in advance!


Solution

  • I tested your sample app now and I saw this exception:

    Caused by: java.lang.IllegalArgumentException: Illegal occurence of [products] in path chain resolver!
        at com.blazebit.persistence.parser.PathTargetResolvingExpressionVisitor.invalid(PathTargetResolvingExpressionVisitor.java:562)
        at com.blazebit.persistence.parser.PathTargetResolvingExpressionVisitor.visit(PathTargetResolvingExpressionVisitor.java:468)
        at com.blazebit.persistence.parser.expression.EntityLiteral.accept(EntityLiteral.java:50)
        at com.blazebit.persistence.view.impl.metamodel.MetamodelUtils.isIndexedList(MetamodelUtils.java:125)
        at com.blazebit.persistence.view.impl.metamodel.MetamodelUtils.isIndexedList(MetamodelUtils.java:120)
        at com.blazebit.persistence.view.impl.metamodel.AttributeMapping.determineIndexed(AttributeMapping.java:333)
        at com.blazebit.persistence.view.impl.metamodel.attribute.AbstractMethodListAttribute.<init>(AbstractMethodListAttribute.java:61)
        at com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodListAttribute.<init>(MappingMethodListAttribute.java:35)
        at com.blazebit.persistence.view.impl.metamodel.MethodAttributeMapping.getMethodAttribute(MethodAttributeMapping.java:757)
        at com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImpl.<init>(ManagedViewTypeImpl.java:319)
        at com.blazebit.persistence.view.impl.metamodel.FlatViewTypeImpl.<init>(FlatViewTypeImpl.java:41)
        at com.blazebit.persistence.view.impl.metamodel.ViewMappingImpl.getManagedViewType(ViewMappingImpl.java:892)
        at com.blazebit.persistence.view.impl.metamodel.MetamodelBuildingContextImpl.getManagedViewType(MetamodelBuildingContextImpl.java:234)
        at com.blazebit.persistence.view.impl.metamodel.ViewMetamodelImpl.<init>(ViewMetamodelImpl.java:88)
        at com.blazebit.persistence.view.impl.EntityViewManagerImpl.<init>(EntityViewManagerImpl.java:271)
    

    The error means that the expression products, which is created behind the scenes for SupplierWithProductsView#getProducts, is illegal. This is an unfortunate side effect of the association being named the same as the entity ProductEntity i.e. @Entity(name = "products"). I created the following bug report for this and will look into this as soon as possible: https://github.com/Blazebit/blaze-persistence/issues/1450

    In the meantime, you could rename the association to e.g. productList, seelingProducts or something like that. Alternatively, you could also rename the entity by using @Entity(name = "product") i.e. omitting the s.