CUBA filters - the fast food of business software?

Last time, i wrote about the generic filter possibilities that CUBA provides out of the box. I left off with two requirements as a developer, that are necessary to be confident that the generic solution does not fall down with real world problems.

Going from fast food to a real healthy meal

After going through the filter possibilities the first time, it felt a little strange to me. This first thing i thought, was something like “ok, so WTF did i spent my time on the last few years?”. Because at first glance it seemed too good to be true. Don’t need to write this simple, boring and similar filter mechanisms by yourself anymore?

all orders that are in state X

all products that are in category Y

all orders that have been placed between t 0 and t 1

and t yada yada yada

From a developer point of view this is just boring stuff. As you’ll get the schema behind it, it becomes pointless. Nevertheless, to wrap this generic schema into code that is efficient in terms of SQL statements and slick from UX perspective is actually pretty hard. This is why oftentimes the developer, and most notably myself, does not go from the specific problem to a more general implementation that can then be used instead of developed.

Going back to the solution we have at hand from the last blog post. After the first attempts to do some stuff with the filtering mechanism, i wasn’t aware what to make of it. At this point it feels a little like fast food.

Mostly fast to get, low price, Tasty to eat at the exact moment. But after eating it, you often have a queasy conscience. You probably have a feeling, that it might bite you in the long run.

The question basically is: Is this a healthy well tasting meal?. Meaning: Are you on the right track with this solution, or will this tool fall off after the first non-obvious filter problems?

For this to figure out i will go through the two objections from the last blog post.

1. pre-defined filter combinations on behalf of the user

Many times there is a need for the developer to pre-define filter possibilities. CUBA allows you to tackle this problem on different layers. You can think of it as different categories in terms of intervene through the user as well as the developer. Below you’ll see a diagram that shows this classification.

So let’s look at the different solution layers one by one, starting with pre-defined filters.

1.1 pre-defined generic filters

The first option that CUBA gives the user is, that an ad-hoc filter (like created in the last blog post), can be saved within the application. To do this, the Filter section has a little Config icon on the left, that lets the user choose between different possibilities to save an ad-hoc filter.

Configuration options for saving filters in CUBA

With Save / Save as only the filter conditions (not the given values) will be saved for the current user. Next there is a possibility to save a filter as a Search folder. In this case, the entry will be shown in the side panel of the application. It stores the conditions as well as the input values and can be shared with other users. There is more stuff like Sets, which will let you save the results insted of the filter definition.

I’ve just screached the surface of the different options - more information about the different possibilities can be found here.

1.2 Custom UI with generic filters

The option that i showed above are mostly the same from a UI perspective. Oftentimes the need for a pre-defined filter comes from the wish to let the user be more efficient in filter execution. If you want to give the user this productiviy improvment, a custom filter UI can be created.

When you go through the example app, especially in the administration section of the app, you’ll find different platform screen, where the generic filter solution is replaced with a custom filter UI. Above you see an example of the Entity Log view.

As you probably can imagine, there is no limit in customization of the UI. You can use all available input elements as well as layout possibilities to design the perfect UI.

Alongside with the customization of the UI elements, there comes the burden to handle UI events that execute the filter on your own. This is basically the trade-off you have to make to implement this kind of UI.

1.3 programatically filtered datasources

The third option that you have, is to adjust the underlying datasource of the filter. A datasource is a concept that is responsible for the data provided to UI components. Of course you have programatic access to these datasources. But often is totally ok, to just configure these datasources through the declarative definition in the XML descriptor. An example of this definition you’ll find in the product-browse view in the ordermanagement app:

<dsContext> <collectionDatasource id= "productsDs" class= "com.company.ordermanagement.entity.Product" view= "product-view" > <query> <![CDATA[select e from om$Product e]]> </query> </collectionDatasource> </dsContext>

In the query tag you have the option to change the query string that should be executed. As this is a plain old JPQL Query, there is obviously a lot of freedom. A few examples can be found in the docs.

2. support for complex filters beyond attribute values or related entities

The second objection that i brought up last time is the question about the support for filters that go beyond “simple” attribute based filterings. That might be even more important than the last topic.

So let’s have a look about what CUBA is capable of in this regard. Since it’s a little bit harder to categorize these advanced filter requirements, i’ll go through a few examples, that should give an overview of what is possible out of the box.

Products that have created within the last week

The first example that shows the dynamism of the filter feature is the possibility to add a custom condition. We’ll define this condition with a criteria that uses a JQPL macro.

Lets assume we want to filter for all products, that have created within the last week. We want to track the success of this products through the orders to do a marketing campaign if necessary.

First of all we create a new condition via the UI (Product browser > Add search condition > Create new…). The name can be something like “from last week”.

In the Where condition we’ll use the JPQL macro @between to define that createdTs has to be in the time frame (now-5) and now. {E} is the current entity (in this case Product).

Gimme all the iPhone lovers

The next filter example is based on an 1:N relationship. In this case, we want all the orders, that contain at least one iPhone in it. This is a little more advanced, because the product information are stored in the LineItem entity, not in Order directly.

The object graph displayed as a wonderful train wreck goes like this:

myOrder . getLineItems (). getAt ( 0 ). getProduct (). getName ()

To get this up and running, lets go into the Orders browse view:

You’ll find the orders the example app. The second one, 15/11/2015 from Misty contains a Line Item with an iPhone as the product.

Next, we create another new search condition with the following settings:

In the Join Attribute, we will join the line items relation in the query. Next, in the Where attribute, we tell CUBA that li (the current Line Item) should have a product, which has a name that is like ‘%iPhone%’.

This is basically it. When doing the search (and choose the checkbox above the search button to activate the condition), you’ll get only Misty’s order.

It’s a bit over, is that ok?

A tiny little extension will drastically increase the value of this filter. Instead of pre-defining the search string, you can let the user decide what product names to search for. Changing the Where attribute to the following:

li . product . name like ?

As well as setting the parameter type to “String” instead of “No Parameter” will give you a input field in the filter section. Entering “iPhone” or “8810” will give the the first or the corresponding second order.

Using the parameter feature a little more, we could extend our query to search for all orders that have a product in the category that the user wants to:

All Orders that have a product of a certain category

I could go on with the examples of “advanced” filters a little more, but i’ll think you get the point. I haven’t covered all available possibilites, but it’s up to you to find it out.

The bottom line of this second objection is, that the limit is not at the point you might think of after reading my last blog post. Instead it is broader and includes much more filter use cases.

If you think it’s fast food, than at least it’s a delicious one

If we really want to stick to the fast food analogy (and i want - on that one you can be sure), lets say it like Jules Winnfield in Pulp Fiction did:

Mmm, this is a tasty burger! - Jules Winnfield

It’s not this McDonalds or Burger King kind of fast food. Its not just any fast food restaurant. At least the CUBA filters are a very tasty Burger from Big Kahuna Burger.

First of all, CUBA generic filters are fast (to “develop”). That’s a fact. If you compare it to developing the same feature set from scratch - well, we’ll see us in a year (if you have your five programming buddies around). Even if you plan to implement the concrete filter requirements you have at hand. Compare the effort to using this solution: even in this case it will be more effort.

Second, CUBA generic filters are cheap. Since software developers paychecks are the driving cost factors in most IT efforts, you should probably optimize for it. I will not start the make or buy discussion right here, but i think the price/performance ratio is pretty unique. Perhaps i’ll cover this topic in a future blog post.

Last but not least, CUBA generic filters are healthier than there reputation (or the one that i painted above). I hope i could point out, that unlike our burger example here, the filter mechanism is not just for the run-of-the-mill case. Instead it can handle filter requirements that are way beyond what anyone could call “easy”.