We have an XHTML page and were noticing a big performance drop during AJAX postback request in some configurations. It only seemed to happen when one ore more input fields were invalid. After some research, I found that the issue lies with Beans.isProxy, which is called many times during bean validation. It takes a few milliseconds each time, which adds up.
Cause
During bean validation, the call chain looks like this:
In other words, Beans.isProxy is called for once for each violation and for each Faces component. In our case, we had about 6 violations and around 20 components, so Beans.isProxy was called about 100 times. Beans.isProxy uses Class.forName to load various CDI proxy classes, up to 8 times for 4 classes.
On my local machine, each Beans.isProxy took about 10-20 ms, resulting in 100 * 10/20 ms = 1-2 seconds of delay for each bean validation cycle. On a somewhat slower test environment machine, we observed performance drops up to 5-6 seconds.
Possible solution
The solution might be simple, fortunately. Is it really necessary to try and load the classes each time Beans.isProxy is called? For testing purposes I made a fork where I try to load the classes only once:
blutorange@12aa9d1
That change solves our performance issue completely. With the change from that fork, the overhead from the entire bean validation becomes insignificant compared to other parts of the Faces lifecycle.
Note
I only tested with the latest 3.x OmniFaces version. But since the relevant code is the same in version 4.x, the issue should occur in 4.x as well. If you fix this, it would be great if you could release a new 3.x version. But if not, that's also fine, we will hopefully be able to update to Jakarta soon and can use a local fork in the mean time.

We have an XHTML page and were noticing a big performance drop during AJAX postback request in some configurations. It only seemed to happen when one ore more input fields were invalid. After some research, I found that the issue lies with Beans.isProxy, which is called many times during bean validation. It takes a few milliseconds each time, which adds up.
Cause
During bean validation, the call chain looks like this:
showMessageForis set to@violating, it calls the method invalidateInputsByPropertyPathAndShowMessages, which searches for matching input fields via forEachInputWithMatchingBase.ExpressionInspector.getValueReferencecalls Beans.unwrapIfNecessary, which then calls Bean.isProxyIn other words,
Beans.isProxyis called for once for each violation and for each Faces component. In our case, we had about 6 violations and around 20 components, soBeans.isProxywas called about 100 times.Beans.isProxyuses Class.forName to load various CDI proxy classes, up to 8 times for 4 classes.On my local machine, each
Beans.isProxytook about 10-20 ms, resulting in 100 * 10/20 ms = 1-2 seconds of delay for each bean validation cycle. On a somewhat slower test environment machine, we observed performance drops up to 5-6 seconds.Possible solution
The solution might be simple, fortunately. Is it really necessary to try and load the classes each time
Beans.isProxyis called? For testing purposes I made a fork where I try to load the classes only once:blutorange@12aa9d1
That change solves our performance issue completely. With the change from that fork, the overhead from the entire bean validation becomes insignificant compared to other parts of the Faces lifecycle.
Note
I only tested with the latest 3.x OmniFaces version. But since the relevant code is the same in version 4.x, the issue should occur in 4.x as well. If you fix this, it would be great if you could release a new 3.x version. But if not, that's also fine, we will hopefully be able to update to Jakarta soon and can use a local fork in the mean time.