I want to change the contents of a page in a Confluence server plugin. All the sample code I found was involving a Page object, but it seems since version 7.3 more or less all methods providing a Page object e. g. in PageManager are deprecated in favor of ContentService.find(...) methods. These work fine, and I can read the body contents. However, I found no way to change the body of a Content object. I found ContentManager has an update(content) method, but I did not find any way to change a Content or ContentBody object, they seem to be read only.
How can I update the body of a page?
Apart from the deprecated methods like
pageManager.saveNewVersion(page, p -> pageObject.setBodyAsString(...))
I only found the REST API call
PUT /rest/api/content/{contentId}
But it seems strange to have to go through a client call in order to just change the content body.
I found the solution, the logic is similar to the REST API call: you have to create a new Content object from the original one via a Content.ContentBuilder, and use that in the call to the ContentService method update(). What was a bit annoying is that I got an
IllegalStateException: Cannot call get() on collapsed object, ensure the property was included in the expansions on the original service request
in the last line of the code shown below, and there was no indication which Expansions were needed to be added, and it was not hust one! A lot of trial and error lead me to find that ANCESTORS and SPACE is needed in addition to BODY and VERSION, which I had added from teh beginning as they are needed to create the new Content object. The following code now has all required Expansions added:
Content content = contentService.find(
new Expansion(Content.Expansions.BODY, new Expansions(new Expansion("storage"))),
new Expansion(Content.Expansions.ANCESTORS),
new Expansion(Content.Expansions.SPACE),
new Expansion(Content.Expansions.VERSION)
)
.withSpace(space)
.withId(ContentId.of(contentId))
.fetchOrNull();
if(content == null
|| operationService.canPerform(user, OperationKey.UPDATE, Target.forModelObject(content)).isNotSuccessful()) {
throw new Exception("No content for id " + contentId + " or user has no update permission for it");
}
ContentBody body = content.getBody().get(ContentRepresentation.STORAGE);
Content newContent = Content
.builder(content)
.body(body.getValue() + "<p>Test: " + System.currentTimeMillis() + "</p>", ContentRepresentation.STORAGE)
.version(content.getVersion().nextBuilder().by(user).build())
.build();
contentService.update(newContent);
The above code seems to work fine for BlogPosts as well as Pages, depending what the contentId points to.
Frank, thank you for your feedback! It helped me with the example how to create Expansions for find().
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.