how to use same active object tables in two different plugin?

Dipti Ranjan Behera
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 6, 2013

I have created a table through active object in one plugin. And i want to access the same active object table in another plugin.

What should i have in my plugin descriptor and classes ?

3 answers

1 accepted

4 votes
Answer accepted
Adrien Ragot 2
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 7, 2013

Rephrasing Daniel:

  • AO Tables are sandboxed and can't be seen from other plugins;
  • The component that manages the table (the DAO) can be made visible to other plugins.

However, making the component public requires good programming skills. There probably are a thousand questions about that, but here's a summary:

  • In atlassian-plugin.xml,
    • Declare your <component/> as public=true (It's Spring technology),
    • Declare an <interface> tag inside your component.
  • In pom.xml
    • Declare an <Export-Package> tag to export the java class (It's OSGi technology),
    • The other plugin must declare the first one in <dependencies>, with <scope>provided</scope>
  • Good luck. There should be a "I've mastered an Export-Package declaration" badge on Answers ;)
BKippelt September 21, 2017

Can you give me a simple example? Atlassian Spring Scanner compliant.

Daniel Wester
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 21, 2017

I would suggest moving this question over to community.developers.atlassian.com (lot's more developers there :) ).

But the basic gist is that you'll need to create another maven artifact that holds all of your interfaces.

Then in the add-on that has the service that you want to expose, implement that interface.

Then you'll need to annotate the class with

@ExportAsAService

Then in your pom.xml where you have the <Import-Package/> area - add:

<Export-Package>your package to the interface here</Export-Package>

 

Then in your add-on that imports the service, just do an @ComponentImport and you'll be in business.

BKippelt September 22, 2017

These are not real plugins. Written just briefly so that I can understand it. Maybe someone can add to that or at least comment on it.

 

Plugin Test with AO

package com.test.confluence.plugins.ao.table;

import net.java.ao.Entity;
import net.java.ao.Preload;
import net.java.ao.schema.Table;

import java.util.Date;

@Preload
@Table("TEST_FIELD")
public interface TestAoTable extends Entity {

public String getFieldValue();
public void setFieldValue(String fieldValue);

public String getFieldName();
public void setFieldName(String fieldName);
}

AO TABLE

 

package com.test.confluence.plugins.ao;

import com.test.confluence.plugins.ao.model.FieldModel;
import java.util.List;

@ExportAsService
public interface TestAo {

FieldModel get(String field);
FieldListModel getList();
Boolean add(FieldModel model);
Boolean update(FieldModel model);
Boolean delete(FieldModel model);

}

 TestAo Interface

 

package com.test.confluence.plugins.serviceportal.ao.impl;

@Component
@ExportAsService
public class TestAoImpl implements TestAo {

private final ActiveObjects ao;
private final TransactionTemplate transactionTemplate;


@Autowired
public TestAoImpl(@ComponentImport final ActiveObjects ao,
@ComponentImport final TransactionTemplate transactionTemplate) {
this.ao = ao;
this.transactionTemplate = transactionTemplate;
}

@Override
public FieldModel get(String field) {
// ...
}

@Override
public FieldModel getList() {
// ...
}

@Override
public Boolean add(FieldModel model) {
// ...
}

@Override
public Boolean update(FieldModel model) {
// ...
}

@Override
public Boolean delete(FieldModel model) {
// ...
}
}

TestAo Implemantation

 

 <build>
<plugins>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-amps-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<extractDependencies>false</extractDependencies>
<jvmDebugSuspend>${jvm.debug.suspend}</jvmDebugSuspend>
<instructions>
<Atlassian-Plugin-Key>${project.groupId}.${project.artifactId}</Atlassian-Plugin-Key>
<Spring-Context>*</Spring-Context>
<Export-Package>
com.test.confluence.plugins.ao.ao.*;resolution:="optional"
</Export-Package>
<Import-Package>
com.atlassian.confluence.*;resolution:="optional",
*;resolution:="optional"
</Import-Package>
</instructions>
<products>
<product>
<id>confluence</id>
<version>${confluence.version}</version>
<httpPort>${product.httpPort}</httpPort>
<contextPath>${product.contextPath}</contextPath>
</product>
</products>
</configuration>
</plugin>
...

</plugins>
</build>

Part of Test Plugin pom.xml 

 

 

Plugin Lorem

package com.lorem.confluence.plugins.macro;

@Component
public class LoremMacro implements Macro {

private final TestAo testAo;

@Autowired
public LoremMacro(@ComponentImport final TestAo testAo) {
this.testAo = testAo;
}


@Override
public BodyType getBodyType() {
return BodyType.NONE;
}


@Override
public OutputType getOutputType() {
return OutputType.INLINE;
}


@Override
public String execute(Map<String, String> parameters, String bodyContent, ConversionContext conversionContext)
throws MacroExecutionException {

Map<String, Object> data = MacroUtils.defaultVelocityContext();
FieldModel model = this.testAo.get("lorem");
data.put("lorem", model);

return VelocityUtils.getRenderedTemplate(MACRO_BODY_TEMPLATE, data);
}
}

LoremMacro with TestAoImpl

BKippelt September 22, 2017

My Result :-)

Error rendering macro 'lorem-macro' : AOP configuration seems to be invalid: tried calling method [public abstract com.test.confluence.plugins.ao.table.TestAoTable[] com.test.confluence.plugins.ao.TestAo.getList(java.lang.String)] on target [com.test.confluence.plugins.ao.TestAoImpl@462abb3]; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class

BKippelt September 22, 2017

(...)

1 vote
Daniel Wester
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 6, 2013
Since the ao tables are sandboxed so that they're isolated on a per plugin basis - you'll need to make sure the <component/> declarations declare them as public="true" and then in the second plugin you'd need to use <component-import/> to pull them in.
0 votes
Dipti Ranjan Behera
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 6, 2013

@Daniel,

how the ao tables are exposed to other plugins?

Should i expose each table entity interface separately as component.

Nadir MEZIANI
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 19, 2014

@Dipti Ranjan Behera

Add in the <component-import/> interface which is implemented by you <component/>

Suggest an answer

Log in or Sign up to answer