I have the following situation in Jmix (framework version 1.3.1, studio version 1.3.0.213):
I am using two datastores (one main, one additional). I have an entity “Task” which is from the main datastore, and an entity “Project” which is from the additional datastore. There is a relationship between them (a Project can have one or more Tasks). That is, on the Task entity there is this:
@SystemLevel
@Column(name = "PROJ_ID")
private Long proj_id;
@Transient
@JmixProperty
@DependsOnProperties({"proj_id"})
private Project project;
I am trying to build a Task browser (StandardLookup) with a propertyFilter on a field that is a property of Project; that is, something like this:
<propertyFilter property="project.some_field" operation="CONTAINS" caption="..." dataLoader="tasksDl" align="BOTTOM_RIGHT" autoApply="true" />
The problem is that no approach I try works.
If I just do this:
<loader dynamicAttributes="true" id="tasksDl">
<query>
<![CDATA[select e from dsk_Task e]]>
</query>
</loader>
then I get an error message “The state field path ‘e.project.some_field’ cannot be resolved to a valid type.”
This seems to be because this query simply doesn’t load the “project” reference into the tasks it loads.
If I change it to this:
<loader dynamicAttributes="true" id="tasksDl">
<query>
<![CDATA[select e from dsk_Task e, dsk_Project p where e.proj_id = p.id]]>
</query>
</loader>
then the error message is different:
[26, 37] The abstract schema type ‘dsk_Project’ is unknown.
[58, 62] The state field path ‘p.id’ cannot be resolved to a valid type.
This seems to be because queries across datastores are not supported.
I also tried leaving the loader element empty and doing something like this in the controller:
@Install(to = "tasksDl", target = Target.DATA_LOADER)
private List<Task> tasksDlLoadDelegate(LoadContext<Task> loadContext) {
List<Task> tasks = dataManager.load(Task.class).query(
"select e from dsk_Task e"
)
.condition(loadContext.getQuery().getCondition())
.list();
for(Task task: tasks) {
Optional<Project> project = dataManager.load(Project.class).query("select p from dsk_Project p where p.id = :id")
.parameter("id", task.getProj_id())
.optional();
if (project.isPresent()) {
task.setProject(project.get());
task.setProj_id(project.get().getId());
}
}
return tasks;
}
This again gives me the “cannot be resolved to a valid type” error above. This makes some sense: At the time the condition is applied (line starting with .condition) the project has not been loaded into the tasks yet, so there is nothing to filter. If I leave out the line starting with .condition, then I get no error, but no filter is applied either; also logical because there is no line that would apply the filter.
I would need to find a way to apply the condition I get from loadContext.getQuery().getCondition(), but only after the loop over the tasks has run, but cannot figure out how to do that.