📜 ⬆️ ⬇️

Developing a simple plugin for JIRA to work with a database

The plugin will be a tab in the administrative part of the project, through which we will work with the database.

The plugin will do for gira 4.4.4. First, create an empty project. You can create a project using the Atlassian SDK and then open it in your favorite IDE. In this case, I will work with Netbeans. The file structure of the project will look like this:


Let's create a page on which our functionality will be located. There are several mechanisms for creating pages — report , webwork actions , servlet — in order to solve this problem, choose webwork actions. At the time of acquaintance with JIRA, everything in this mechanism was extremely simple, clear and familiar (in fact, this is the same Apache Struts). Create a new class, MyAction.java, inherited from the JiraWebActionSupport class. And create a velocity that succeess.vm pattern with this content:
')
MyAction template 

Now it remains to add the following element in atlassian-plugin.xml to create a new page:

 <webwork1 key="actions" name="MyActions"> <actions> <action name="com.edsd.jira.plugins.simpleplugin.action.MyAction" alias="action" roles-required="admin"> <view name="success">/myaction/success.vm</view> </action> </actions> </webwork1> 

And when clicking on the link http: //myserver/secure/action.jspa, we will see the page we created:



Now we will make this page become the same as the tab in the admin part of the project.
First we make the link itself:



To make the link look like a separate group, add a new section ( web-section ) to atlassian-plugin.xml. Then in this section we will add the link itself ( web-item ):

 <web-section key="my_section" name="MySection" location="atl.jira.proj.config" weight="50"/> <web-item key="my_item_link" name="MyTab" section="atl.jira.proj.config/my_section" weight="10"> <label key="MyLink" /> <link linkId="my_item_link">/secure/action.jspa</link> </web-item> 

But when clicking on a link, we will still receive a page without a design, in order to fix this we will make changes to MyAction.java. In fact, when you click the http: //myserver/secure/action.jspa link , the execute () method is called and the return value is the success, so we described our action in atlassian-plugin.xml. So we will explicitly transfer which project is currently active, and add the project header to the tab.

 public class MyAction extends JiraWebActionSupport { private Project project; @Override public String execute() throws Exception { project = getSelectedProjectObject(); //     request.setAttribute("com.atlassian.jira.projectconfig.util.ServletRequestProjectConfigRequestCache:project", project); return super.execute(); } } 

But this way only html code without css is transmitted. To add css to the page we will add in atlassian-plugin.xml

 <web-resource key="my-resources"> <dependency>com.atlassian.jira.jira-project-config-plugin:project-config-global</dependency> <context>my-resources</context> </web-resource> 

Here we added dependency dependency for the resources themselves and declared through the context how we can access these resources through the manager.
Then the velocity pattern is as follows:

 <!DOCTYPE HTML> <html> <head> <title>MyTestPage</title> <meta name="decorator" content="atl.admin"/> <meta name="projectKey" content="$project.getKey()"/> <meta name="projectId" content="$project.getId()"/> <meta name="admin.active.tab" content="my_item_link"/> <meta name="admin.active.section" content="atl.jira.proj.config"/> $webResourceManager.requireResourcesForContext("my-resources") </head> <body> MyAction template </body> </html> 

As a result, we get the page:



Add the functionality of working with the database. We will use Active Objects (further AO). First, create a logic package. We will describe an object with which we will work in it, let it be an elementary Student:

 public interface Student { public void setName(String name); public String getName(); } 

In the entity package, we describe our interface-entity, which we will store in the database. For example, let the database still store the creation time of this record:

 import java.util.Date; import net.java.ao.Entity; public interface StudentEntity extends Entity, Student { public Date getCreated(); public void setCreated(Date created); } 

Now add our AO to atlassian-plugin.xml:

 <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> <ao key="ao-module"> <entity>com.edsd.jira.plugins.simpleplugin.entity.StudentEntity</entity> </ao> 

You can read more about connecting AO to the plugin here .

Now let's deal with the interaction of our application with the database. Define the StudentDAO interface from the DAO package, containing a set of necessary methods:

 public interface StudentDAO { public StudentEntity addStudent(Student student) throws Exception; public StudentEntity[] getStudents() throws Exception; }      DAO.Impl   StudentDAOImpl. public class StudentDAOImpl implements StudentDAO { private final ActiveObjects ao; public StudentDAOImpl(ActiveObjects ao) { this.ao = ao; } @Override public StudentEntity addStudent(final Student student) throws Exception { return ao.executeInTransaction(new TransactionCallback<StudentEntity>() { @Override public StudentEntity doInTransaction() { StudentEntity entity = ao.create(StudentEntity.class); entity.setName(student.getName()); entity.setCreated(new Date(System.currentTimeMillis())); entity.save(); return entity; } }); } @Override public StudentEntity[] getStudents() throws Exception { return ao.executeInTransaction(new TransactionCallback<StudentEntity[]>() { @Override public StudentEntity[] doInTransaction() { return ao.find(StudentEntity.class); } }); } } 

Now we will create the DAOFactory class in the DAO package, to which we will turn for our DAO implementations, from which we will call the methods we need:

 public class DAOFactory { private static StudentDAO studentDAO = null; private static DAOFactory instance = null; private static ActiveObjects ao; public DAOFactory(ActiveObjects ao) { DAOFactory.ao = ao; } public static synchronized DAOFactory getInstance() { if (instance == null) { instance = new DAOFactory(ao); } return instance; } public StudentDAO getStudentDAO() { if (studentDAO == null) { studentDAO = new StudentDAOImpl(ao); } return studentDAO; } } 

Add in our atlasian-plugin.xml DAOFactory. This is necessary to avoid problems with accessing AO. Who cares: reasoning on the topic of Active Objects injection .

  <component key="dao-factory" class="com.edsd.jira.plugins.simpleplugin.DAO.DAOFactory"> </component> 

Actually, we have described and implemented everything that is necessary for working with the database, it now remains to add functionality to MyAction:

 public class MyAction extends JiraWebActionSupport { private Project project; private StudentEntity[] students; @Override public String execute() throws Exception { project = getSelectedProjectObject(); request.setAttribute("com.atlassian.jira.projectconfig.util.ServletRequestProjectConfigRequestCache:project", project); students = DAOFactory.getInstance().getStudentDAO().getStudents(); return super.execute(); } public String doAdd() throws Exception { String name = request.getParameterValues("name")[0]; Student student = new StudentImpl(name); DAOFactory.getInstance().getStudentDAO().addStudent(student); ServletActionContext.getResponse().sendRedirect("/secure/action.jspa"); return NONE; } } 

And in the velocity template, bring the body tag to this view:

 <body> <form action="/secure/action!add.jspa"> <input type="text" name="name"/> <input type="submit" value="OK"/> </form> <table> <thead> <th>id</th> <th>name</th> <th>created</th> </thead> <tbody> #foreach($student in $students) <tr> <td>$student.getID()</td> <td>$student.getName()</td> <td>$student.getCreated()</td> </tr> #end </tbody> </table> </body> 

In general, we launch, we test, we receive:



On this for the first time everything, in the next article I will tell:


All plugin code on github

Continued: we give our plugin a normal appearance .



More projects:
How to create software for a microtomograph for 5233 man-hours
SDK for the introduction of support for e-books in FB2 format
Control access to electronic documents. From DefView to Vivaldi
Integrating two video surveillance systems: Axxon Next and SureView
Read more about the development of x-ray tomograph software
Sphere: how to monitor billions of kilowatt-hours
Developing a simple plugin for JIRA to work with a database
To help DevOps: a firmware builder for network devices on Debian for 1008 hours
Windows Service Auto Update for Poor AWS

Source: https://habr.com/ru/post/256789/


All Articles