Blogs
Let me say that again:
Pretty strong statement, but for for those considering Liferay as a platform it's really an important concept, one that lives in the core of Liferay.
Note: This is really a different kind of blog post for me. I prefer to keep things technical and discuss practical solutions to common problems. But I've actually seen this problem come up in many projects and I'm sure many of you have seen it too. So forgive me while I climb up on my soap box and preach for a while...
The Authors Dilemma
Since the first cave drawings, authors have been able to express themselves using basic tools to put thought to paper (or some other transferrable media). The only barriers to creating content was the availability of the basic instruments.
In the modern era, publishing became a structured process that applied to most physical print media. Whether a book, a magazine or a newspaper, the following roles are involved:
- Writer - Responsible for authoring the content.
- Editor - Approves content and edits for length, content, format, syntax and spelling.
- Illustrator - Provides supporting images if it's illustrated.
- Production Designer - Handles page layout and general design.
- Printer - Generates the final physical media.
With the invention of the world wide web, publishing on the web still needed to follow this standard process (in lieu of the printer, instead you have the web browser). After all, it is still publishing even though it's on a digital platform.
The dilemma for these roles for web publishing is that the simple, basic tools that were used in the past were replaced with complex computer languages and required software developers (and often development teams). Even the initial HTML-only pages still required computer knowledge, tools and skills, things that the average content authors don't have.
Unfortunately, adding software developers into the content authoring process brought with it the software development process.
Publishing and the Software Development Process
After a lot of pain and suffering, software development lifecycles and processes were defined and implemented to reduce or eliminate bugs. An experienced developer knows and appreciates the separate environments for development, testing, UAT and production. A development team's goal is to push the promotion of the software artifacts through each successive enviroment and eventually make it to production.
The publishing process actually overlays onto this development process without too much contention, especially given the original nature of web publishing.
Remember way back in 1995 when we first started creating web pages? I do so I guess that dates me a little. At that point in time we were creating complete HTML pages with content wrapped in <b>, <i>, <u> and (god forbid) <blink> tags. We'd connect all of the pages with simple <a> tags and had some <img> tags too. Pages were extremely simple, but more important, an HTML page contained everything.
We quickly moved away from simple HTML and started doing some JSP pages, some PHP pages, some perl, some ruby, some <insert favorite web language here>... We added CSS to style the content and JavaScript to liven it up.
Even with this shift, however, the files contained everything. Even with web applications, REST, javascript SPAs, etc. we still have the same basic concept that the files contained everything.
So with web publishing, the artifacts created by the developer could be promoted through the environments just as non-web projects. The classic publishing roles would overlay onto the environments, perhaps in a different order, but in each of the environments the different roles could effect change on the content and, on final approval, can be published on the production environment.
It's been like that for 20 years now, so long that it's practically ingrained in our enterprises that for web content creation/publishing we need to get all those environments lined up and ready for content promotion.
Enter The Liferay
So we come to Liferay with this expectation on how web content publishing works. I mean, it's been this way for 20 years, so this is the only way it can and should work. Right?
Well, wrong. Liferay actually allows the restoration of the classic publishing roles. Through existing facilities already baked into the Liferay core, a writer can author content. Through the use of workflow, editors can approve and edit content. Illustrators can upload images. Using local or remote staging, production designers can deal with page layouts and design. The printer doesn't generate physical media, but they can be responsible for publishing the staging content to the live site.
Great! We've restored the classic publishing process, so everything is puppies and flowers!
Well, not really. Liferay really sticks it to the old time web content developers and project managers because it practically eliminates the ability to promote content between environments. Liferay really doesn't allow you to create content in development and promote it to test, UAT and eventually production.
This seems to blow everyone's minds. How is a PM supposed to say "yes, the developer did the job correctly and the content is ready for promotion'? How does a developer provide a software artifact to support marking the end of a phase of the SDLC? We can't possibly do a real web project on Liferay without support for web content promotion...
The Trouble with LARs
It's usually this point where someone will say "Hey, I can export pages/content as a LAR file from one environment and then import it into another! I can force Liferay to support web content promotion..."
That's really a problem. Often it will work in a test case or for an initial short run, but LARs are really the round peg for a "web content promotion" square hole. In order to get LARs to work in this process, you really end up shoving and pushing and hammering to try to get it to work.
Here's some finer points about LARs that often need to be mentioned when discussing using them in this fashion:
- They are extremely fragile. LAR imports can break if you even look at them funny.
- Failures are reported like idiot lights on a car dashboard. The errors logged during failures are quite obtuse. They don't tell you what part of the LAR failed, they don't report what conflicts actually are, and they certainly don't suggest how you fix the problem.
- LAR imports terminate on first exception. If your LAR actually has five potential import exceptions, you're not going to know it until you complete a few rounds of export/import/analyze to work through all the issues individually.
- LARs are tightly coupled to the version of Liferay. LARs are stamped with the version of Liferay the data was exported from and will not import into a different Liferay version. And this is not a major version restriction (i.e. from 6.1 to 6.2), this is an exact version match on specific GA or SP release.
- LARs can be tightly coupled to installed plugins. Depending upon options selected during LAR export, the LAR file can actually contain data related to deployed plugins; if the plugins are not available on the target system, the import will fail. For example, exporting a page that has a calendar instance, the LAR will contain info about this; if the target Liferay does not have the calendar plugin installed, the LAR import will fail. One might expect the page to load but exclude the calendar, but it is treated as an entire failure.
- LARs do not maintain asset IDs during import. LARs actually do their work on asset names. This allows the LAR import to work by reassigning a valid surrogate ID in the system where the assets are imported. However, if any of your code refers to an asset by ID that code will likely fail in other environments as surrogate ID values will not be guaranteed to match. So if you use a simple URL to embed an image in web content using the ID, it will need to be adjusted in the target system to get it to work. These kinds of things can be tricky because there is no failure at LAR import time, it really will only be noticed by someone viewing the imported LAR content in the site.
- It is super easy to export a LAR that cannot be imported. This is really frustrating and happens a lot with structures. When you're exporting a journal article that uses a structure it is normal to include the structure in the LAR. But after you do this once, the structure would have already been loaded into the target environment (maybe). So you should stop including the structure in the LAR as this allows the import to work until, of course, you try to import into an environment that doesn't have the structure loaded...
- LAR created/modified users and times. This is valuable meta information, but if I give you a LAR that has web content that I created, it won't keep that information in your system unless I'm a user in your environment.
- Big LAR files fail to load for mysterious reasons. Often they are due to some of the previously raised points, but other times they just outright fail and don't give you a reason.
And seriously, the list of issues goes on, but I think you get the point.
Long story short, the idea that LARs can be used to support a long term process of promoting web content between environments is really doomed to failure. Those of you who are using LARs to support web content promotion, well I'm sure you've already seen some of these issues and, if you haven't yet, well then I'd say so far you have been lucky but predict that luck will run out.
LARs were designed for a specific use case, but web content promotion between environments was not one of them.
Restoring Sanity
No, LARs are not broken, so don't go opening bugs on Liferay.com to get web content promotion working.
What's broken is the view that web content creation must be treated as a development activity.
It's not, and everyone really should be happy about that. Developers are not web content creators and project managers are not editors nor designers and web content creation is not a project.
So restore sanity in your Liferay installation. Get the PMs and developers out of the web content creation business.
Set up a workflow process to allow knowledgable folks to review and approve content. Set up staging (either local or remote) to give folks time to lay things out and have them reviewed and approved. Manage all of the normal activities that a publishing process requires.
But do all of these things in production. Don't try to push down to the lower levels of a SDLC setup, and don't try to force web content creation through the promotion process as though it's a software development artifact.
Liferay spent a lot of time and effort bringing these web content creation and publication tools into Liferay so the content creation process could be freed from the grips of the IT department.
Take advantage of this freedom. It is yours...
Update 07/2023: What is Content?
This blog post has been up a long time. It still very much applies even in the latest 7.4 version.
However, there is this basic question that plagues most of us when using Liferay - what is content?
There are obvious answers to this of course. Web content articles are certainly content, blog posts are content, forum posts are content, ...
But there are many other things that Liferay considers content that most developers (including myself), would not.
A web content template, for example, is a Freemarker script. That's like all code, so certainly it should be treated like code and live in the developer's source repository, should be developed, tested, approved and promoted like any other code artifact.
This same thing can also apply to:
- Web content structures
- Widget templates
- ADTs
- Workflow definitions
- Custom fragments
- Object definitions
- Site/Page templates
- Forms
- Blueprint Recipes
- Etc
There are Liferay things which typically require some development experience/background/skills to build, and they often require testing and approval of some kind.
And yet, we have Liferay's definition for content:
That's right. All of the things listed above, which as a developer I would want to classify and treat as a development artifact, Liferay considers to be content. And because they are content, there is little if any support for storing in a developer source repository or promotion between environments.
The argument goes like this... Since we know that Web Content is classified as content, and we are only creating the Web Content in production, if that Web Content is dependent upon a structure and template, well those too only should be built in production. There's no benefit to creating them in our test environment because we are not creating Web Contents and promoting them from there.
Probably the one item I have the most issue with is the custom fragments. Yes you can build them in the UI and yes they get stored in the database, so per Liferay's definition this is content, but they're really all code, yeah? HTML, CSS and JS together to create the right presentation, this doesn't seem like content to me at all. Fortunately for this one, though, I can use the fragment toolkit to build the custom fragment outside of Liferay and treat it like the development activity that it is, and that's the only way I do custom fragments... But still, it is too tempting to just build it in the UI so you can make quick changes, test, more changes, ... The development cycle is much faster, but I know I'm going to struggle moving those things later on.
There are some aspects that do have some export/import support. Objects, for example, can be exported as JSON and imported into a new environment, so you can do a form of promotion, and through a Batch Client Extension, you could turn your export into a deployable artifact to automate the deployment into other environments, but there can be shortcomings to this. If, for example, you create a Form that is bound to the object definition and is used for adding new objects, you can promote your objects but you're going to struggle trying to get that form to promote and would probably end up re-creating it anyway, so why go through this headache?
The best advice that I can give you on these things is that you should just follow Liferay's lead and treat them like content . Build your templates in prod. Define your objects in prod. If you're not going to use the fragment toolkit to build custom fragments, then only build custom fragments in prod.
Of course, enable staging so that you have a separation between your live data and your staging data...
But continue to treat these things as content. Even though, as a developer, you will disagree that these items are content, to Liferay they absolutely still are.
Trust me, you'll have a much easier time if you embrace this rule than if you try and go against the grain...
The Exception
There is one exception though that I want to share - the Site Initializers...
- https://liferay.dev/blogs/-/blogs/introducing-site-initializers
- https://liferay.dev/blogs/-/blogs/site-initializers-101
As a quick review, a Site Initializer is a developer artifact that can contain basically everything from the list above, but those files can be stored in your source repository, and they can be built and deployed and promoted between environments.
So it solves all of our "this is really code" concerns.
But there are two things to keep in mind:
First, you have to plan for this. You can't get up one day and say "Hmm, I'll take my site and create an initializer out of it and then start promoting it" (although I did find an interesting project that I haven't tested, https://npm.io/package/generator-liferay-site-initializer). It can take a lot of work to extract your assets, transform as necessary, add to a site initializer project, build, deploy and test it. If you plan for this from the start and update it as you build your site out and continually test it, it will be a much easier path.
Second, for most Liferay versions a Site Initializer is only good for creating a new site. Doesn't work so well when you have a site and just want to update it. However, later versions of 7.4 support updating an existing site from a Site Initializer. Currently it is hidden behind a feature flag to use right now, but expect it to be fully available in a future bundle. Read more about it here: https://liferay.dev/blogs/-/blogs/site-initializers-update-support.