I can't get Active Objects data loader to work for existing custom database tables

Hi,

I can’t get Active Objects data loader to work for existing custom database tables.

Here is content in pom.xml:

<properties>
        <confluence.version>8.4.2</confluence.version>
        <confluence.data.version>5.3.4</confluence.data.version>
        <amps.version>6.2.11</amps.version>
        <upm.license.compatibility.version>2.2.4</upm.license.compatibility.version>
        <ao.version>3.2.7</ao.version>
    </properties>

<dependency>
            <groupId>com.atlassian.activeobjects</groupId>
            <artifactId>activeobjects-plugin</artifactId>
            <version>${ao.version}</version>
            <scope>provided</scope>
        </dependency>
        <!-- Google Collections, useful utilities for manipulating collections -->
        <dependency>
            <groupId>com.google.collections</groupId>
            <artifactId>google-collections</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
        </dependency>

And content in atlassian-plugin.xml:

<component-import key="ao" interface="com.atlassian.activeobjects.external.ActiveObjects"/>
  <component key="appLifecycle" class="com.teknologiaplaneetta.confluence.grideditor.Servlets.AppLifecycle" interface="com.atlassian.sal.api.lifecycle.LifecycleAware" public="true"/>

<ao key="ao-module">
    <description>The module configuring the Active Objects service used by this plugin for Tasks</description>
    <entity>com.teknologiaplaneetta.confluence.grideditor.Servlets.Status</entity>
    <entity>com.teknologiaplaneetta.confluence.grideditor.Servlets.Timesheet</entity>
    <entity>com.teknologiaplaneetta.confluence.grideditor.Servlets.Hours</entity>
  </ao>

And these also:

package com.teknologiaplaneetta.confluence.grideditor.Servlets;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.sal.api.lifecycle.LifecycleAware;
import com.teknologiaplaneetta.confluence.grideditor.Servlets.LoadContentToStatus;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AppLifecycle implements LifecycleAware {

    private static final Logger log = LoggerFactory.getLogger(AppLifecycle.class);
    private final ActiveObjects ao;

    public AppLifecycle(ActiveObjects ao) {
        this.ao = ao;
    }

    @Override
    public void onStart() {
        log.info("AppLifecycle onStart method called");
        LoadContentToStatus loader = new LoadContentToStatus(ao);
        loader.importDataToStatus();
    }
}
package com.teknologiaplaneetta.confluence.grideditor.Servlets;

import java.util.ArrayList;
import java.util.List;

import com.atlassian.activeobjects.external.ActiveObjects;
import net.java.ao.Query;
import com.teknologiaplaneetta.confluence.grideditor.Servlets.Status;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoadContentToStatus {

    private static final Logger log = LoggerFactory.getLogger(LoadContentToStatus.class);
    private final ActiveObjects ao;

    public LoadContentToStatus(ActiveObjects ao) {
        this.ao = ao;
    }

    public void importDataToStatus() {
        log.info("Importing data to Status table...");
        // Assuming you have a method to get your data
        List<String> titles = getDataFromDatabase();

        for (String title : titles) {
            try {
                Status status = ao.create(Status.class);
                status.setTitle(title);
                status.save();
                log.info("Saved Status entity with title: " + title);
            } catch (Exception e) {
                log.error("Error saving Status entity with title: " + title, e);
            }
        }
    }

    private List<String> getDataFromDatabase() {
        List<String> statuses = new ArrayList<>();
        statuses.add("Open");
        statuses.add("In Progress");
        statuses.add("Incomplete");
        statuses.add("Complete");
        return statuses;
    }

}

Error:

2023-12-10 08:45:19,137 ERROR [lifecycle:thread-30] [confluence.grideditor.Servlets.LoadContentToStatus] importDataToStatus Error saving Status entity with title: Incomplete
 -- url: /rest/plugins/1.0/installed-marketplace | userName: admin | referer: https://confluence.i4ware.fi/plugins/servlet/upm | traceId: 3e4a22247bfed511
java.lang.IllegalStateException: plugin [{com.teknologiaplaneetta.confluence.grideditor.agile-application-stack}] invoking ActiveObjects before <ao> configuration module is enabled or plugin is missing an <ao> configuration module. Note that scanning of entities from the ao.model package is no longer supported.

I think this question has good answers for you: How to create custom filed on start of plugin - #2 by david.pinn

This is my Timesheet for Confluence plugin and I try to do custom database with Active Objects for Timesheet (Time-tracking toll for Atlassian Confluence which have nothing to do with Atlassian Jira). Active Objects works perfect bur when I try to import some content on my App installation to this custom Active Objects database table STATUS it not work after-all. I just try to import task statuses of Open, In Progress, Incomplete and Complete to this STATUS table.

This issue is now fixed by agency hired via Upwork.

1 Like

I hired freelancer from Upwork but he did wrong:

Here is code that work only if STATUS table exist:

<ao key="ao-module">
    <description>The module configuring the Active Objects service used by this plugin for Tasks</description>
    <entity>com.teknologiaplaneetta.confluence.grideditor.Servlets.Status</entity>
    <entity>com.teknologiaplaneetta.confluence.grideditor.Servlets.Timesheet</entity>
    <entity>com.teknologiaplaneetta.confluence.grideditor.Servlets.Hours</entity>
   <upgradeTask>com.teknologiaplaneetta.confluence.grideditor.Tasks.LoadContentToStatusTask</upgradeTask>
  </ao>
package com.teknologiaplaneetta.confluence.grideditor.Tasks;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.activeobjects.external.ActiveObjectsUpgradeTask;
import com.atlassian.activeobjects.external.ModelVersion;
import com.teknologiaplaneetta.confluence.grideditor.Servlets.LoadContentToStatus;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoadContentToStatusTask implements ActiveObjectsUpgradeTask {

    private static final Logger log = LoggerFactory.getLogger(LoadContentToStatusTask.class);

    @Override
    public ModelVersion getModelVersion() {
        return ModelVersion.valueOf("2");
    }

    @Override
    public void upgrade(ModelVersion modelVersion, ActiveObjects activeObjects) {
        log.info("Upgrading data to Status table...");
        //System.err.println("Upgrading data to Status table...");
        LoadContentToStatus loader = new LoadContentToStatus(activeObjects);
        loader.importDataToStatus();
    }
}
package com.teknologiaplaneetta.confluence.grideditor.Servlets;

import java.util.ArrayList;
import java.util.List;

import com.atlassian.activeobjects.external.ActiveObjects;
import net.java.ao.Query;
import com.teknologiaplaneetta.confluence.grideditor.Servlets.Status;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoadContentToStatus {

    private static final Logger log = LoggerFactory.getLogger(LoadContentToStatus.class);
    private final ActiveObjects ao;

    public LoadContentToStatus(ActiveObjects ao) {
        this.ao = ao;
    }

    public void importDataToStatus() {
        log.info("Importing data to Status table...");
        // Assuming you have a method to get your data
        List<String> titles = getDataFromDatabase();

        for (String title : titles) {
            try {
                Status status = ao.create(Status.class);
                status.setTitle(title);
                status.save();
                log.info("Saved Status entity with title: " + title);
            } catch (Exception e) {
                log.error("Error saving Status entity with title: " + title, e);
            }
        }
    }

    private List<String> getDataFromDatabase() {
        List<String> statuses = new ArrayList<>();
        statuses.add("Open");
        statuses.add("In Progress");
        statuses.add("Incomplete");
        statuses.add("Complete");
        return statuses;
    }

}

Caused by: java.sql.SQLSyntaxErrorException: Table 'i4ware_confluence.AO_3D9901_STATUS' doesn't exist
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:121)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:912)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1054)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1003)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1312)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:988)
	at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
	at net.java.ao.ForwardingPreparedStatement.executeUpdate(ForwardingPreparedStatement.java:45)
	at net.java.ao.ParameterMetadataCachingPreparedStatement.executeUpdate(ParameterMetadataCachingPreparedStatement.java:10)
	at net.java.ao.DatabaseProvider.executeInsertReturningKey(DatabaseProvider.java:1984)
	at net.java.ao.DatabaseProvider.insertReturningKey(DatabaseProvider.java:1848)
	at net.java.ao.EntityManager.create(EntityManager.java:399)
	at com.atlassian.activeobjects.internal.EntityManagedActiveObjects.create(EntityManagedActiveObjects.java:93)
	... 48 more

Where I put this after plugin enabled and AO status table created?