Here’s a step-by-step walkthrough of how we achieved it.
- The client had multiple custom modules (entities) inside Liferay.
- They needed granular control over what different roles could do with each entity.
- Permissions needed to be manageable from Liferay's Control Panel without custom UIs.
Step 1: Add a default.xml
in the Service Module
In the Service Module of each custom entity, we created a default.xml
file under the resource-actions
folder.
This file defined Model Resource Permissions for each entity and listed the actions supported.
Sample (service/src/main/resources/resource-actions/default.xml
):
action-key
placeholders represent the actions you want to define for your entity. Step 2: Add a default.xml
in the Web Module
In the Web Module (Portlet Module) associated with the entity, we also created a default.xml
This file defined Portlet Resource Permissions.
Sample (web/src/main/resources/resource-actions/default.xml
):
This ensures the portlet itself is recognized in the Roles UI and can be assigned permissions.
Step 3: Create/Update portlet.properties
In the Web Module and Service Module, we created a portlet.properties
file (if not already existing) and added the following line:
resource.actions.configs=resource-actions/default.xml
- This tells Liferay to load the
default.xml
we created, so action keys are properly registered when the module deploys.
Step 4: Add Action Key Labels
We updated the module’s Language.properties to define readable labels for each action key.
Example:
- These appear in the Liferay Control Panel under Roles → Define Permissions.
Step 5: Handle Liferay’s 64 Action Keys Limit
- In Liferay, one entity can only have up to 64 action keys because of internal storage as bit fields.
- To manage hundreds of permissions across many entities:
- We designed modular entities with focused sets of action keys.
- Split large functionality into smaller logical modules when needed.
Result: No entity exceeded 64 keys, ensuring stability and smooth upgrades later.
Result: No entity exceeded 64 keys, ensuring stability and smooth upgrades later.
Step 6: Provide a Headless API for Frontend
To simplify frontend integration:
We exposed a custom Headless API that returns all action keys available to the logged-in user, grouped by entity.
The frontend team only needed one API call to fetch all permissions at once.
✅ This minimized complexity and accelerated frontend development.
Additional Note
Custom Action Keys for Liferay Objects:
We also implemented custom action keys for Liferay Objects (dynamic entities).
we’ll explain it separately in the next blog post.
Conclusion
By correctly setting up resource actions in both Service and Web modules, and by aligning closely with Liferay’s framework:
We delivered a scalable, admin-manageable, and future-proof permissions system.
No heavy custom development was needed beyond smart configuration.
At ReactorBee, we always aim to maximize platform capabilities to deliver elegant, enterprise-ready solutions quickly and reliably.