Home/Field Guide/OSGi & Java
CONCEPT 06
MVC portlets and REST Builder
Separate native widgets, server-rendered commands, and generated REST contracts.
MVC portlets
A portlet is a page widget with its own lifecycle. Liferay MVC uses render commands to prepare views, action commands for mutations, and resource commands for widget-scoped resource responses. Bind a command to the portlet name and command name using DS service properties. Build URLs with the appropriate portlet URL tag, and namespace form inputs so two instances of a widget on one page do not collide.
Place business logic in a service and permission checks on every protected action or resource request. Keep rendering side-effect free and apply output escaping in views. Use the API and namespace for your target build. Jakarta-era projects need compatible portlet imports and component metadata.
REST Builder
REST Builder generates JAX-RS resources and DTOs from YAML contracts, typically rest-config.yaml and rest-openapi.yaml. Use the generated API and implementation modules, implement endpoint behavior in the designated implementation classes, and regenerate after contract changes. Inspect the resulting OpenAPI spec in API Explorer. Plan compatibility, pagination, errors, and permission behavior as public API decisions.
Choose by caller
| Caller | Typical fit | Why |
|---|---|---|
| Browser rendering a native portal widget | MVC portlet | Portal lifecycle, widget configuration, JSP or server rendering |
| Mobile, SPA, or external service | Published headless API | Explicit HTTP contract and reusable identity model |
| External client needing domain-specific transactions | REST Builder resource when Java deployment is supported | Contract and custom server-side orchestration |
Worked example
For “resolve request,” expose a dedicated operation if closing requires validation, an audit event, and one transaction. Test a repeated request and a caller from another account. If a supported Object action meets the same requirement, document its API contract and test the same boundaries. Use a versioned API when semantics need to change.
