Create a comment with custom properties via Java API

I want to create a comment with custom properties via the Confluence Java API (in a Rest endpoint I am exposing by a Confluence plugin).

My code is as following:

        Content commentedPage = contentService.find(new Expansion("id"))
                .withId(ContentId.of(comment.getCoordinates().getPageObjects().get(comment.getCoordinates().getPageObjects().size()-1).getPageId()))
                .fetch().get();

        comment.getProperties().put("highlight", comment.getHighlight());
        comment.getProperties().put("coordinates", comment.getCoordinates());

        String amdocsProps = "{\"key\": \"amdocsProps\", \"value\":" + new Gson().toJson(comment.getProperties()) + "}";
        logger.error("amdocsProps is: " + amdocsProps);


        Content.ContentBuilder contentBuilder = Content.builder()
                .type(ContentType.COMMENT)
                .container(commentedPage)
                .body(comment.getContent(), ContentRepresentation.STORAGE)
                .metadata(new HashMap<String,Object>(){{put("properties",new HashMap<String,String>(){{put("amdocsProps", amdocsProps);}});}});

I printed to the log the value of amdocsProps and it is as following:
{“key”: “amdocsProps”, “value”:{“visibility”:“medium”,“priority”:“medium”,“reply”:,“highlight”:{“text”:“performed during customer billing and f”,“occurrences”:1,“occurrence”:1},“coordinates”:{“pageObjects”:[{“pageId”:28216445,“pageVersion”:1}],“section”:“overviewsec”}}}

When I take this json string and use it as the body of Confluence API - /rest/api/content/{commentId}/property - The custom properties are added as required.

But, when doing it via server side - the properties do not get added.

I’ve tried also to create the comment without the properties, and only after the creation, to fetch it and add to it the properties. I did it like this:

        Content newComment = contentService.create(contentBuilder.build());



        @Nullable ContentEntityObject createdComment = contentEntityManager.getById(newComment.getId().asLong());
        ContentProperties commentProperties = createdComment.getProperties();
        propertyManager.setStringProperty(createdComment, "amdocsProps", new Gson().toJson(comment.getProperties()));

But again - the properties do not get added.

What am I doing wrong?
Any advice?

Thanks
Tova

As I am trying to figure the content properties out myself, I keep coming across other people getting the two different, but named the same, “content properties” mixed up, and rightly so. They should have been named differently. I posted a similar response in the Atlassian Community, but that was from the viewpoint of accessing the properties from the REST API itself.

You can still get to how the REST API does its thing from the Java API, which is what I’m guessing you did, since you’re using key/value pairs and you used toJson(). I’m also guessing the .metadata refers to the “REST API” pathway. I’ll refer to that kind of content properties as “REST API” from hereon (not to be confused, additionally :grin:, by your REST endpoint).

Here’s what I put in the Community, but I’ll translate after it.

The REST API content properties are stored in the content (key as the title) and bodycontent (value as Json) tables.

The Java API content properties are stored in the contentproperties table.

They’re completely different.

So when you set the values with the REST API, you cannot retrieve the values with the Java API, which is essentially what you’re trying to do in the user macro with Velocity.

You’d have to GET the data with the REST API if you POST the values with it.

In your first code example, that is somehow using the REST API pathway with a comment object. I’m not sure why it works in one place and not another.

In your second code example, you’re using the Java API pathway with contentEntityManager and ContentProperties (which is the key piece). You’re also missing another key piece, which I had to dig to find. You have to use contentEntityManager.saveContentEntity after setting the property/s or it won’t actually do anything.

You could still save your value as Json if you wanted, but using the Java API pathway, you can enter separate records in the contentproperties table and be able to search on their fields and values via SQL at least. You can’t access that type of content properties from the REST API, though.

I know it’s probably two years too late for you, but for anybody else digging, hopefully this will help.

I use ContentRepresentation.STORAGE and works for me.