Filter won't work on embedded frame

Some time ago I posted about a problem I had with filters. Filters wouldn’t work on embedded frames
(Filter search doesn't work on embedded frames). The bug was added on youtrack and it had been solved.

Now I have a similar problem. Filters won’t work when i add a frame in an editor. This frame has a simple table. I attached a sample project to prove it.

filtersBug.rar (149.6 KB)

Instructions to reproduce bug:

Open Cars tab from Application menu. Create a car object using create button. Double-click on the new created car to open edit car screen. Now you should see a table containing your car. Add any filter condition and press search. Nothing happens unfortunately!

I tried to add the frame from xml, not dynamically, and still doesn’t work…

2 Likes

It will work if you set an id to the frame. For example, in your code opening the frame programmatically:

    @Override
    public void init(Map<String, Object> params) {
        super.init(params);

        CarsTableFrame frame = (CarsTableFrame)
                openFrame(null, "cars-table-frame");

        frame.setId("carsFrame");
        frame.ready();

        carsGroupBox.add(frame);
    }

1 Like

Actually if the frame is declared in screens.xml or web-screens.xml it already has an Id, so no need to assign one in the init() method of the embedding Frame/Window.

However, and this is still the case in 6.9, if you put a ‘$’ (dollar) or a ‘.’ (dot) in the frame id filter will not work when embedded.

With a dot you will get: IllegalStateException: Illegal parameter info 'component$'

With a $ you will get something like: IllegalStateException: Illegal parameter info 'component$OrderDetail$browse.filter.date24791'

Both issues comes from the ParametersHelper pattern matching that does not tolerate that.

This can be confusing, because we are fostered to name our frames like CUBA does, for instance in my case today an embedded frame with a filter named 'app$OrderDetail.browse' for which I stumbled upon the issue. Make it a Window and it works.

I think the root issue might be elsewhere, in ConditionDescriptorsTreeBuilderAPI.getFilterComponentName() (code below). In this method, when the filter name is embedded in a frame it will be prefixed by its frame id. If the filter is embedded in a window, it won’t.

This is due to how ComponentsHelper.getFilterComponentPath() works, it stops when stumbling upon a Window.

Not sure why there are two semantics here, because filter name for a filter conditions tree is always computed for the frame/window the filter belongs, there is no need to prefix. Especially when this prefix (the frame Id) is subject to limitations it would not have with a window.

Take any generated CUBA screen with a filter named “filter”, and the filter component name wil be “filter”, why not keeping the same for an embedded frame.

  protected String getFilterComponentName() {
        String filterComponentName = ComponentsHelper.getFilterComponentPath(filter);
        String[] parts = ValuePathHelper.parse(filterComponentName);
        if (parts.length > 1) {
            filterComponentName = ValuePathHelper.format(Arrays.copyOfRange(parts, 1, parts.length));
        }
        return filterComponentName;
    }`

Attached a project allowing to reproduce easily the case.

testcuba5.zip (82.3 KB)

Thank you for the investigation and test project.
In order to prioritize the issue, could you explain why you need the filter id in the screen equal to its id in screens.xml?

I do not specifically need that in my project.

It’s just that as I said, we are incited to name our screens/frames like CUBA using dollar and dot in the id for the sake or homogeneity, so this is what I do since I use the platform.

I’m working on a custom component that fiddles a bit with filter internals, so when I encountered the issue I first suspected my code.

One should just be aware of the fact that there is this particular case of a frame embedding a filter, you cannot use a dollar or a dot in the frame id.

Once you know, it’s no big deal.

OK, I see.
We are planning major changes in how the filters are handled by the framework. So this problem should go away naturally.

Great. If at this occasion you could take the opportunity to split the filter logic between GUI & service/global layer that would be great.

Filter component of CUBA is very powerful, and currently you cannot use it at service or global level which is sad.

For instance in our case we compute aggregates over different axes (customer, product family, product, provider, expenditure items, etc.) and some of them will be computed and persisted in real-time.

E.g, new order causes recalculation of aggregates for the given customer, product families & product […] and corresponding Totals.

We don’t want to recompute all axes on each modification because we have up to 5 years of data in line for our clients (regulatory + business statistics), which makes quite some.

As a corrollary, lots of our queries for day-to-day operations are filtered on “current year” by default.

All of that would be greatly simplified by a framework allowing quickly filtering a base query, exactly what CUBA Filter does.

QueryFilter does precisely that at global level, but API is not very convenient currently. Plus some items are defined at GUI level like PredefinedDateInterval so the criteria “current year” can not be used in aggregation services.

Just an idea.

Regards,
Michael

Right, QueryFilter wasn’t meant to be a public API, it’s rather an implementation thing now. And we are going to move the filter handling logic down to service/datastore layer and decouple it from JPQL to allow for using with non-ORM-based data stores.

That’s great news @knstvk. I guess this will be for CUBA 7.0, can’t wait for the baby to born.