Problem: Add created date and updated date states to Jira project entity, which is not present in Jira OOB.
This problem is addressed here by implementing Active Objects.
1. Download "activeobjects-plugin-0.15.4.jar" from https://repository.atlassian.com/com.atlassian.activeobjects/jars/.
2. Download "activeobjects-jira43-spi-0.15.4.jar" from https://repository.atlassian.com/com.atlassian.activeobjects/jars/.
Note: This plugin jar needs to be compatible with the Jira version. Here, this is compatible with Jira 4.3.3 version.
Deploy the above mentioned artifacts in the JIRA_HOME/plugins/installed-plugins folder.
3. Import "Active Objects" component into your plugin. This is done by incorporating following snippet in the atlassian-plugin.xml file.
<component-import key="ao" name="Active Objects service" interface="com.atlassian.activeobjects.external.ActiveObjects">
<description>Component to access Active Objects functionality from the plugin</description></component-import>
Note: Make sure to give component-import key as a two letter word.
4. Add the Transaction component in the plugin xml.
<component key="tx-processor" name="Transactional Annotation Processor"
class="com.atlassian.activeobjects.external.TransactionalAnnotationProcessor">
<decription>Processes @Transactional annotations.</decription>
</component>
By finishing the above mentioned steps, it's good to go with adding the tables to Jira database.
5. We are adding the new states to default jira project entity by a new table. Create a table "Project_Ext" using active objects.
package ao.entity;
import java.sql.Timestamp;
import net.java.ao.Entity;
/**
*
* @author sateesh
*
*/
public interface ProjectExt extends Entity {
long getProjectId();
void setProjectId(long projectId);
Timestamp getCreatedDate();
void setCreatedDate(Timestamp createdDate);
Timestamp getLastUpdatedDate();
void setLastUpdatedDate(Timestamp lastUpdatedDate);
public static final String PROJECT_ID = "PROJECT_ID";
}
Also, add the below entry into atlassian-plugin.xml file
<ao key="ao-module">
<description>The module configuring the Active Objects service used by this plugin</description>
<entity>com.company.application.ao.entity.ProjectExt</entity>
</ao>
6. Create a boot-strap service to migrate the custom tables (which are created using active objects). Below is are the two classes required to add to achieve this.
(i) BootStrapService
import com.atlassian.jira.extension.Startable;
/**
*
* The class implementing BootStrapService interface is notified when the JIRA application has started.
* The start() method would be called after the plug-in system is initialized
* and components added to the dependency injection framework,
* To be able to make it actually Startable, plug-in modules of type Component need to be created for it.
*
* @author sateesh
*
*/
public interface BootStrapService extends Startable {
public static final String PLUGIN_KEY = "xxxxxxxxx";
public void initialize();
}
(ii) BootStrapServiceImpl
/**
* Implementation of the Velocity Startable service.
* It would be used to initialize the objects used by velocity platform.
* e.g. - Manager classes, Cache, Listeners etc.
* @author priyanka.jain & sateesh.b
*
*/
public class BootStrapServiceImpl implements BootStrapService{
private final Logger logger = Logger.getLogger(BootStrapServiceImpl.class);
private ActiveObjects activeObject;
/**
* Adding the dependency of active object
*
*/
public BootStrapServiceImpl (ActiveObjects activeObject) {
this.activeObject = activeObject;
}
public void initialize() {
logger.info("Initializing the My App Platform.");
this.activeObject.migrate(ProjectExt.class);
}
public void start() throws Exception {
try {
initialize();
} catch (ApplicationException e) {
logger.error(e);
}
}
}
7. Add bootstrap service entries in the plugin-xml
<component key="my-bootstrap-service" name="App Bootstrap Service" class="com.company.application.BootStrapServiceImpl " public="true">
<interface>com.company.application.BootStrapService</interface>
</component>
By doing this, ProjectExt table will be created in Jira database as "ao_e523d0_project_ext"
Here "ao" is the key mentioned in the atlassian-plugin.xml file for the active objects component, "e523d0" is the hash key for the plugin artifact and "project_ext" is the name of the entity class mentioned in the plugin artifact.
By implementing above mentioned steps, one can add new tables in Jira database using Active Objects. Now, let's focus on how to do crud operation on the tables using Active Objects.
8. Create ProjectExtService which will do crud operations on ProjectExt table.
(i) Add a value object class (wrapper class) for additional states of Jira project entity.
import java.sql.Timestamp;
/**
* @author sateesh.b
*
*/
public class ProjectExtVO {
private long id;
private Timestamp createdDate;
private Timestamp updatedDate;
public long getId() {
return this.id;
}
public void setId(final long id) {
this.id = id;
}
public Timestamp getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Timestamp createdDate) {
this.createdDate = createdDate;
}
public Timestamp getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(Timestamp updatedDate) {
this.updatedDate = updatedDate;
}
}
(ii) Add an interface ProjectExtService
/**
* Service for adding/updating/deleting project extension information
* @author sateesh.b
*
*/
public interface ProjectExtService{
/**
* This method adds a new entry into the table
* and takes input argument as {@link ProjectExtVO} and persists the data
* @param projectExt
* @return
*/
public void add(ProjectExtVO projectExt);
/**
* this method updates existing entry in the table
* and takes input argument as {@link ProjectExtVO} and persists the data
* @param projectExt projectExt
* @return
*/
public void update(ProjectExtVO projectExt);
/**
* this method returns the project configuration information for a
* given velocity project id
*
* @param pId
* @return
*/
public ProjectExtVO find(Long pId);
/**
* this method returns the list of project configuration information
* @return
*/
public List<ProjectExt> find();
/** this method returns the list of project configurations for a given last updated date
* @param lastUpdatedDate
* @return
*/
public List<ProjectExt> find(Timestamp lastUpdatedDate);
/**
* this method deletes the existing entry in the table
* and takes input argument as long
* @param id projectId
* @return
*/
public void delete(long id);
}
(iii) Add implementation class ProjectExtServiceImpl
/**
* @author sateesh.b
*
*/
public class ProjectExtServiceImpl implements ProjectExtService{
private final ActiveObjects activeObject;
public ProjectExtServiceImpl (ActiveObjects activeObject) {
this.activeObject = activeObject;
}
@Override
public void add(ProjectExtVO projectExt) {
DBParam dbParam = new DBParam("PROJECT_ID", Long.valueOf(projectExt.getId()));
final ProjectExt project = this.activeObject.create(ProjectExt.class, dbParam);
project.setCreatedDate(projectExt.getCreatedDate());
project.setUpdatedDate(projectExt.setUpdatedDate());
project.save();
}
@Override
public void update(ProjectExtVO projectExt) {
final ProjectExt[] projects = this.activeObject.find(ProjectExt.class,
Query.select().where("PROJECT_ID = ?", projectExt.getId()));
final ProjectExt project = projects[0];
final ProjectExtVO projectExtension = getProjectExt(project);
project.setUpdatedDate(projectExt.setUpdatedDate());
project.save();
}
@Override
public ProjectExtVO find(Long id) {
final ProjectExt[] projects = this.activeObject.find(ProjectExt.class,
Query.select().where("PROJECT_ID = ?", id));
ProjectExtVO projectConfig = null;
if (projects.length > 0) {
final ProjectExt project = projects[0];
if (null != project) {
projectConfig = new ProjectExtVO();
projectConfig.setId(project.getProjectId());
projectConfig.setCreatedDate(project.getCreatedDate());
projectConfig.setUpdatedDate(project.getUpdatedDate());
}
}
return projectConfig;
}
@Override
public void delete(long id) {
final ProjectExt[] projects = this.activeObject.find(ProjectExt.class,
Query.select().where("PROJECT_ID = ?", id));
if (projects.length > 0) {
final ProjectExt project = projects[0];
this.activeObject.delete(project);
}
}
Above mentioned 3 java classes would help to do CRUD operation on ProjectExt table which is created in step-5
9. Add the ProjectExtService entries in the atlassian-plugin.xml file.
<component key="project-ext-service" name="Project Service" class="com.company.appliation.ao.service.ProjectExtServiceImpl" public="true">
<interface>com.company.appliation.ao.service.ProjectExtService</interface>
</component>
This comment has been removed by the author.
ReplyDeleteIf you observe my post (at step:3), I am importing ActiveObjects class into jira plugin.
ReplyDeleteOnce it's added to your plugin, we are just adding the dependency using constructor as you mentioned in comment.
Also @ step-9, I have mentioned ProjectExtService as a component. So, where ever you require to get this component, you just needs to include as a input argument in any class constructor.
ReplyDeleteHope, my post answers you.
Can we see All code of this plugin? may be on github or any else?
ReplyDelete