In User Macro Velocity - How to use ContentService like PageManager?
Asked by WW:

I see this post about [How to use ContentService instead of PageManager?](https://community.atlassian.com/t5/Confluence-questions/How-to-use-ContentService-instead-of-PageManager/qaq-p/1546008), which is great for when I need to use ScriptRunner.

But how do I do the same thing inside of a custom **User Macro with Velocity**?

I can't figure out how to do **the Expansion part**. There is no documentation.

I tried something like this, but I knew it would fail miserably, and did.  

```
#set($contentFinder = $contentService.find(new Expansion('content'))

    .withPropertyKey($spaceKey)

    .withContentId($pageId)

    .fetch())
```

*It should be a requirement before releasing a deprecation's replacement to document the crap out of the new class. This is so frustrating!*

Does anybody have any ideas?


Answers:
author: Bill Bailey
body: Hello [@WW](/t5/user/viewprofilepage/user-id/1209024) , and welcom to the world of user macros -- so much power, so little documentation and support.

I have struggle whti this as well. Over the years, I have found macros from others much smarter than me, and then copied what they did. Not sure when I need to do this, but it does seems to make the methods I need work. ;-)

So on one of my complex macros, described in this article: [A-Child-Page-by-Label-User-Macro](https://community.atlassian.com/t5/Confluence-articles/A-Child-Page-by-Label-User-Macro/ba-p/1502246) , you will see early on in the macro as set of declarations:

```
#set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set( $containerManager=$getInstanceMethod.invoke(null,null) )
#set( $containerContext=$containerManager.containerContext )
#set( $pageManager=$containerContext.getComponent('pageManager') )
```

Do you need all of them? I am not smart enough to know, but now you get access to all of the page manager methods. You can look at the code in my article to see how to manulipulate the code to get what you need. For example:

```
$currentPage = $pageManager.getPage($content.id)
```

Now I will point you to this page as some of the objects are available by default:

<https://confluence.atlassian.com/doc/user-macro-template-syntax-223906130.html#UserMacroTemplateSyntax-Objectsavailabletoyourmacro>

comments: author: WW
body: Hi [@Bill Bailey](/t5/user/viewprofilepage/user-id/502089) ,

I'm familiar with how to instantiate the classes/objects in Velocity.

I don't think I explained the initial problem very well. I had assumed the answerer would understand the problem by going to the link I provided, which is the solution for using the Java API for the same problem I'm having, but that was probably not so clear. So here goes again:

**The problem is** that the PageManager and ContentEntityManager classes both now have **deprecated methods** that are super useful in Confluence User Macros, such as the methods:

```
$pageManager.getPage(spaceKey, pageTitle)
$pageManager.getPage(Id)

$contentEntityManager.getById(Id)
```

However, the methods they've been replaced with are not typical, and there is no documentation on their syntax. Here's what they say:
> [ContentService.find(Expansion...)](https://docs.atlassian.com/ConfluenceServer/javadoc/7.15.0/com/atlassian/confluence/api/service/content/ContentService.html#find-com.atlassian.confluence.api.model.Expansion...-) from plugins, or use [PageManagerInternal](https://docs.atlassian.com/ConfluenceServer/javadoc/7.15.0/com/atlassian/confluence/internal/pages/PageManagerInternal.html) in core where applicable
>
> [ContentService.find(Expansion...)](https://docs.atlassian.com/ConfluenceServer/javadoc/7.15.0/com/atlassian/confluence/api/service/content/ContentService.html#find-com.atlassian.confluence.api.model.Expansion...-) for plugins, or use [ContentEntityManagerInternal](https://docs.atlassian.com/ConfluenceServer/javadoc/7.15.0/com/atlassian/confluence/internal/ContentEntityManagerInternal.html) in core where applicable

As far as I know, any class with **Internal** at the end is only available to **Atlassian staff** , otherwise at least one of those might be useful. I don't know if the "**for plugins**" class/method would work in a User Macro. Seeing as how there are no examples provided and little documentation other than the structure, it's anybody's guess.

The link I provided to [the other Community post](https://community.atlassian.com/t5/Confluence-questions/How-to-use-ContentService-instead-of-PageManager/qaq-p/1546008) I previously linked to did give the syntax for using the Java API, but I need to know the **syntax in Velocity**.

In particular, **the Expansion part** is the not so typical part, and I have no idea how to approach it in Velocity since Velocity doesn't really handle nested *anything* very well.

The [Confluence objects accessible from Velocity](https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/) page says that $pageManager is an object accessible from Velocity, but it doesn't mention anything about the deprecated method replacements being available.

I'm just saying they need to be consistent, remember they have multiple locations for documentation and multiple ways in which objects are used, and they need to update, update, update the documentation.

I understand one department probably works on the deprecation replacement code and somebody else does the documentation for this area and somebody else for that area, but they need some cohesion. That and examples.


author: Bill Bailey
body: Well if you understand how to properly instantion classes and methods, you are way ahead of me. ;-) I started my career with punch cards,, but never really learned programming beyond BASIC. ;-) And I am stuck on 6.13.23 for a ton of reasons.

And I am not sure you can make an API call that way within a user macro. I have never seen it done that way from within Velocity.

And again, welcome to the world of writing user macros, where trying to find good examples is really hard, and having to deal with Atlassian documentation being in many locations and incomplete. For example, is this page still accurate as it is over a year old?

<https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/>

First, I would assume that anything marked **for plugins** can be *made* to work (maninly because you can package user macros as a plugin). The rub is trying to figure out how. For your specific case, the documetnation for current version of DC still shows the $space object being available (I assume it is accurate). So the following should still work in DC 7.15:

```
$currentSpaceKey = $space.getKey()
```

And the doc linked on that page still shows .getkey as being current

<https://docs.atlassian.com/atlassian-confluence/6.6.0/index.html?com/atlassian/confluence/spaces/Space.html>

And I see there is a method [getDisplayTitle](https://docs.atlassian.com/atlassian-confluence/6.6.0/com/atlassian/confluence/spaces/Space.html#getDisplayTitle--)`()`

And generally, even if a method says depricated, I try the dumb thing and test it out. I have found that atlassian is slow to actually remove depricated items.

And you can also bring classes and methods into the Velocity context, including your own java code:

<https://developer.atlassian.com/server/confluence/velocity-context-module/>

And let me direct you to another forum with lots of smart people <https://community.developer.atlassian.com/>

Another pro tip is to set up a plugin develop environment. While it is not intended to be used for user macro development, I have tested user macros within the environment as you get detailed syntax checking and some useful error messages from within the associated console -- very useful with complex macros.


author: WW
body: One of the deprecated methods used to work but now it doesn't (no idea why). So that's why I'm trying to change the existing code.

The code doesn't necessarily use the space for the page the macro is in, so $space wouldn't work for this.

I'm already using external classes, too.

We're not allowed to setup much of anything where I work, without an act of nature/Congress/whatever or without opening a can of worms. I've tried.

I checked the developer community, too, but that forum is mostly for plugins. From what I found, they don't much like or understand the new style of the deprecation replacement either, but there was no mention of Velocity.

I guess I could try re-posting my question there if no one else here has any ideas.


author: Bill Bailey
body: I have seen structures were they take

```
#set($contentFinder = $contentService.find(new Expansion('content')).withPropertyKey($spaceKey).withContentId($pageId).fetch())
```

By setting variables at each stage, for example

```
#set($contentFinder = $contentService.find(new Expansion('content'))
#set($contentFinderPropatery = $contentFinder.withPropertyKey($spaceKey)
```

Etc.

You could experiement by printing the results at each stage to make sure you are getting results.

And yes, I have to luxury of being the Confluence admin.

The developement enviroment still may help you to develop your code as you have complete control.

And yes, the developer community doesn't view us user macro developers as real developers. ;-) That we should be writing plugins instead,


author: WW
body: I *am*a Confluence admin. Unfortunately, we're not even allowed to install anything without jumping bureaucratic hurdles.

I'll try some of your examples to see if they work. I don't think the first one will since Velocity does not like anything nested, but who knows.

Thank you for your suggestions!


author: Bill Bailey
body: One thing I noticed is that you are first finding a matching space key and then page ID, is that right? But page IDs are unique to an instance. So would this not work?

```
#set( $targetPage = $pageManager.getPage($pageid) )
```

And your sistuation sounds really tough. But maybe if you can come up with a working solution you can demostrate, you could stand a chance of installing your macro?


author: WW
body: Unfortunately,

```
$pageManager.getPage(id)
```

is also deprecated.

The space key and page Id are what were in the example in the first link I posted in my question.

I'd still have to somehow declare the Expansion, its properties, and fetch.

Regardless, I looked at the macro's requirements and figured out a way to avoid having to use a Page object. So I no longer need to search for a page. I'm sure one day it would be good to know how to do, but for today, I surrender.


author: Bill Bailey
body: With user macros, I have had to surrender more than once. Good luck!


Tags: confluence-server

server

user-macro

velocity