Home/Knowledge Hub/Client extensions & integration
Client extensions & integration
Microservice Client Extensions in Liferay DXP
Architecture, configuration, OAuth 2, deployment, security and integration
Introduction
Traditional Liferay customizations are frequently deployed as OSGi modules inside the Liferay runtime. For example:
Liferay JVM
|
+-- MVC Portlet
+-- Service Builder
+-- REST Builder
+-- OSGi Component
+-- Event ListenerThis architecture is powerful, but it creates runtime coupling between the customization and Liferay. A Client Extension provides another integration model. Instead of deploying all custom application logic directly into the Liferay JVM, functionality can run externally and integrate with Liferay through supported interfaces.
The architecture becomes:
+-----------------------+
| Liferay DXP |
+-----------+-----------+
|
| HTTP / OAuth 2 / APIs
|
v
+-----------------------+
| External Microservice |
| Java / Python / Node |
| Go / .NET / etc. |
+-----------------------+What is a Client Extension?
A Liferay Client Extension is a mechanism for extending or integrating with Liferay while reducing direct coupling to the portal runtime. Client extensions can support different extension scenarios. Depending on the Liferay version and platform capabilities, examples can include:
- Custom element integrations
- Global CSS
- Global JavaScript
- Theme CSS
- Object actions
- Object validation
- Workflow-related integrations
- OAuth applications
- External microservices
The exact supported types depend on the Liferay release.
What is a Microservice Client Extension?
A Microservice Client Extension is intended for external application logic that needs to participate in a Liferay solution. The service can be developed independently using technologies such as:
- Java / Spring Boot
- Python / FastAPI
- Node.js
- Go
- .NET
- Other HTTP-capable frameworks
For example:
Liferay
|
+------> FastAPI AI Service
|
+------> Spring Boot Payment Service
|
+------> Node.js Notification Service
|
+------> Python Quantum ServiceThis allows teams to choose technology according to the workload rather than requiring every feature to execute inside Liferay.
Traditional OSGi vs Microservice Architecture
Consider a custom business operation. In the traditional model:
Browser
|
v
Liferay
|
vOSGi Module
|
v
Business LogicThe custom logic runs inside the Liferay JVM. With an external microservice:
Browser
|
v
Liferay
|
+----------------+
|
v
Microservice
|
v
Business LogicThe application logic executes outside Liferay.
Architectural Comparison
| Characteristic | OSGi Module | Microservice Client Extension |
|---|---|---|
| Runtime | Inside Liferay JVM | Outside Liferay JVM |
| Technology | Primarily Java/OSGi | Language/framework inde- |
| Deployment | Liferay deployment lifecycle | pendent External/container deployment lifecycle |
| Failure isolation | Lower | Potentially stronger |
| Scaling | Usually tied to Liferay | Can scale independently |
| Communication | Java/OSGi services | HTTP/API-based |
| Security | Portal/OSGi security model | OAuth/API/network security |
| Upgrade coupling | Potentially stronger | Potentially reduced |
Why Use Microservice Client Extensions?
They are useful when the application requires:
- Independent deployment
- Independent scaling
- Non-Java technologies
- AI/ML workloads
- Quantum computing integration
- Data processing
- External APIs
- Long-running computation
- Specialized libraries
- Better failure isolation
High-Level Architecture
A typical architecture is:
+----------------------+
| User |
+----------+-----------+
|
v
+----------------------+
| Liferay DXP |
| |
| Pages |
| Objects |
| Workflow |
| Headless APIs |
| OAuth 2 |
+----------+-----------+
|
| HTTPS
|
v
+----------------------+
| Microservice Client |
| Extension |
+----------+-----------+
|
v
+----------------------+
| Business Service |
| |
| FastAPI |
| Spring Boot |
| Node.js |
| Go |+----------+-----------+
|
v
+----------------------+
| DB / AI / Quantum / |
| External Systems |
+----------------------+Role of client-extension.yaml
A central artifact in a client-extension project is typically:
client-extension.yamlIt describes the client extension and its integration configuration. Conceptually:
my-microservice:
name: My Microservice
type: microserviceThe exact schema and properties depend on the Liferay version and client extension type.
Project Structure
A conceptual project structure can look like:
my-microservice/
|
+-- client-extension.yaml
|
+-- Dockerfile
|
+-- src/
| |
| +-- application code
|
+-- requirements.txt
|
+-- README.mdFor Java:
my-service/
|
+-- client-extension.yaml
+-- Dockerfile
+-- build.gradle
+-- src/
+-- main/
+-- java/For Python:
quantum-service/
|
+-- client-extension.yaml
+-- Dockerfile
+-- requirements.txt
+-- app/
+-- main.py
+-- services/
+-- models/Example FastAPI Microservice
Consider a simple Python service:
from fastapi import FastAPI
app = FastAPI()
@app.get("/health")
def health():
return {
"status": "UP"
}
@app.post("/api/process")
def process(payload: dict):
return {
"success": True,
"input": payload
}The service runs independently from Liferay. For example:
http://microservice:8000or in production:
https://service.example.comContainerizing the Microservice
A common deployment strategy is Docker. For the FastAPI example:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir \
-r requirements.txtCOPY . .
CMD [
"uvicorn",
"app.main:app",
"--host",
"0.0.0.0",
"--port",
"8000"
]Build the image:
docker build -t my-liferay-service .Run locally:
docker run \
-p 8000:8000 \
my-liferay-serviceThen test:
curl http://localhost:8000/healthExpected result:
{
"status": "UP"
}Client Extension Build
In a Liferay workspace, client extensions are commonly located under:
client-extensions/For example:
liferay-workspace/
|
+-- client-extensions/
| |
| +-- my-microservice/
| |
| +-- client-extension.yaml
| +-- ...
|
+-- modules/
+-- themes/
+-- gradle/A typical Gradle workflow may involve:
./gradlew buildor building the specific client extension project. On Windows:
gradlew.bat buildThe build packages the client-extension configuration into an artifact that Liferay can deploy.
Deployment Concept
A key distinction is that there are effectively two deployment concerns:
The client extension registers/configures the integration with Liferay. The actual microservice runs separately. Conceptually:
BUILD
|
+----------+----------+
| |
v v
Client Extension Microservice
Artifact Container
| |
v v
Liferay Docker/K8s/
Cloud RuntimeDeployment Flow
A practical flow can be understood as:
- Develop the microservice.
- Test the service independently.
- Define the client extension.
- Configure authentication.
- Build the client extension.
- Build the service/container.
- Deploy the client extension to Liferay.
- Deploy the microservice to its runtime.
- Configure environment variables and secrets.
- Verify connectivity.
- Test authentication.
- Execute end-to-end integration testing.
Communication Direction
There are two important directions of communication.
Liferay to Microservice
Examples:
- Object Action
- Workflow action
- Webhook
- External validation
- AI inference request
Microservice to Liferay
Examples:
- Read Liferay Objects
- Update Object entries
- Retrieve documents
- Create content
- Query users
- Invoke Headless APIs
Many real systems use both directions.
OAuth 2 Authentication
A microservice should generally not call protected Liferay APIs without authentication. OAuth 2 can provide service-to-service authorization. The architecture becomes:
+--------------------+
| Microservice |
+---------+----------+
|
| OAuth 2
v
+--------------------+
| Liferay |
| OAuth Provider |
+---------+----------+
|
v
+--------------------+
| Headless REST APIs |
+--------------------+Client Credentials Flow
For machine-to-machine communication, a common OAuth pattern is:
There is no interactive user login. Instead:
Microservice
|
| client_id
| client_secret
v
OAuth Token Endpoint
|
| access_token
v
Microservice
|
| Bearer Token
v
Liferay APIConceptually:
Token Request
A conceptual token request is:
POST /o/oauth2/token
grant_type=client_credentials
client_id=YOUR_CLIENT_ID
client_secret=YOUR_CLIENT_SECRETThe response can contain:
{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 600
}The service then sends:
Authorization: Bearer ACCESS_TOKENwhen calling Liferay.
Calling Liferay Headless APIs
Suppose the microservice needs to retrieve Liferay Object entries. Conceptually:
GET /o/c/orders/
Authorization: Bearer ACCESS_TOKENThe response may contain:
{
"items": [
{
"id": 101,
"orderNumber": "ORD-1001"
}
]
}Thus:
Python Example
A simplified Python example is:
import requests
LIFERAY_URL = "https://portal.example.com"
CLIENT_ID = "my-client"
CLIENT_SECRET = "my-secret"
token_response = requests.post(
f"{LIFERAY_URL}/o/oauth2/token",
data={
"grant_type": "client_credentials",
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET
}
)
token_response.raise_for_status()
token = token_response.json()["access_token"]
response = requests.get(
f"{LIFERAY_URL}/o/c/orders/",
headers={
"Authorization": f"Bearer {token}"
}
)
response.raise_for_status()
print(response.json())Environment Variables
A microservice can use environment variables such as:
LIFERAY_URL
LIFERAY_CLIENT_ID
LIFERAY_CLIENT_SECRET
DATABASE_URL
LOG_LEVELPython example:
import os
liferay_url = os.environ["LIFERAY_URL"]
client_id = os.environ["LIFERAY_CLIENT_ID"]
client_secret = os.environ[
"LIFERAY_CLIENT_SECRET"
]This separates configuration from application code.
Development vs Production
Development might use:
Liferay:
http://localhost:8080
Microservice:
http://localhost:8000Production might use:
Liferay:
https://portal.company.com
Microservice:
https://api.company.comThe application should therefore avoid hard-coded URLs.
Deployment Using Containers
The external service can be deployed using:
- Docker
- Kubernetes
- Cloud container platforms
- Virtual machines
- Managed application platforms
Conceptually:
Internet / Private Network
|
+-------------+-------------+
| |
v v
+-------------+ +---------------+
| Liferay DXP | | Microservice |
+-------------+ +-------+-------+
|
v
+-------------+
| Database / |
| AI / APIs |
+-------------+Kubernetes Architecture
For larger deployments:
+--------------------------------------+
| Kubernetes Cluster |
| |
| +---------------+ |
| | Service | |
| +-------+-------+ |
| | |
| +-------+--------+ |
| | Load Balancer | |
| +-------+--------+ |
| | |
| +-----+-----+ |
| | | |
| v v |
| +-----+ +-----+ |
| | Pod | | Pod | |
| +-----+ +-----+ |
| |
+--------------------------------------+
^
|
| HTTPS
|
Liferay DXPThe microservice can scale independently:
without necessarily scaling the Liferay runtime itself.
Independent Scaling
Suppose Liferay handles:
while an AI service receives:
The AI workload may require more compute resources than the portal. With a microservice architecture:
Each component can be scaled according to its workload.
Failure Isolation
Suppose an AI service crashes. With tightly embedded application logic:
With an external microservice:
Liferay can remain available and display an appropriate service error or retry later.
Timeouts
External calls must have explicit timeouts. Bad approach:
requests.get(url)Better:
requests.get(
url,
timeout=10
)Without timeouts, slow external services can consume application resources indefinitely.
Retries
Transient failures may justify retry logic. For example:
This is an example of exponential backoff. However, retries must be used carefully. A POST operation that creates data should not automatically be repeated unless the operation is designed to be idempotent or otherwise protected against duplication.
Circuit Breaker
If an external service is repeatedly failing, continuing to call it can worsen system instability. A circuit breaker conceptually behaves as:
This can protect Liferay and the external service during outages.
Health Checks
A microservice should expose a health endpoint. For example:
GET /healthResponse:
{
"status": "UP"
}A more advanced health endpoint might check:
- Database connectivity
- Liferay connectivity
- Model availability
- Message broker availability
- Required external APIs
Logging and Observability
A distributed architecture requires strong observability. Useful information includes:
- Timestamp
- Request ID
- Correlation ID
- Service name
- HTTP status
- Response time
- Error details
For example:
requestId=abc-123
service=quantum-service
endpoint=/simulate
status=200
duration=840msCorrelation IDs
A request may cross multiple systems:
A correlation ID can follow the request:
X-Correlation-ID: abc-123Then logs across systems can be associated with the same transaction.
Security Architecture
A secure architecture should consider:
- HTTPS/TLS
- OAuth 2
- Least privilege
- Secret management
- Network restrictions
- Input validation
- Authentication
- Authorization
- Logging
- Token expiration
The goal is:
Least Privilege
A microservice should receive only the permissions required for its function. For example, if a service only reads orders:
not:
This limits the impact of credential compromise.
Example AI Architecture
A useful Liferay architecture is:
+---------------------+
| Liferay Portal |
| |
| UI |
| User Management |
| Workflow |
| Objects |
+----------+----------+
|
| REST
v
+---------------------+
| FastAPI |
| AI/ML Service |
+----------+----------+
|
v
+---------------------+
| ML Model |
| PyTorch / TF / etc. |
+---------------------+This avoids forcing Python machine-learning dependencies into the Liferay JVM.
Example Quantum Architecture
The same architecture works particularly well for quantum services.
+------------------------+
| Liferay DXP |
| |
| Assessment Portal |
| User Management |
| Workflow |
+-----------+------------+
|
| REST
v
+------------------------+
| FastAPI Quantum |
| Microservice |
+-----------+------------+
|
+------+------+
| |
v v
+---------+ +---------+
| Qiskit | | Qulacs |
+---------+ +---------+ |
v
+-------------------------+
| Quantum Backend / |
| Simulator |
+-------------------------+This provides a clean separation:
while:
Microservice vs Remote App
A useful conceptual distinction is:
| Microservice | Remote UI/App | |
|---|---|---|
| Primary role | Backend/business logic | External user interface |
| Interaction | API/service calls | Browser-facing application |
| Typical technologies | FastAPI, Spring Boot, Node | React, Angular, Vue |
| UI required | No | Usually yes |
A solution may contain both.
Deployment Pipeline
A CI/CD pipeline can be:
Developer
|
v
Git Repository
|
v
CI Pipeline
|
+-------------------+
| |
v v
Build Client Build Docker
Extension Image
| |
v v
Deploy to Push to
Liferay Registry
|
v
Deploy
|
v
MicroserviceThis allows the portal integration and service runtime to have controlled but independent deployment lifecycles.
Versioning
External services should expose versioned APIs. For example:
/api/v1/diagnose
/api/v2/diagnoseinstead of relying permanently on:
/diagnoseVersioning makes backward-compatible upgrades easier.
API Contract
The integration between Liferay and a microservice should have a clearly defined contract. For example:
POST /api/v1/diagnose
Request:
{
"patientId": "P10025",
"imageId": 7812
}
Response:
{
"reportId": "R-981",
"prediction": "Normal",
"confidence": 0.94
}The contract should define:
- Endpoint
- HTTP method
- Authentication
- Request schema
- Response schema
- Error codes
- Timeout
- Version
Common Deployment Problems
Microservice is Unreachable
Check:
- DNS
- Service URL
- Firewall
- Container port
- Reverse proxy
- TLS certificate
401 Unauthorized
Check:
- Client ID
- Client secret
- Access token
- Token expiration
- OAuth configuration
403 Forbidden
Authentication may have succeeded, but the service identity may not have sufficient permissions.
Connection Refused
Verify:
host
port
container status
service status
networkTimeout
Check:
- Service processing time
- Network latency
- Downstream systems
- Timeout configuration
Recommended Production Architecture
A robust enterprise architecture can be represented as:
+----------------+
| User |
+-------+--------+
|
v
+----------------+
| Liferay DXP |
+-------+--------+
|
OAuth 2 / HTTPS
|
v
+----------------+
| API / Gateway |
+-------+--------+
|
+-----------+-----------+
| |
v v
+---------------+ +---------------+
| Microservice | | Microservice |
| A | | B |
+-------+-------+ +-------+-------+
| |
v v
Database AI / External
SystemOptional enterprise components can include:
- API gateway
- Message broker
- Centralized logging
- Metrics
- Distributed tracing
- Secret manager
- Kubernetes
Best Practices
For production deployments:
- Keep the microservice stateless where practical.
- Use HTTPS.
- Use OAuth 2 for protected Liferay APIs.
- Keep secrets outside source code.
- Apply least privilege.
- Define explicit HTTP timeouts.
- Use retries only where safe.
- Use health checks.
- Add correlation IDs.
- Centralize logs.
- Version APIs.
- Validate input.
- Design idempotent operations where practical.
- Monitor latency and failures.
- Separate development, test, and production configuration.
Interview Questions
Multiple Choice Questions
Question 1
Where does a Microservice Client Extension’s application logic primarily execute?
A. Inside the browser only
B. Inside the Liferay JVM
C. Outside the Liferay JVM
D. Inside Elasticsearch
Answer: C
Question 2
Which file commonly describes a Liferay client extension?
A. portal-ext.properties
B. client-extension.yaml
C. service.xml
D. web.xml
Answer: B
Question 3
Which technology can be used to implement an external microservice?
A. Spring Boot
B. FastAPI
C. Node.js
D. All of the above
Answer: D
Question 4
Which OAuth flow is commonly suitable for machine-to-machine communication?
A. Client Credentials
B. Interactive password entry on every API call
C. JSP session flow
D. None
Answer: A
Question 5
Which header commonly carries an OAuth access token?
A. Content-Length
B. Host
C. Authorization
D. Accept-Language
Answer: C
Question 6
What is a major benefit of external microservices?
A. They require every service to use Java
B. They can scale independently
C. They eliminate network communication
D. They remove all security requirements
Answer: B
Question 7
Where should production client secrets normally be stored?
A. Public GitHub repository
B. JavaScript source
C. Environment/secret management system
D. HTML page
Answer: C
Question 8
What does HTTP 401 generally indicate?
A. Authentication problem
B. Successful request
C. Database backup
D. Client extension build success
Answer: A
Question 9
What does HTTP 403 generally indicate?
A. Authorization/permission problem
B. DNS success
C. Docker build success
D. Liferay startup completion
Answer: A
Question 10
Why are correlation IDs useful?
A. They increase CPU speed
B. They trace a request across distributed services
C. They replace OAuth
D. They replace TLS
Answer: B
Question 11
Which is generally preferable for a computationally intensive Python AI model?
A. Embedding Python dependencies directly in the Liferay JVM
B. External Python microservice
C. JSP scriptlet
D. Theme CSS
Answer: B
Question 12
Which component provides REST APIs for external services to interact with Liferay resources?
A. Liferay Headless APIs
B. CSS Loader
C. JSP Compiler
D. Theme Builder
Answer: A
Quick Revision
| Concept | Meaning |
|---|---|
| Client Extension | External extension/integration mechanism |
| Microservice | Independently running application service |
| client-extension.yaml | Client extension configuration descriptor |
| OAuth 2 | Authorization framework for secured API access |
| Client Credentials | Machine-to-machine OAuth grant |
| Headless API | REST API exposed by Liferay |
| Docker | Container packaging/runtime technology |
| Kubernetes | Container orchestration platform |
| Health Check | Endpoint indicating service health |
| Correlation ID | Identifier for tracing distributed requests |
| Circuit Breaker | Resilience pattern for failing services |
Key Takeaway
The fundamental architecture is:
Instead of placing every customization inside the Liferay JVM:
the system can be decomposed into:
and:
This architecture is particularly useful for applications involving AI/ML, quantum computing, data processing, external enterprise systems, or independently scalable backend services. The production design should emphasize:
rather than treating a microservice as simply another HTTP endpoint.
Official Reference
For current, version-specific configuration and deployment details, refer to the official Liferay documentation:
https://learn.liferay.com/w/dxp/development/integrating-microservices/
using-a-microservice-client-extensionThe exact client-extension.yaml schema, supported properties, OAuth configuration, and deployment process should always be verified against the Liferay DXP release used by the target environment.
Prefer to read offline? Download the PDF edition (29 pages).
