Wasim's Site
Back to all articles
Tutorial

Creating Your First Liferay Object: A Step-by-Step Tutorial

Published on July 8, 2026 by Wasim

What You'll Build

This tutorial walks through creating a working Contact Object from scratch — a simple business contact management model. By the end you'll have a custom data model with six fields, an auto-generated admin UI, live REST and GraphQL APIs, basic role permissions, and one real record created and queried — all without writing code, using only the Liferay Control Panel.

Prerequisites: Liferay DXP or Portal 7.4+ (or the equivalent 2024.Q4+ / 2025.Qx / 2026.Qx cloud release), plus the Administrator or Object Administrator role. Check with your site administrator if you're unsure which role you have — Object creation requires "Object Definitions" permission.


Step 1: Navigate to Objects

Log in to Liferay, open the Global Menu (top-left grid/hamburger icon), and under Control Panel click Objects:

Global Menu → Control Panel → Objects

If this is your first Object, the list will be empty aside from any system-defined Objects Liferay ships with. See the official Creating and Managing Objects guide for the full reference.


Step 2: Create the Object Definition

Click Create Object Definition and fill in the basic details:

Field Value Notes
Label Contact Singular, human-readable name
Plural Label Contacts Used in menus and API URLs
Name Contact Auto-fills from Label; internal system name
Scope Site Or "Instance" for availability across all sites
Storage Type Default (Liferay's database) Alternative: an external table, if configured

You'll also see three optional toggles — Enable Workflow (approval steps before a record goes live), Enable Comments (discussion threads on records), and Enable Categorization (tag records with categories/tags). Leave all three off for this tutorial; you can turn them on later without losing data.

Click Save. Liferay creates the base Object shell and takes you to its detail page, ready for fields.


Step 3: Add Fields

Click Add Field for each piece of data the Contact needs.

Full Name — Type: Text, Required: Yes, Indexed: Yes (enables search/filter).

Email — Type: Text, Required: Yes, Unique: Yes. Setting Unique: Yes means Liferay rejects any new record whose email already exists elsewhere in the Object — the simplest way to prevent duplicate contacts.

Phone — Type: Text, Required: No, Indexed: No.

Status — Type: Picklist, Required: Yes. A Picklist is a predefined dropdown; when you select it, Liferay asks you to create a new options list or reuse an existing one. Create a new list called Contact Status with the options Active, Inactive, Pending, and set Active as the default.

Date Added — Type: Date, Required: No.

Notes — Type: Long Text, Required: No. Use Long Text for anything that might run more than a sentence or two — Liferay renders it as a larger text area in the generated form.

Your finished field list:

Field Type Required Unique
Full Name Text Yes No
Email Text Yes Yes
Phone Text No No
Status Picklist Yes No
Date Added Date No No
Notes Long Text No No

Step 4: Review Field Order

Most Object editors let you drag and drop fields into a logical order, which determines how they appear in the auto-generated form. A sensible order here is simply Full Name → Email → Phone → Status → Date Added → Notes.


Step 5: Publish the Object

Click Publish. Liferay validates the field configuration and, once it checks out, activates the Object. This single click generates:

  • A database table behind the scenes
  • REST API endpoints at /o/c/contacts
  • An updated GraphQL schema
  • An admin UI (list view plus a create/edit form)
  • Default permissions, initially restricted to Administrators

You can safely add new fields after publishing at any time. Changing a field's type once it holds data is riskier — Liferay will warn you if a change could affect existing records.


Step 6: Explore the Auto-Generated Admin UI

Go back to Global Menu → Control Panel → Objects → Contact (or, if the Object is site-scoped, look for a new Contacts menu item under that site's Content section). You'll find a list/table view of all records (empty for now), a New Contact button, column headers matching your fields, and basic sort/filter controls — all generated without any UI work on your part.


Step 7: Create Your First Record

Click New Contact. Liferay presents a form built directly from your field definitions. Fill in sample data:

Full Name:    Jane Rivera
Email:        jane.rivera@example.com
Phone:        555-0142
Status:       Active
Date Added:   2026-07-08
Notes:        Initial contact via conference lead.

Click Save, and Jane Rivera's record appears in the list view immediately.


Step 8: Verify the Auto-Generated API

The API is live the moment you published in Step 5 — no separate deployment step. Open the API Explorer at http://your-instance:8080/o/api and look for Contact under REST Applications; you'll see the full OpenAPI spec with all six CRUD endpoints already generated.

Test it directly:

curl -X GET 'http://localhost:8080/o/c/contacts' \
  -H 'Authorization: Bearer YOUR_TOKEN'
{
  "items": [
    {
      "id": 40001,
      "fullName": "Jane Rivera",
      "email": "jane.rivera@example.com",
      "phone": "555-0142",
      "status": "Active",
      "dateAdded": "2026-07-08",
      "notes": "Initial contact via conference lead.",
      "dateCreated": "2026-07-08T11:20:00Z",
      "dateModified": "2026-07-08T11:20:00Z"
    }
  ],
  "totalCount": 1,
  "pageNumber": 1,
  "pageSize": 20
}

Seeing your record come back as JSON confirms the data model, admin UI, and API all came from the single configuration you just did. For the full range of what these endpoints support — filtering, sorting, relationships, authentication — see REST APIs Auto-Generated by Liferay Objects.


Step 9: Set Basic Permissions

New Objects are restricted to Administrators by default. To open Contacts up to another role, go to the Object's Permissions tab, choose a role (e.g., a custom Sales Team role), and assign granular permissions — View, Add, Update, Delete, and Permissions (who else can manage access).

A common real-world setup for a sales role:

Permission Sales Team
View
Add
Update
Delete
Manage Permissions

This lets salespeople create and edit contacts without being able to delete records or change who else has access. Click Save.


Step 10: Confirm Everything Works End-to-End

Run through this quick checklist before calling the Object done:

  • Object appears in Control Panel → Objects
  • Fields display correctly in the auto-generated form
  • A new record can be created via the UI and shows up in the list view
  • GET /o/c/contacts returns the record via the API
  • A POST request can create a record via the API
  • The role you assigned can access Contacts according to the permissions you configured

If all of those hold, your first Object is production-ready.


Common Beginner Mistakes to Avoid

Forgetting to mark required fields. If a field like Email isn't marked Required: Yes, users can save incomplete records — set it on anything your business logic depends on.

Skipping unique constraints. Without Unique: Yes on Email, duplicate contacts with the same address will be allowed. Decide up front which fields must be unique.

Overcomplicating the first version. It's tempting to add twenty fields immediately. Start with 5–8 essential fields, publish, test, and expand later — adding fields afterward is easy, but changing types or removing fields on populated data is riskier.

Skipping permission configuration. An Object left accessible only to Administrators means no one else can actually use it. Assign role permissions before considering it "done."

Ignoring picklist reuse. If you build a similar Object later (say, an Application Object with its own status field), check whether you can reuse an existing picklist definition instead of creating a duplicate list of the same options.


What Gets Created Behind the Scenes

For reference, here's everything Liferay generates automatically the moment you publish — none of it requires manual setup:

Component Auto-Generated
Database table
REST endpoints (GET, POST, PUT, PATCH, DELETE)
GraphQL schema
OpenAPI/Swagger documentation
Admin list view
Admin create/edit form
Field validation (required, unique)
Default permission structure
Search indexing (for indexed fields)

Next Steps

Once your first Object is working, natural extensions include adding relationships (linking Contact to a Company Object), adding Object Actions to trigger automated logic like a notification on status change, customizing the UI layout, enabling Workflow so records require approval, or building a custom frontend that consumes the REST/GraphQL API directly. Each builds on the foundation from this tutorial — there's no need to start over.


Summary

You created an Object Definition (Contact), added six fields spanning Text, Picklist, Date, and Long Text types, published it, created a record through the auto-generated UI, verified the REST API returns live data, and configured role-based permissions — all through the Control Panel, with no custom code, manual database work, or separate API development.

This is the core loop you'll repeat every time you model new business data in Liferay: define fields, publish, and the UI, API, and permissions scaffolding all come with it.


Wasim Shaikh

About the Author

Wasim Shaikh is an experienced UI/UX Developer & Front-End Engineer with 15+ years of expertise. Based in Ahmedabad, Gujarat, India, he specializes in Liferay, React, Angular, Next.js, Tailwind CSS, and CMS integrations. He regularly shares insights on web development, SEO, and performance optimization through his blog wasimshaikh.com.