Blogs
Although it's not difficult, it's not as easy as you might hope.

Between major versions of Liferay, the internal structure of Service Builder (SB) modules can change—sometimes subtly, sometimes significantly. These changes might affect how services are implemented, extended, or referenced, and can easily break existing SB modules during an upgrade.
As developers, we often hope that a simple update to
gradle.properties
is enough. Change the
liferay.workspace.product
to your new target version,
build, deploy… and everything just works.
But if you’re here, you probably already know: it doesn’t.
So let’s walk through the correct and complete process for upgrading Service Builder modules properly—without carrying forward technical debt or breaking runtime behavior.
Step 1: Update the Target Liferay Version
Before doing anything else, update the
liferay.workspace.product
in your root
gradle.properties
to reflect your new version of Liferay,
whatever that might be.
This tells the workspace which product dependencies to use for building and deploying.
Step 2: Create Brand New SB Modules (Controversial, But Necessary)
Here’s where things might get a little controversial.
Many developers recommend deleting all generated source
files and running buildService
to regenerate. While
that can work, it comes with risks:
-
Old cruft may remain in the module
-
Non-source files (like service descriptors) might retain outdated structure
-
New Liferay version-specific defaults won’t be applied correctly
Instead, I strongly recommend creating fresh SB modules. This ensures a clean slate with no lingering legacy files and full compatibility with the new version.
Use Blade CLI:
$ blade create -t service-builder my-service-2025
It doesn’t matter that the module has a different folder name
(e.g., my-service-2025)—the final artifact names will still
be defined by the bnd.bnd
file.
Step 3: Copy Over Configuration — Carefully
From the old my-service modules:
-
Copy the bnd.bnd files to the new -api and -service modules.
Be sure not to lose any directives, such as:
-dsannotations-options: inherit
-
Copy service metadata selectively :
Open the old service.xml
Copy the <namespace>, package-path, <entity> blocks, and <exceptions>
Do not overwrite the DTD declaration. Service Builder relies on the DTD version to generate version-specific code. -
Check for new DTD attributes:
If upgrading from older versions like 7.1 to 7.4+, newer attributes may exist that you might need to add. In my 7.1 to 7.4 update, I added
change-tracking-enabled="false" external-reference-code="false" mvcc-enabled="false"
to my entities because I didn't need or want these additional columns or functionality.
Step 4: Run buildService
on the
New Modules
Now build your new modules for the first time:
$ blade gw buildService
This will generate:
-
All interfaces and implementations
-
Empty method stubs
-
Clean
portlet-model-hints.xml
andservice.properties
Step 5: Compare and Sync Configuration Files
Verify and sync the following:
-
portlet-model-hints.xml
Ensure all expected columns and types are present.
Copy over any old hint settings as needed.
-
service.properties
Copy from the old module to preserve the build number and prevent future deployment errors.
Step 6: Migrate Implementation Logic — Selectively
Now move your implementation logic from the old module carefully and manually:
-
Open the old model/impl and service/impl classes.
-
Copy only your custom methods, business logic, and helper utilities.
-
Do not copy old constructors, annotations, or class declarations.
This avoids bringing in outdated annotations, incorrect inheritance, or unsupported code patterns.
Also copy over:
-
resource-actions
(if used) -
META-INF/custom-sql
(for custom queries) -
Any custom Finder implementation classes
-
Constants, Configuration classes, and model helpers in the -api module
Once done, run buildService again to regenerate the interfaces based on your implementation changes.
Step 7: Compile and Validate the Modules
Build both -api and -service to verify that all your custom methods, references, and imports are valid under the new Liferay version.
Step 8: Deploy and Test
Now deploy the modules to your updated Liferay environment.
-
Verify that the modules deploy without errors
-
Watch for missing dependencies, OSGi errors, or unresolved component issues
-
Use the services in your portal to test:
-
Data access
-
CRUD operations
-
Custom finders
-
JSON/SOAP/GraphQL endpoints (if relevant)
-
Pay attention to:
-
Log errors (e.g., NPEs, IllegalArgumentException)
-
Unexpected data behavior
-
Permission or localization regressions
Conclusion: Clean Slate, Clean Upgrade
Upgrading SB modules between major versions of Liferay isn’t just about flipping a version flag. It’s about ensuring your services are:
-
Regenerated cleanly
-
Free from outdated configuration and binding
-
Using the latest APIs and conventions
While the process outlined here is more involved, it also ensures that you’re not carrying forward legacy quirks, obsolete code, or platform mismatches.
Once you’ve walked through these steps, your SB modules are truly upgraded—and ready to thrive on your new Liferay version.