Broken Boilerplate for intermediate blueprint plugin

Greetings,

we just installed Confluence Server Edition and want to shape it fitting our workflow. Sadly it doesn’t seem as easy as i expected.

Currently i need to create a ‘intermediate’ blueprint. Nothing special. All we want is a simple blueprint with its own template and name. Also the current date should be inserted into the title (just like the meeting notes-blueprint). But i didn’t even get to this point…

I followed the beginner tutorial and created a basic blueprint without any context provider nor java code. Worked as expected. After that i went on to the intermediate tutorial and tried to create a context provider.

I can’t follow the tutorial anymore since it seems like it uses some old confluence-create-content-plugin. Also the created plugin boilerplate already includes some java-code splitted into impl and api. I tried to work around this issue and follow the guide, but wasn’t able to get it working.

To get a better idea of a working code example i found (or so i though…?) the source of the meeting notes-blueprint on bitbucket. https://bitbucket.org/atlassian/confluence-business-blueprints/src/84b86c46d457?at=master But a cloned repo does also not run via atlas-run.

Next i tried to use the atlas-sdk scripts to create a clean plugin and blueprint boilerplate. So i used atlas-create-confluence-plugin to create my plugin (which works), followed by atlas-create-confluence-plugin-module and selected the option blueprint. Also added a ContextProvider via the interactive script. And guess what? It doesn’t work. Seems like the Script creates also a ‘old’ version of ContextProvider-Blueprint since atlas-run fails with package com.atlassian.confluence.plugins.createcontent.api.contextproviders does not exist.

All i was able to find about this issue are old threads without a working solution, people telling each other how bad the confluence-guides are and some info about using Spring-Scanner instead of the broken create-content-plugin. (I would provide links to my found threads, but i am not allowed to post more links.)

I was redirected to the README-file of the used Spring-Scanner in Confluence but can’t wrap my head around how to use it in my ‘simple’ blueprint.

I really didn’t though that this will need so much work. All i want is the current Date in the Page Title to make the confluence experience for my coworkers as pleasant as possible…

1 Like

Usually the solution is simple, truth is confluence can be bitchy until you master it.
Truth is though I can’t reproduce your error with confluence 5.8.8.
To me it sounds like an OSGi issue, please take a look on your pom.xml, in the section of plugins, in the artifact maven-confluence-plugin, especially the Import-Package section.
It should be looking like

<Import-Package>
    org.springframework.osgi.*;resolution:="optional",
    org.eclipse.gemini.blueprint.*;resolution:="optional",
    com.atlassian.plugin.osgi.bridge.external,
    com.atlassian.confluence.plugin.descriptor.web.conditions.user;resolution:="optional",
    com.atlassian.confluence.plugin.descriptor.web.conditions;resolution:="optional",
    com.atlassian.confluence.mail.notification.actions;resolution:="optional",
    com.atlassian.confluence.pages.persistence.dao.*;resolution:="optional",
    *;resolution:=optional
</Import-Package>

Now, add the com.atlassian.confluence.plugins.createcontent.api.contextproviders in the section, just like rest of entries and ensure that the dependency confluence-create-content-plugin has scope provided.
If that won’t work, please make some github so i can check it.

1 Like

Thank you for your help.

Indeed, confluence feels bitchy. But i managed to archive ‘something’?

I created a new plugin, followed the beginner guide to create u dumb blueprint. Worked out fine. I deleted the impl and api folder and placed my BlueprintContextProvider.java there.

I tried something simple first: blueprintContext.put("vName", "TestUserName"); to test my ‘structure’. First i got failing Maven-Unit-Tests. So i deleted the test-files in the test-dir. Still: Tests failing… Some googling later i am starting the test-server via atlas-run -DskipTests=true -Dmaven.test.skip=true (is it somehow possible to disable the maven tests till use them globally?). Anyway, my simple Variable Function worked.

Now i wanted to create what i was trying to archive: Put the current date into the Site-Title.

As best as i could i tried to copy the official meeting-notes blueprint (https://bitbucket.org/atlassian/confluence-business-blueprints/src/84b86c46d4577b3cbe189ececd092689a06efcf7/plugin/src/main/java/com/atlassian/confluence/plugins/meetingnotes/MeetingNotesContextProvider.java?at=master&fileviewer=file-view-default) Worked out every thrown error. Now atlas-run -DskipTests=true -Dmaven.test.skip=true starts without a problem. No ERROR message or Warnings. But when log into confluence the blueprint plugin does’nt load. This add-on couldn't be loaded. It has one or more errors that prevent it from being enabled. Where can i find the error-log, or what can cause this?

Maybe my BlueprintContextProvider.java-file can help out: https://pastebin.com/mPrvxQMn It sits in ../src/main/java/com/domain/confluence/plugins/.

Greetings

by doing atlas-run -DskipTests=true as you did.

The output of atlas-run should contain the cause. Otherwise you are looking for catalina.out file. Generally speaking catalina.out and atlassian-confluence.log are your sources of logging.

Without looking on the tutorial you followed… add @Scanned in your class, @ComponentImport in
whatever you DI and @Inject in the constructor. Your class should look like:

@Scanned
public class BautagebuchContextProvider extends AbstractBlueprintContextProvider {
   @ComponentImport
    private LocaleManager localeManager;
   @ComponentImport
    private final I18NBeanFactory i18NBeanFactory;
   @ComponentImport
    private final UserAccessor userAccessor;
   @ComponentImport
    private final FormatSettingsManager formatSettingsManager;
 
   @Inject
    public BautagebuchContextProvider(LocaleManager localeManager,
                                      I18NBeanFactory i18NBeanFactory,
                                      UserAccessor userAccessor,
                                      FormatSettingsManager formatSettingsManager) {
        this.localeManager = localeManager;
        this.i18NBeanFactory = i18NBeanFactory;
        this.userAccessor = userAccessor;
        this.formatSettingsManager = formatSettingsManager;
    }

I am not quite sure if i18nbeanfactory needs it. Improvise :slight_smile:

1 Like

Thank you Panos once again.

I played with @ComponentImport and @Inject and was able to understand the needed basics to get it working (Blueprint with String-Date in the Title).

For my last magic trick i need to get the current Space Name and place it into the document. Sadly i need help once again.

I searched through the javadoc and found some classes which return the space-name e.g.: https://docs.atlassian.com/atlassian-confluence/5.9.2/com/atlassian/confluence/core/SpaceContentEntityObject.html#SpaceContentEntityObject-- or Spaced, GlobalHelper, …

But i always get the same error: non-static method getSpace() cannot be referenced from a static context. I am not really into object-oriented-programming, but i though that this could fix it:

@Scanned
public class BautagebuchContextProvider extends AbstractBlueprintContextProvider {
    [...]
    @ComponentImport
    private final GlobalHelper globalHelper;

    @Inject
    public BautagebuchContextProvider(LocaleManager localeManager,
                                      [...]
                                      GlobalHelper globalHelper,
                                      [...]) {
        [...]
        this.globalHelper = globalHelper;
    }

Sadly it only results into a timeout while loading the plugin (while starting the tomcat server for confluence) till the plugin gets skipped after 25 seconds. Is the some function i can use in a static context, or do i only need a little snippet again, which i am missing out? :slight_smile:

As reference my current code: http://pastebin.centos.org/521356/

Greetings

Step 1) Change the GlobalHelper with
com.atlassian.confluence.web.context.HttpContext.HttpContext
Step 2) Get the ThemeContext:
ThemeContext themeContext = ThemeContext.get(httpContext.getRequest());
Step 3) Get the space(key) by
themeContext.getSpace() / themeContext.getSpaceKe()
Step 4)
Profit and accept the answer :smiley:

1 Like

I really would like to press that that “accept the answer” button, but i think i need one last step :smiley:

I imported HttpContext and ThemeContext, added HttpContext via:

    @ComponentImport
    private final HttpContext httpContext;

    @Inject
    public BautagebuchContextProvider(LocaleManager localeManager,
                                      [...]
                                      HttpContext httpContext,
                                      [...]) {
        [...]
        this.httpContext = httpContext;
    }

and tried to get the spacename with:

        ThemeContext themeContext = ThemeContext.get(httpContext.getRequest());
        Space space = themeContext.getSpace();
        String spaceName = space.getName();

        blueprintContext.put("vSpaceName", spaceName);

which resulted in a javax.servlet.http.HttpServletRequest not found error. After some googling i added the following to my pom.xml-file:

        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.3</version>
          <scope>provided</scope>
        </dependency>

The Plugin now compiles, but i can’t use the blueprint in confluence: We can't create that blueprint right now.. Also no Error-Output in the console. As soon as i remove the quoted snippets, everything works fine. (I also tried the newest version of javax.servlet e.g. 2.5)

Thank you again Panos!

… if you want to see the whole ContextProvider: http://pastebin.centos.org/523271/

Edit: When i try a different approach:

        ThemeContext themeContext = ThemeContext.get(httpContext.getRequest());
        String spaceKey = themeContext.getSpaceKey();
        Space space = new Space(spaceKey);
        String spaceName = space.getName();

        blueprintContext.put("vSpaceName", spaceName);

i don’t get any errors, but the variable field stays blank :confounded:


Edit2: Okay, i just got it working… Somehow i was not able to retrieve a proper SpaceKey (always blank). So i simply guessed and tried to interact with the given BlueprintContext:

        String spaceKey = blueprintContext.getSpaceKey();
        Space space = spaceManager.getSpace(spaceKey);
        String spaceName = space.getName();

        blueprintContext.put("vSpaceName", spaceName);

and it works! Sadly i really just guessed (after reading about generated PageID and the whole meaning of “context”. And since we are using java, i simply tried a function i often found in similar objects…

Can you link me the right documentation for this? I can’t find it and want to read about this blueprintContext. Also i want to give you the answer :wink:

I am sorry, i dont understand what you mean by “right documentation”.

Documentation for confluence is so sparsed, depending on version, plugin version and much more. example… confluence is a mix of spring and atlassian stuff where spring core is tied to atlassian needs. At least that’s my perception.

I also never used blueprints :slight_smile:

1 Like