Blogs
Recently we got a couple of complains about new Web Content article behaviour, specifically about the JournalArticle.getContent() method’s return value. The main problem developers experience is when they embed an Image into the Web Content article or use ddm-image or ddm-document-library field in their structures they expect to see the URL of the object(Image or D&M asset) in the raw XML when using JournalArticle.getContent() method, it actually was there in the 7.0 and the raw XML looked like this:
(...)
<dynamic-element
name="Image8r1v" type="image" index-type="text" instance-id="ryns">
<dynamic-content
language-id="en_US" alt="" name="blonde.png" title="blonde.png"
type="journal" fileEntryId="34506" id="34835">
/image/journal/article?img_id=34835&t=1531817578959
</dynamic-content>
</dynamic-element>
(...)
There are two main differences in the 7.1:
We switched from the internal table JournalArticleImage to the common Documents and Media repository as a storage for the Web Content article images
DDM fields for Image and D&M assets changed their internal representation from the URL to the JSON object
Now the raw XML of the article with Images or ddm-image(ddm-documentlibrary) fields looks like this:
(...)
<dynamic-element
name="Image54q7" type="image" index-type="text" instance-id="wscg">
<dynamic-content language-id="en_US">
<![CDATA[\{
"groupId":"20124","name":"allatonce.png","alt":"",
"title":"allatonce.png","type":"journal",
"uuid":"80269faa-dea9-fd5a-cb78-3c7aa9da51ea",
"fileEntryId":"36774","resourcePrimKey":"36772"}
]]>
</dynamic-content>
</dynamic-element>
(...)
It was an internal decision and we didn’t realize that out there could be developers who actually use the raw XML content for their own needs…
First I would like to explain why it was done, not to try to excuse for this case, but to prevent such cases in the future. On the one hand, JournalArticle.getContent() method is a public API and its behaviour must be, at least, backward compatible, but on the other hand its behaviour depends on many components behind it, the signature of the method didn’t change and the implementation details (including the raw XML format of the content) never were published. To avoid such a problem we strongly recommend the developers to use published means for Web Content processing, such as JournalContent and JournalArticleDisplay. Both of them provide processed content of the Article without need to work with the raw XML, clear example can be found in the Web Content Display portlet:
(...)
JournalArticleDisplay articleDisplay = _journalContent.getDisplay(
article, ddmTemplateKey, viewMode, languageId, page,
new PortletRequestModel(renderRequest, renderResponse), themeDisplay);
String processedContent = articleDisplay.getContent();
(...)
@Reference
private JournalContent _journalContent;
(...)
Also there is a taglib which allows to render a specific journal article using its JournalArticleDisplay instance:
<liferay-journal:journal-article-display articleDisplay="<%= articleDisplay %>" />
Or the developer can use JournalContent.getContent() method directly, the result must be the same - processed content where all the fields behave as expected.
Now let’s talk about how to get the URLs back because I understand that it could be a problem to refactor hundreds of lines of your code and the best way for the developers who use the raw XML would be to keep processing the URLs as they were doing it before.
Here I have to mention one detail - there is no way to return to the old format of the URLs for embedded images, so if you have some sort of regular expression catching “/image/journal/article...” - there is no way to make it work again.
There are two options to get the URLs back, both need to adapt your existing code, which works with the raw XML, a little bit.
First option is applicable when you have a concrete file entry ID:
(...)
// here fieldValue is raw XML field value for your Image/DM field
JSONObject jsonObject = JSONFactoryUtil.createJSONObject(fieldValue);
long fileEntryId = jsonObject.getLong("fileEntryId");
FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(fileEntryId);
String fileEntryURL = PortletFileRepositoryUtil.getDownloadPortletFileEntryURL(
themeDisplay, fileEntry, StringPool.BLANK);
(...)
And the second option is applicable in case when you don’t have specific file entry ID, but have UUID and group ID of the target entry:
(...)
// here fieldValue is raw XML field value for your Image/DM field
JSONObject jsonObject = JSONFactoryUtil.createJSONObject(fieldValue);
String fileEntryGroupId = jsonObject.getLong("groupId");
String fileEntryUuid = jsonObject.getLong("uuid");
FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
fileEntryUuid, fileEntryGroupId);
String fileEntryURL = PortletFileRepositoryUtil.getDownloadPortletFileEntryURL(
themeDisplay, fileEntry, StringPool.BLANK);
(...)
Hope these 5 lines of code help you to solve the problem. We understand that it could be frustrating to deal with such changes and we are trying to do our best to avoid them without actual need.

