Hi all!
I am developing a plugin and I have the next problem:
- I retrieving from a user a JQL string like this: "project = DEMO"
- then I want to retrieve JSON with issues, but I can retrieve only List<Issue>
example:
String query = "project = DEMO";
Query conditionQuery = jqlQueryParser.parseQuery(query);
ApplicationUser searcher = jiraAuthenticationContext.getUser();
SearchResults results = searchService.search(searcher, conditionQuery, PagerFilter.getUnlimitedFilter());
List<Issue> issues = results.getIssues();
Object SearchResult is similar to JSON, retrieving from the link:
http://localhost:2990/jira/rest/api/2/search?jql=project+%3D+DEMO
This JSON is what I need. But I can’t understand how I can get it. Maybe somebody can give me advice - how to convert SearchResult to JSON, or maybe there is another way to get the JSON I need?
A wild banana appears!
Hi @Oleksii Skachkov
First note that the structure behind a server / data center is not the same that the one used in cloud, so probably the best approach is to work with Java classes provided on Server / Data Center apps, and develop a different application using rest services on cloud.
Saying that, if you need to use the issue JSON representation provided by Jira REST API itself, why don't simply make an http request to the endpoint and grab the data you need?
You can use the TrustedRequestFactory provided on SAL API (Shared Layer Access) to make http request using current user authorization token, in that way you don't need to know the user password at all.
Here is a quick example I did some time ago using groovy to call the Zephyr REST API within my Jira instance
/*
* @autor avillalobos
*
* To be use as a Script Listener for ProjectCreatedEvent
* Creates some test cycles by default when the project is created on behalf of a user who created the project
*
* Dependencies:
* - SAL-API >= 3.0
* - Zephyr add-on
* - ZAPI add-on
*/
package com.atsistemas.groovy
import com.atlassian.jira.project.Project
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.config.properties.APKeys
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.sal.api.net.Request.MethodType
import com.atlassian.sal.api.net.TrustedRequestFactory
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import groovy.json.JsonOutput
import groovyx.net.http.URIBuilder
import groovyx.net.http.ContentType
// Zephyr test cycles creation
[
"Aceptacion",
"Sistema",
"Rendimiento",
"Seguridad"
].each{ cycleName ->
createCycle(cycleName, getProject().id)
}
/*
* Returns the base URL of this Jira instance
*/
String getBaseUrl()
{
return ComponentAccessor.applicationProperties.getString(APKeys.JIRA_BASEURL)
}
/*
* Returns the target project where test cycles will be created
* Formely, returns the project which generated this event
*/
Project getProject()
{
return event.project
}
/*
* Returns the user who will create the test cycles
* Formely, returns the user which generated this event
*/
ApplicationUser getAuthor()
{
return event.user
}
/*
* Returns the minimal payload needed to create a new Zehyr Test Cycle.
* See: https://getzephyr.docs.apiary.io/#reference/cycleresource/create-new-cycle/create-new-cycle
*/
String getCyclePayload(String cycleName, Long projectId)
{
return JsonOutput.toJson([
name: cycleName,
projectId: projectId,
versionId: "-1"
])
}
/*
* Create a Zephyr Test Cycle with the given name.
*/
void createCycle(String cicleName, Long projectId)
{
//Get the base URL of our instance
def baseUrl = getBaseUrl()
def host = new URIBuilder(baseUrl).host
//Create the request, including the method type and REST Endpoint we would like to call
def requestFactory = ScriptRunnerImpl.getOsgiService(TrustedRequestFactory)
def request = requestFactory.createTrustedRequest(MethodType.POST, "${baseUrl}/rest/zapi/latest/cycle")
//Add the username of the user we would like to authenticate with
request.addTrustedTokenAuthentication(host, getAuthor().username)
//Add the data to the request and specify the type of data being passed
request.setRequestBody(getCyclePayload(cicleName, projectId))
request.setHeader("Content-Type", ContentType.JSON.toString())
try {
def response = request.execute()
log.info "New Zephyr cycle created '${cicleName}'...."
log.debug response
} catch(e){
log.error "Failed to created '${cicleName}'...."
log.error e.message
}
}
Hope this help.
Regards
@Jack Nolddor [Sweet Bananas]Thanks for coming to my rescue! ;D
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You're welcome :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, @Jack Nolddor [Sweet Bananas]
Thanks for your help.
I am not familiar with groovy, but the general meaning is clear. Before trying to approach from my first question, I started from http reqest. And the general problem was how to get and use user authorization token. My working code:
private HttpResponse<JsonNode> getResponce(String url) throws UnirestException {
return Unirest.get(url)
.basicAuth("admin", "admin") //TODO change auth method
.header("Accept", "application/json")
.asJson();
}
I cannot use it that way, and I need to change the basic authorization to use an authorization token. No matter which library to use. Can you give an example?
I tried using TrustedRequestFactory from your example, but this factory is no longer available.
Also, I found that Jira Server cant generate REST API token, it can use only Basic and OAuth: https://jira.atlassian.com/browse/JRASERVER-67869?_ga=2.241339585.254191367.1589777640-1416201942.1578820105
Can you direct me - on which side to look for a solution to Java?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
There is no way to use externals httpClients to call Jira itself if you want to avoid to hardcode user credentials. My code it a bit outdated since it worked on Jira 7, probably on Jira 8 you must use ApplicationLink#createAuthenticatedRequestFactory() or ApplicationLink#createImpersonatingAuthenticatedRequestFactory() methods.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, @Jack Nolddor [Sweet Bananas]
Thanks for your help.
I tried to use AuthenticatedRequestFactory and AuthenticatedRequestFactory, but I did not succeed. And I decided to try on the other side. I founded how to convert JSON to SearchResult. I hope that there is a functionality that does the reverse work.
I didn't find it yet, but maybe you know about it?
Regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
No idea to be honest, I've never used the json format I've always used Java beans such us MutableIssue, Project, ...
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Oleksii Skachkov ,
I'm not sure if this could be of any help:
https://stackoverflow.com/questions/14228912/how-to-convert-list-to-json-in-java
By the way, may you elaborate on why do you need to generate a JSON? I mean, is that the goal? Or is it just a way to access issue data in a way you are more comfortable with?
Regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, @Ignacio Pulgar.
Thanks for your help.
The solution you proposed does not work. The Issue consists of other objects that also refer to the Issue. Therefore, when converting to JSON, we get recursion and Stackoverflow.
Now I'm trying to solve the issue through a chain of objects: BeanBuilderFactory -> IssueBeanFactory -> IssueBean -> SearchResultsBean to make JSON from SearchResultsBean. But I am stuck on injection BeanBuilderFactory and IssueBeanFactory. Maybe you can help with it?
My plugin should work with the Server and with the Cloud. I want to write logic only once. It would be great to get the data for calculations in the same form both from the Server and from Cloud. In addition, it will be more convenient for me to process it with a JSON.
Regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Interesting goal! This seems to be a question where @Jack Nolddor [Sweet Bananas] (the best developer of Atlassian apps I know) may help! :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hey! What an incredible summoning!
May I join the party? 🎉💙
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Of course! You are always welcome! :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.