Expression rule with same rule inputs should produce different results

I have the following situation:

- search text field for entering the client's ID

- ADD button that does the search and adds the client to the grid

- pretty complex UI which has this part regarding ADD button:

a!buttonArrayLayout(
                      buttons: {
                        a!buttonWidget(
                          label: "Add",
                          saveInto: {
                            a!save(local!addbButtonSwitch, not(local!addbButtonSwitch)),
                            a!localVariables(
                                local!client: a!refreshVariable(
                                  value: rule!APP_getclient(
                                  clientGroup: fv!item.id,
                                  clientCheckCdt: ri!clientCheck_cdt,
                                  clientRequestCdt: ri!request_cdt,
                                  searchString: trim(
                                    local!searchId[fv!index]
                                  ),
                                  global: not(
                                    fv!item.local
                                  ),
                                  isValid: local!isValid
                                ),
                                refreshOnVarChange: local!addbButtonSwitch
                                ),

Action order is as follows.

- client with some ID does not exist inside some remote database

- user searches for this client's ID via mentioned UI

- user receives the message NOT FOUND inside the text field (message replaces the ID that was used for search within local variable local!searchId)

- user adds client's data to the remote database without navigating away from the current UI (opens new tab and adds client via some third party application)

- user enters the same ID and clicks ADD again

- user should successfully add the client to the grid since it exists inside the remote database

However, this doesn't happen.

Since there are multiple grids on screen ("client buckets"), attempt to add the same client to any other bucket is successful. Attempt to search for another client, adding it to the grid and then searching for the first client again is also successful.

But, attempt to add the first client to the grid where it was searched for before it was added to the remote database results always with the message NOT FOUND.

It seems that this local variable local!client is never refreshed if rule inputs for rule rule!APP_getclient are unchanged.

I've tried to add some "switch" variable (local!addbButtonSwitch) that will cause the local!client to be refreshed upon each click on ADD button but it seems that result stays the same - empty result set since that client didn't exist upon first search attempt.

Is there any way to force the expression rule rule!APP_getclient to return new result set even though rule inputs are unchanged?

Just to mention, I do not have an option to change rule inputs or paradigm that uses array of search IDs or anything like that. This is the legacy code and cannot sustain major refactoring at this point. Maybe I can modify expression rule itself or the way it is referenced inside this a!localVariables block?

  Discussion posts and replies are publicly visible

Parents Reply Children
  • It is built with with() and contains local variables. One of the local variables calls another expression rule which then fetches client from the remote database (query entity). Should I try with a!localvariables and refreshAlways instead of with? Are there any benefits?

  • 0
    Certified Lead Developer
    in reply to ivanm0004

    with()/load() is the old way, a!localVariables is the new way. Variables inside with() are reevaluated on each interaction. There is no real benefit in refactoring this. But you have to make sure that the whole chain of calls and local variables uses with() or a!localVariables with refreshAlways.

    Do you have any chance to find out whether this is a DB caching issue?

  • Thank you for the clarifications. I intended to "modernize" this expression rule and replace with(). I've made some tests and it seems that rule itself (when it is invoked from EDIT rule screen) works fine and doesn't have problems with caching. 

    I've tried to:

    - define rule inputs to mimic the case from the interface,

    - then run the search for non existing client,

    - then add the client into remote database

    - finally run search again without leaving or refreshing the EDIT screen.

    Everything worked fine.

    It seems that it has some issues only when this rule is invoked from the user interface.

    If it helps you understand better this is the more detailed logic:

    - in user interface local variable local!client is refreshed on each click of ADD button (as shown in the code snippet)

    - client's data are fetched via expression rule rule!APP_getclient

    - rule!APP_getclient has multiple local variables within with() that help produce the final output

    - one of those local variables invokes another expression rule which decides which of 2 available integrations is called to retrieve client

    - these integration retrieve the data from remote database

    As far as i can see, I have forced the refresh on both key points.

    1) a!localVariables on user interface

    2) with() inside the expression rule

    Could it be something with the fact that mentioned user interface is a "monster" with multiple nested a!localVariables() and FOR loops?

    There are 2 more a!localVariables above the one from the snippet (lets say "parent a!localVariables()").

  • +1
    Certified Lead Developer
    in reply to ivanm0004

    That is a quite complex scenario. My approach would be to drill down and add debugging information along the way. There is a plugin "Log a Message" which allows you to write to the tomcat-std-out log.

    This way you should be able to find out what is going on behind the scenes.

  • Could it be something with the fact that mentioned user interface is a "monster"

    You're correct in that this is often a recipe for trouble and confusion.  I bend over backwards to make sure my forms don't pass a certain complexity threshold, because debugging and future maintenance quickly becomes a nightmare.

  • Unfortunately, in this case I had no option to think about best practices since i wasn't the designer. I am just a "lucky winner" who received this legacy :)  Maybe sometimes in the future someone will have enough time to rewrite it and "calm down the monster". I believe Stefan's and yours responses will be another PRO argument why to do this.

  • I'll add a +1 for taking the time to simplify the logic whenever possible.  Every "Monster" project I've inherited, it has been quicker to rebuild and support lighter code later than to support a massive form's spaghetti code in production..

  • I've been there - i've dealt with a lot of "legacy" issues like this too.