Active objects issues
Asked by Miroslav Kralik:

Hi;

I am trying to create a Confluence plugin that will store additional space attributes (such as space owner, backup space owners...). Initially I was storing the data in page labels and page content, but I would like to move it ideally to database.

I started playing with ActiveObject, but for some reason I am unable to store there object relationships.

Below is my code and console output with errors.

Any idea what could be wrong?

----------------

Space Attributes

```
package com.atlassian.confluence.msd.objects;

import com.atlassian.confluence.spaces.Space;
import com.atlassian.confluence.user.ConfluenceUser;
import net.java.ao.Entity;
import net.java.ao.OneToMany;
import net.java.ao.OneToOne;

public interface SpaceAttributes extends Entity {

    @OneToOne
    ConfluenceUser getSpaceOwner();
    void setSpaceOwner(ConfluenceUser spaceOwner);

    @OneToMany
    ConfluenceUser[] getSpaceBackupOwners();
    void setSpaceBackupOwners(ConfluenceUser[] spaceBackupOwners);

    String getDivision();
    void setDivision(String division);

    String getDataClassification();
    void setDataClassification(String dataClassification);

    String getBusinessClassification();
    void setBusinessClassification(String businessClassification);

    @OneToOne
    Space getSpace();
    void setSpace(Space space);

}
```

Space Attributes Service

```
package com.atlassian.confluence.msd.services;

import com.atlassian.activeobjects.tx.Transactional;
import com.atlassian.confluence.msd.objects.SpaceAttributes;
import com.atlassian.confluence.spaces.Space;
import com.atlassian.confluence.user.ConfluenceUser;

import java.util.List;

@Transactional
public interface SpaceAttributesService {

    SpaceAttributes add(Space space, ConfluenceUser spaceOwner, ConfluenceUser[] spaceBackupOwner, String division, String businessClassification, String dataClassification);

    List<SpaceAttributes> all();
}
```

Space Attributes Service Impl

```
package com.atlassian.confluence.msd.services;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.confluence.msd.objects.SpaceAttributes;
import com.atlassian.confluence.spaces.Space;
import com.atlassian.confluence.user.ConfluenceUser;
import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;

import javax.inject.Inject;
import javax.inject.Named;
import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Lists.newArrayList;

@Scanned
@Named
public class SpaceAttributesServiceImpl implements SpaceAttributesService {
    @ComponentImport
    private final ActiveObjects ao;

    @Inject
    public SpaceAttributesServiceImpl(ActiveObjects ao)
    {
        this.ao = checkNotNull(ao);
    }

    @Override
    public SpaceAttributes add(Space space, ConfluenceUser spaceOwner, ConfluenceUser[] spaceBackupOwner, String division, String businessClassification, String dataClassification)
    {
        final SpaceAttributes spaceAttributes = ao.create(SpaceAttributes.class);
        spaceAttributes.setSpace(space);
        spaceAttributes.setSpaceOwner(spaceOwner);
        spaceAttributes.setSpaceBackupOwners(spaceBackupOwner);
        spaceAttributes.setDivision(division);
        spaceAttributes.setBusinessClassification(businessClassification);
        spaceAttributes.setDataClassification(dataClassification);
        spaceAttributes.save();
        return spaceAttributes;
    }

    @Override
    public List<SpaceAttributes> all()
    {
        return newArrayList(ao.find(SpaceAttributes.class));
    }
}
```

Listener

```
@EventListener
public void onSpaceBlueprintCreateEvent(SpaceBlueprintCreateEvent event) {
    // Get space owners
    String spaceOwner = event.getContext().get(GlobalConstants.SPACE_OWNER).toString();
    ConfluenceUser spaceOwnerObject = userAccessor.getUserByName(spaceOwner.split(",")[0]);

    // Get space backup owners
    String spaceBackupOwners = event.getContext().get(GlobalConstants.SPACE_BACKUP_OWNER).toString();
    ConfluenceUser[] spaceBackupOwnersObject = new ConfluenceUser[spaceBackupOwners.split(",").length];

    for(int i = 0; i < spaceBackupOwners.split(",").length; i++) {
        spaceBackupOwnersObject[i] = userAccessor.getUserByName(spaceBackupOwners.split(",")[i]);
    }

    String division = event.getContext().get(GlobalConstants.DIVISION).toString();
    String businessClassification = event.getContext().get(GlobalConstants.BUSINESS_CLASSIFICATION).toString();
    String dataClassification = event.getContext().get(GlobalConstants.DATA_CLASSIFICATION).toString();

    spaceAttributesService = new SpaceAttributesServiceImpl(ao);
    spaceAttributesService.add(event.getSpace(),spaceOwnerObject,spaceBackupOwnersObject,division,businessClassification,dataClassification);
}
```

Console Output

```
[INFO] [talledLocalContainer] Caused by: com.atlassian.activeobjects.internal.ActiveObjectsInitException: bundle [com.atlassian.confluence.msd.SpaceTemplates]
[INFO] [talledLocalContainer] at com.atlassian.activeobjects.osgi.TenantAwareActiveObjects$1$1$1.call(TenantAwareActiveObjects.java:95)
[INFO] [talledLocalContainer] at com.atlassian.activeobjects.osgi.TenantAwareActiveObjects$1$1$1.call(TenantAwareActiveObjects.java:86)
[INFO] [talledLocalContainer] at com.atlassian.sal.core.executor.ThreadLocalDelegateCallable.call(ThreadLocalDelegateCallable.java:38)
[INFO] [talledLocalContainer] at com.atlassian.confluence.impl.vcache.VCacheRequestContextManager.doInRequestContextInternal(VCacheRequestContextManager.java:87)
[INFO] [talledLocalContainer] at com.atlassian.confluence.impl.vcache.VCacheRequestContextManager.doInRequestContext(VCacheRequestContextManager.java:71)
[INFO] [talledLocalContainer] at com.atlassian.confluence.vcache.VCacheRequestContextOperations.lambda$withRequestContext$1(VCacheRequestContextOperations.java:59)
[INFO] [talledLocalContainer] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[INFO] [talledLocalContainer] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[INFO] [talledLocalContainer] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[INFO] [talledLocalContainer] ... 1 more
[INFO] [talledLocalContainer] Caused by: java.lang.RuntimeException: Unrecognized type: [Lcom.atlassian.confluence.user.ConfluenceUser;
[INFO] [talledLocalContainer] at net.java.ao.types.TypeManager.getType(TypeManager.java:73)
[INFO] [talledLocalContainer] at net.java.ao.schema.SchemaGenerator.getSQLTypeFromMethod(SchemaGenerator.java:406)
[INFO] [talledLocalContainer] at net.java.ao.schema.SchemaGenerator.parseFields(SchemaGenerator.java:311)
[INFO] [talledLocalContainer] at net.java.ao.schema.SchemaGenerator.parseInterface(SchemaGenerator.java:277)
[INFO] [talledLocalContainer] at net.java.ao.schema.SchemaGenerator.parseDDLRoots(SchemaGenerator.java:159)
[INFO] [talledLocalContainer] at net.java.ao.schema.SchemaGenerator.parseDDL(SchemaGenerator.java:141)
[INFO] [talledLocalContainer] at net.java.ao.schema.SchemaGenerator.generateImpl(SchemaGenerator.java:106)
[INFO] [talledLocalContainer] at net.java.ao.schema.SchemaGenerator.migrate(SchemaGenerator.java:84)
[INFO] [talledLocalContainer] at net.java.ao.EntityManager.migrate(EntityManager.java:128)
[INFO] [talledLocalContainer] at com.atlassian.activeobjects.internal.EntityManagedActiveObjects.migrate(EntityManagedActiveObjects.java:51)
[INFO] [talledLocalContainer] at com.atlassian.activeobjects.internal.AbstractActiveObjectsFactory$1.doInTransaction(AbstractActiveObjectsFactory.java:77)
[INFO] [talledLocalContainer] at com.atlassian.activeobjects.internal.AbstractActiveObjectsFactory$1.doInTransaction(AbstractActiveObjectsFactory.java:72)
[INFO] [talledLocalContainer] at com.atlassian.sal.core.transaction.HostContextTransactionTemplate$1.doInTransaction(HostContextTransactionTemplate.java:21)
[INFO] [talledLocalContainer] at com.atlassian.sal.spring.component.SpringHostContextAccessor$1.doInTransaction(SpringHostContextAccessor.java:71)
[INFO] [talledLocalContainer] at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
[INFO] [talledLocalContainer] at com.atlassian.sal.spring.component.SpringHostContextAccessor.doInTransaction(SpringHostContextAccessor.java:68)
[INFO] [talledLocalContainer] at com.atlassian.confluence.spring.transaction.interceptor.ConfluenceSpringHostContextAccessor.access$001(ConfluenceSpringHostContextAccessor.java:21)
[INFO] [talledLocalContainer] at com.atlassian.confluence.spring.transaction.interceptor.ConfluenceSpringHostContextAccessor.lambda$doInTransaction$3(ConfluenceSpringHostContextAccessor.java:72)
[INFO] [talledLocalContainer] at com.atlassian.confluence.impl.vcache.VCacheRequestContextManager.doInRequestContextInternal(VCacheRequestContextManager.java:87)
[INFO] [talledLocalContainer] at com.atlassian.confluence.impl.vcache.VCacheRequestContextManager.doInRequestContext(VCacheRequestContextManager.java:71)
[INFO] [talledLocalContainer] at com.atlassian.confluence.spring.transaction.interceptor.ConfluenceSpringHostContextAccessor.doInTransaction(ConfluenceSpringHostContextAccessor.java:72)
[INFO] [talledLocalContainer] at sun.reflect.GeneratedMethodAccessor242.invoke(Unknown Source)
```


Answers:
author: Stephen Sifers
body: Hello Miroslav,

Congratulations on starting the undertaking to create a Confluence add-on.

Something to be aware of is this is a support community and not often browsed by developers. We want to ensure you get the responses and answers you need so we would suggest you check out the [Developer Community](https://community.developer.atlassian.com/). The [Developer Community](https://community.developer.atlassian.com/) may have more available resources to answer or address your developer questions.

Regards,  
Stephen Sifers

comments: author: Miroslav Kralik
body: Hello Stephen, thanks for the reminder. It looks like I overlooked it, as I was in impression I created it in developer community.

I re-created the article there. thanks.

Best regards, Miroslav


Tags: atl-dev

confluence-server

developer

server