Upgrading the Liferay Workspace Plugin Safely (When Using Service Builder and REST Builder)
I recently ran into an issue that's easy to reproduce and surprisingly confusing the first time you see it.
I had a Liferay workspace that was working perfectly. It included both Service Builder and REST Builder modules. The workspace plugin version was 13.1.0, and the target platform was 2025.Q1.20. Everything compiled cleanly. Life was good.
Then I decided to upgrade the workspace plugin to 15.0.0 so I could take advantage of some newer capabilities. After the upgrade, I modified some Service Builder code and regenerated the services.
That's when things broke.
I started getting compile errors in the persistence classes. The generated code didn't match my target platform anymore. It looked like it had been generated for a newer version of Liferay.
When I reverted the workspace plugin back to 13.1.0 and regenerated, everything worked again.
So what happened?
The Hidden Coupling: Workspace Plugin → Tool Versions
When you choose a version of the Liferay workspace plugin, you're not just choosing workspace behavior.
Internally, the workspace plugin determines which versions of:
- Service Builder
- REST Builder
are used during generation.
If you jump ahead to a much newer workspace plugin, it may start using newer versions of the Service Builder or REST Builder tools, and those tools may generate code intended for newer versions of Liferay than the one you're targeting.
That's exactly what happened to me.
My newer workspace plugin pulled in newer tool versions, and those tools generated persistence code incompatible with 2025.Q1.20.
Step 1: Identify the Tool Versions You're Currently Using
Before upgrading the workspace plugin, find out which versions of Service Builder and REST Builder you're using.
For Service Builder
From your -service module:
$ blade gw dependencies --configuration serviceBuilder
Example output:
> Task :modules:foo:foo-service:dependencies
------------------------------------------------------------
Project ':modules:foo:foo-service' - Foo :: Foo :: Service
------------------------------------------------------------
serviceBuilder - Configures Liferay Service Builder for this
project.
\--- com.liferay:
com.liferay.portal.tools.service.builder:1.0.513
+--- com.liferay:
org.apache.logging.log4j.core:2.17.1.LIFERAY-PATCHED-2
...
The important part is: com.liferay.portal.tools.service.builder:1.0.513
In this example, the Service Builder tool version is 1.0.513.
For REST Builder
From your -rest-impl module:
$ blade gw dependencies --configuration restBuilder
Example output:
> Task :modules:foo:foo-rest-impl:dependencies
------------------------------------------------------------
Project ':modules:foo:foo-rest-impl' - Foo :: REST :: Impl
------------------------------------------------------------
restBuilder - Configures Liferay REST Builder for this project.
\--- com.liferay:
com.liferay.portal.tools.rest.builder:1.0.419
+--- com.liferay:
org.freemarker:2.3.33.LIFERAY-PATCHED-2
...
The important part is: com.liferay.portal.tools.rest.builder:1.0.419
Here, the REST Builder tool version is 1.0.419.
Now you know exactly what tool versions are generating code compatible with your current target platform.
Step 2: Upgrade the Workspace Plugin
Now go ahead and update the workspace plugin version.
At this point, if you regenerate Service Builder or REST Builder code, you might start seeing problems. That's expected if the new workspace pulls in newer tool versions.
Step 3: Lock the Tool Versions in
gradle.properties
To keep using the compatible versions of Service Builder and REST Builder, explicitly set them in your gradle.properties file.
Add:
com.liferay.portal.tools.service.builder.version=1.0.513 com.liferay.portal.tools.rest.builder.version=1.0.419
(Replace with the versions you discovered earlier.)
Notice what we did:
- Took the artifact version from the dependency output
- Changed the colon (:) to an equals sign (=)
- Added them as explicit properties
Now the workspace plugin can be version 15.0.0 (or whatever you need), but Service Builder and REST Builder will continue using the tool versions you know are compatible with your target platform.
After this change, regenerate your services, and your build should succeed again.
Why This Happens More with Complex Service Builder Modules
In my case, the Service Builder module wasn't simple.
It included:
- Asset-enabled entities
- Workflow
- Search indexing
- Permissions
- Trash support
When you enable all of those features, the generated persistence and service code becomes tightly aligned with specific platform APIs.
Newer versions of the tools may generate slightly different patterns or use newer APIs that don't exist in your current target platform.
If you're working with very simple entities, you might get lucky and never notice a problem. But once you're using advanced features, version mismatches become much more likely to surface as compile errors.
The Takeaway
Upgrading the workspace plugin does not automatically mean your generated code will stay compatible with your target Liferay version.
If you:
- Identify your current Service Builder and REST Builder tool versions
- Upgrade the workspace plugin
- Explicitly lock the tool versions in
gradle.properties
You can safely move forward without breaking your build.
Sometimes you won't need to do this. But if you run into persistence compilation or other errors after a workspace upgrade, now you know exactly what's happening, and how to fix it in a few minutes instead of chasing ghosts for hours.


