A service that runs at regular intervals is a much wanted feature in any web application. It is more so if it is one that can be managed with user configured parameters and without having to reboot etc. JIRA offers a mechanism to add new services on to it that runs at regular intervals after every start-up. It lets us do things related to JIRA and things independent of it. It lets us integrate with third party applications. It lets us do wonders!
There are built-in services in JIRA. Export Service, POP Service etc to name a few. Here we are going to see how we can add a custom service on to JIRA
As opposed to the other JIRA plug-in modules, services don't need a plug-in descriptor. Instead it uses a configurations XML. It is typically a jar file with the related classes , files and a configuration xml.
Let us write a configuration XML to start with:
<someservice id="jtricksserviceid">
<description>My New Service</description> <properties> </properties> </someservice> This is a simple configuration XML that doesn't take any properties. It has a root element and a unique id both which can be custom names of your pick. The root element we have is someservice and id is jtricksserviceid. The description, as the name suggests, is just a short description of the service. Properties tag holds the different properties you want to associate with the service. These properties will be entered by the user while configuring the service. We will see more on that later. Now let us put the xml file under src/main/resources/com/jtricks/services. Let us now create the same package com.jtricks.services under src/main/java. The package can of-course be different but just to be in sync I am using the same. The next step is to create a Java class JTricksService. The class should extend AbstractService which implements JIRAService. Following are the only 2 mandatory methods that you need to implement:
public void run() {
System.out.println("Running the JTricks service!!"); } public ObjectConfiguration getObjectConfiguration() throws ObjectConfigurationException { return getObjectConfiguration("MYNEWSERVICE", "com/jtricks/services/myjtricksservice.xml", null); } Here run is the key method that is executed when the service runs at regular intervals. The other key, mandatory method is getObjectConfiguration(). We get the configurations from the XML we have written earlier in this method. All we need to do here is to call the parent class's getObjectConfiguration method by passing 3 things. The first argument is a unique ID (which need not be same as the id in XML file). This id is used as key while saving the configurations internally. The second argument is the path to the configuration XML file we wrote earlier. The third argument is a Map using which you can add user parameters on to the object configuration. Note: The third argument is mostly null in case of services as these user parameters are not used anywhere. It is meaningful in other places of JIRA like portlets but not in the case of services. Now you can compile these two files in to a jar and drop it under WEB-INF/classes. See here for more information on services, to see how to configure the service etc. Once it is configured, wait till the delay is over and see it in action! Let us now have a look at how to add more parameters in addition to the default delay parameter. The first things is to modify the XML file. Add the new property tags in to it. The modified file will look like this:
<someservice id="jtricksserviceid">
<description>My New Service</description> <properties> <property> <key>Tutorial</key> <name>The tutorial you like</name> <type>string</type> </property> </properties> </someservice> As you can see, a new property 'Tutorial' is added which is of type string. Now we need to modify the class to retrieve this property. In the Java class, let us add a new class variable tutorial to hold this property and initiate it in the init method.
@Override
public void init(PropertySet props) throws ObjectConfigurationException { super.init(props); if (hasProperty(TUTORIAL)) { tutorial = getProperty(TUTORIAL); } else { tutorial = "I don't like tutorials!"; } }
The init method checks if the property is configured and available and if so, assigns the value to tutorial variable.
Let us now modify the run method to print the value of the new property:
@Override
public void run() { System.out.println("Running the JTricks service!! Tutorial? " + tutorial); } The init method will be called whenever the service is configured/re-configured and the property value we enter on the JIRA Admin GUI is retrieved and stored in the class variable for use in the run method. You can also optionally override the destroy method to do anything you want before the service is removed! Now, re-build the jar and drop in under WEB-INF lib. Restart to see how the service works now. You might have noticed that the service prints "Running the JTricks service!! Tutorial? I don't like tutorials!" when it runs as the tutorial property is not configured yet. Go to the Administration > Services area, edit the service to enter a value under 'The tutorial you like' field. Assuming you entered "JTricks Tutorials", you will see the output as "Running the JTricks service!! Tutorial? JTricks Tutorials". Well, that is our first simple service. Rest is up to you to develop your complex, super efficient service! Njoy!! As usual, feel free to add your comments and download the full source below.
26 Comments
Cory S
1/31/2012 07:17:34 am
Thanks so much, this was exactly what I need to get started. The online JIRA docs don't really get into this at all.
Reply
J-Tricks
8/16/2012 10:54:36 am
Yes, indeed. I haven't tried it yet but one advantage of services I noticed is that it doesn't need a UI developed for storing delay and other attributes. JIRA already provides it.
Reply
Bastien
11/20/2012 03:32:56 am
Hey, nice tutorial :)
Reply
J-Tricks
11/20/2012 02:18:50 pm
real value of TUTORIAL is "Tutorial" (i.e. the key). You can see it in the attached code :)
Reply
Bastien
11/20/2012 07:48:15 pm
Ok, thank you. So, when you write getProperty("key_value");, you get the "name" content ?
Bastien
11/20/2012 08:16:50 pm
Ok, i found the solution. The "name" is just for the name option in the service configuration (in the jira service web interface).
Reply
J-Tricks
11/21/2012 12:59:52 am
Exactly!
Reply
Bastien
12/20/2012 03:10:59 am
Hey, it's me again :)
Reply
J-Tricks
12/20/2012 03:40:28 am
I wish. But there is no such property in JIRA now. You can find the available properties here: https://developer.atlassian.com/display/JIRADEV/Configuring+Plugins+with+Object+Configurable+Parameters
Reply
Perrik
2/24/2013 09:22:30 pm
i tried your example but it doesn't work for me, i can't find the service from jira even if i dropped the jar under WEB-INF lib.
Reply
J-Tricks
2/25/2013 01:12:16 am
Did you add the service? What do you mean by not finding it? Seeing any error when you add the service?
Reply
Perrik
2/25/2013 02:51:47 am
Yes i added the service, for me i developed a v2 plugin.
J-Tricks
2/25/2013 03:02:42 am
Sorry, what does it mean? Can you translate to English?
Perrik
2/25/2013 03:20:09 am
the error is : the class [plugin.jira.test3.JTricksService] not find,
Reply
J-Tricks
2/25/2013 03:37:01 am
Not sure what that error means. As long as the plugin has the class file in it, I don't know why you will get a class not found error.
Reply
Perrik
2/25/2013 03:58:43 am
ok thank you
Reply
Anand
9/2/2013 11:15:54 pm
Hi,
Reply
J-Tricks
9/3/2013 01:42:46 am
As mentioned in the tutorial, you can compile these two files in to a jar and drop it under WEB-INF/lib or drop it directly under WEB-INF/classes folder.
Reply
arek
3/12/2014 07:49:49 pm
How make that the run() method will be called every 1h/1 day/etc. Now ii is called every 2 min. I want to check every 2 min if pass 1 day.
Reply
J-Tricks
3/13/2014 02:33:46 am
Services can only have scheduled delays. They cannot be scheduled to run at a particular time. For services, the best you can do is to increase the interval in minutes.
Reply
Mario
10/7/2014 07:47:39 am
Hi Guys, do you know if is possible execute the services manually? I mean call the run method service from another place in Jira or another plugin?
J-Tricks
10/13/2014 10:18:56 am
Check out ServiceManager: https://docs.atlassian.com/jira/latest/com/atlassian/jira/service/ServiceManager.html.
Avi
6/25/2014 12:20:47 am
very nice explanation thanks a lot :)
Reply
Ulrich
7/21/2015 11:31:54 am
How do you inject plugin components into the service? For example my v2 plugin has a component with interface 'MyPluginComponent'. How can I inject MyPluginComponent to use myPluginComponent.doStuff() inside the service.run() method?
Reply
J-Tricks
7/22/2015 10:25:45 am
You can use
Reply
Your comment will be posted after it is approved.
Leave a Reply. |
AuthorJobin Kuruvilla - Works in Adaptavist as Head of DevOps Professional Services. Categories
All
Archives
October 2016
|