In my experience, it has been a horrible technology (even when combined with PrimeFaces) for complex functionality.
When you have a page that has a bunch of tabs, which have tables with custom action buttons, row editing, row expansion, as well as composite components, modal dialogs with other tables inside of those, various dropdowns or autocomplete components and so on, it will break in new ways all the time.
Sometimes the wrong row will be selected, even if you give every element a unique ID, sometimes updating a single table row after AJAX will be nigh impossible, other times the back end methods will be called with the wrong parameters, sometimes your composite components will act in weird ways (such as using the button to close a modal dialog doing nothing).
When used on something simple, it's an okay choice, but enterprise codebases that have been developed for years (not even a decade) across multiple versions will rot faster than just having a RESTful API and some separate SPA (that can be thrown out and rewritten altogether, if need be).
Another option in the space is Vaadin which feels okay, but has its own problems: https://vaadin.com/
Of course, my experiences are subjective and my own.