Are Epicor Widgets Broken? šŸ¤

I appreciate the conversation!

  1. It occurs only when a smart client proxy is used (probably web-ui was updated to support this mode too). Calls via REST, Service Renderer, naked service-methods do not have such ā€˜magicā€™
  2. This behavior has no relation to PRE (or any other BPM-specific things). It is just about client-to-server call convention.
  3. Also, ā€˜Epicorā€™ sends not only the updated tables but all parent rows for modified rows.
  4. All above is true only for tableset parameters with ref modifier. In the case of ā€˜normalā€™ parameters, even client proxies send whole tablesets.

I understand that, I am not complaining that Epicor does it that way. I love it that way. I was pointing out that when you use a Widget in a POST and you invoke the same Update method you get different outcomes which dont align with Epicorā€™s usual way, when the Facade is called, you get different behaviour than what Epicor usually would do from Smart client; not to rely on that.

For example Iā€™ve seen folks do if (ttOrderDtl.Any()) { ... } when a ipTableName isnā€™t present they check if the ds has that table to indicate its probably a OrderDtl update. That is what the Epicor trace showed them. But little did they know is that calling Update from a POST or Service Connect would mess up their PRE since it would send ttOrderDtl, ttOrderRel, ttOrderWhatever - just be cautious id say.

In addition since it doesnt include a BeforeImage when your facade fires the following would for example not work:

image

The saying Just do a trace and you will know what Epicor does and repeat it isnā€™t necessarily accurate if one thinks the behavior will be the exact same, atleast when using built-in widgets vs Custom Code.

It is a bad idea to bypass facades. In general, this parameter is for infrastructure only. If you call Updated from Update, you just need to make your code self-protected.

What other fields besides callContextBpmData can one use, they are as dangerous once you start using them they can be overwritten by other BPMs.

Also if you have 10 PRE BPMs you would need to add a gatekeeper to all of them, instead of ignoring the facade.

  1. Just in case, loops are not supported officially. And validation explicitly says about that.
  2. They are not blocked, since they work in general. But you have to clearly understand how Epicor logic works to implement complex cases.

Something as simple as Loop through all OrderDtl and Update a OrderRel column with a datestamp isnā€™t a complex case.

I know they are not supported officially; is there a reason the BPM Customization tools have been stale for a while now. If I took a poll how many people have used a foreach loop in their BPMs im sure 90% would say they have.

Could you please point me to the exact place in the guide? Changed == Add|Updated|Deleted since E9 (AFAIR).

Since Changed is actually !Unchanged when the code is generated, based on that Guide we all started off with when coming off E9 to E10 - it was taken was !Unchanged() is Added or Updated.

Here is an actual BPM that I have currently have in Production that would exception on Delete:


The fix is to have a condition before that to check for Added or Updated or maybe add an option so we can select Added || Updated in the dropdown :slight_smile:
image

Direct modification of RowMod column is dangerous. The whole Epicor business logic relies on it.
Most likely, Set Field widget restricts access to it, since the widget came from the time when only parameter ā€œtablesā€ were supported. And RowMod in such tables should not be changed ever.

Also, if you need this functionality in Set Field, did you create a feature request?

An example where you always have to set RowMod to U is pretty much on many OnChangeSomething methods. Maybe its time to support RowMod U so folks can use Business Logic and not always go to UpdateExt

Many of the OnChangeSomething check for !string.IsNullOrEmpty(Row.RowMod) you must be able to set it, dangerous or not.

  1. we never promised that we will support never version of C# in BPM/EFx.
  2. you can treat it as Epicor dialect of C#.

Are there any plans to support some newer C#? Yeah you never promised it I am not saying you did; but why do we have to be so far behind. Maybe something like a FeatureFlag to set CompilerServices language version, wouldnā€™t be bad.

2 Likes

Without even a stop-watch can we assume that this:

Is not faster than:
image

Now imagine doing the UpdateTableByQuery 10x :slight_smile:

Is it slow by minutes? Noā€¦ maybe 100ms maybe 1500ms.

3 Likes

You are correct. I was wrong. Not sure if I recalled this from the past using Custom Code after a Condition.

For sure trying to access Unchanged row in Custom Code after a condition wonā€™t workā€¦ but you do that rarely anyways. Condition after Custom Code or a Chained Condition works fine.


1 Like

:point_up: So, I know the hypocrisy that I am about to engage in as I go on to defend us low-coders, but I think thatā€™s the idea, is that it should be as LOW code as possible, and preferably all widget-able.

I agree with this in a non-object-oriented language. I can do a VBA macro for Excel pretty easily and there is a ton of info out there for it.

But wow, do I disagree when it comes to BPMs.

Look, there is simply no manual that exists that explains how Epicor business objects tie into C# programming.

Those of you with insane programming backgrounds, I think you just canā€™t see the colossal leap that it takes to go from ā€œI want to do thisā€ to ā€œDid you use the right adapter?ā€

What on earth is an adapter?! Where is that in the trace logs?

Like, the barrier to entry from ā€œI see this happening in the UIā€ to ā€œthis is the code you needā€ is so steep! It is not a 20-hour cram sesh to become an expert. I do agree with that philosophy on a lot of things; I have done that repeatedly over the years. But BPM coding is not one of those 20-hour things; it is a like a college major or at least a minor.

Widgets are really wonderful. I have done so much with them over the last year. And I also totally agree with @hkeric.wci 's criticisms (the ones I understood).

But abandoning widgets because itā€™s ā€œsimpleā€ to learn how to code BPMs, that is not the answer.

3 Likes

There kind of is oneā€¦ If you look at the code that gets generated when you use widgets, it is a great way to learn. Haso was just posting about this in another thread.

Here is one that scares me the mostā€¦ Many people who use widgets join ttTable to RealTable little do they know is that it brings the entire RealTable into memory.

Its just natural to use the Compose Query that way

2 Likes

Youā€™re quite right about that. But this is an Epicor thing, not a coding thing. Epicorā€™s documentation is basically non-existent compared to what developers are used to on other platforms. Working with Epicor gives me flashbacks to the early '90s. But despite this, if you already live and breathe C#, widgets feel even more restrictive than coding blind.

1 Like

Oohā€¦ not a fan alreadyā€¦ I mean, the widget version of this was not hardā€¦

But, I did not know (or really, did not appreciate) this ability till you mentioned it.

1 Like

Oi! Iā€™m right here, you know!

Just kidding, youā€™re right to some extent - in my case though it was 20 hours to figure out oTrans (ui) use, another 20 for ServiceRenderer(BPM) , and 20 for CallService(efx). Probably another 20 for each building block in Epicor, and as far as I can tell there are 32 building blocks. So about 600 hours of actual development (not just ā€œworkā€) and Bobā€™s your proverbial uncle.

The thing is, I went well over 20 on widgets and got frustrated with the lack of visibility of what was going wrong, and decided Iā€™d do better learning C# but that was at the very beginning.

Thanks @SAD and @hkeric.wci and everyone else for livening up this thread, very informative. Sounds like Epicor better keep both and improve both systemsā€¦

3 Likes

BPM/EFx are server-side stuff. It behaves as other server-side stuff works. In general, it behaves as the code of services. So the usual way here is different from the client-side way.

Again, trace shows client-to-server behavior. BPM works inside server and behaves like other server-side stuff.

What BeforeImage means? I do not know what it is :frowning:

Some UD fields for example.

Just in caseā€¦ Most likely, the ability to bypass facades will be removed in the future.

I agree that BPM and EFx need for-each functionality.

You make two mistakes simultaneously :wink:

  1. The article is about extension method added to ICE by me ;). There are 4 method, Add(), Updated(), Deleted() and Unchanged(). So Unchanged() means !Added() && !Updated() && !Deleted(). And therefore !Unchanged() == Added() || Updated() || Deleted().

  2. UI options are inherited from E9. And they have the original means. Actually, there is no relation between UI options and these extension methods.

As for me, the actual fix would be to switch to checkboxes :wink:
But I think that such changes have no chance to be implemented in windows client :frowning:

  1. Maybe, but without official requests, it is least likely possible.
  2. Do you realize that Update methods do not support multiple modified rows in most cases? (in contrast with UpdateExt).

Only after moving the editing logic from client to server. This transition is very complex and expensive.

2 Likes

Improper comparison :). You create a complex query with multiple fields. It is not needed for updating a single field.

But, in general, I wanted to add Udpate Table widget similar to Update Table by Query, but without source query. But again, there were no feature requests for that.
And now, most likely, no one approves such functionality for the existing UI.

1 Like

BeforeImage is when you are in a POST and you do GetByID and you make a change, before you call Update or UpdateMaster and sometimes other Methodsā€¦ you need to create a copy of the row, basically your own RowMod ā€œā€ blank and then you make changes to second copy of the row RowMod ā€œUā€.

image

If you donā€™t certain methods will fail, they kind of require both. Epicor uses this technique throughout all of their BPMs. Example from SDK


Its not always update that only requires it others too.

1 Like

Do you not get to think for the users anymore :frowning: you know those ā€œour Customers would benefit from xā€. Is it required now that you always have a request first?

Right, and thatā€™s not a trivial distinction. I mean, a tech ref guide to BPM custom coding would be great, but I donā€™t see it ever happening, so itā€™s widgets, baby!

Exactly.

If.

Definitely, Iā€™m correct :slight_smile: I had to add this bloody stuff to the BPM on the late E10.0 development stage just because it works this way in E9 and this requirement was missed.
Actually, you need to remember that filtering is not applied to the directive variables. And completely disabled in EFx.

It is by design. By E9 design. Actually for directives where ā€œwith ruleā€ setting is available (Standard DD and MD on services with multiple dirty row support) you can change rule from ā€œmatchingā€ to ā€œexistingā€ (sorry, donā€™t remember the exact name).

1 Like

The thing is, there are like 50 people in the world who are wizards with Epicor widgets, and 50 million C# developers. For the company looking to hire someone to set up Epicor, the choice is clearā€¦ if they have a choice at all.

Iā€™m a professional developer (solution designer, architect) more than 30 years already.
And. definitely, code is a more native approach for me.
But widgets have a great benefit over the custom code blocks. They are upgrade-friendly. And it is a great benefit for the product customizations. Custom code is either hard to or even impossible to upgrade.

4 Likes

Just do not forget, that code generated now can be completely different from the code that BPM/EFx will generate in the next release.

1 Like

I do like widgets or coding in blocks, it also lets me visualize the BPM Flow better. I do appreciate your time SAD. I am not bashing widgets; actually I want to use them. But I feel like I canā€™t without cluttering my flow with ā€œhacksā€. :slight_smile:

Iā€™ve done plenty of:
image

I do prefer this more:
image

I want to get to this:

But I always end up with pockets of Custom Code :stuck_out_tongue:

1 Like

Thank you! Never heard about this recommendation. I never saw directives with such code. More precisely, no one sent such directives to me for review.

Just in case, modern versions (probably starting 10.2.700 or 2021.1) support BufferCopy-like stuff to clone the whole tableset.

Also, one of the things that I would like to see in BPM/EFx is clone widgets. But again - no requests mean no features :(.

1 Like