404尝试使用JIRA Scriptrunner自定义REST端点

时间:2016-09-07 13:43:48

标签: groovy jira jira-plugin jira-rest-api

我正在尝试使用Script Runner添加自定义JIRA REST端点。

REST端点需要设置用户属性:提供用户列表,并为每个用户提供用户属性列表。

这是我到目前为止拼凑的剧本:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.user.search.UserSearchService
import com.atlassian.sal.api.user.UserManager
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.transform.BaseScript

import javax.servlet.http.HttpServletRequest
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response

@BaseScript CustomEndpointDelegate delegate

setUserProperties(httpMethod: "POST", groups: ["jira-administrators"])
{ MultivaluedMap queryParams, String body, HttpServletRequest request ->

  def userPropertyManager = ComponentAccessor.getUserPropertyManager()
  def userManager = ComponentAccessor.getUserManager()
  def userSearchService = ComponentAccessor.getComponent(UserSearchService.class)

  def json = new JsonSlurper().parseText(body)
  def propertyCount = 0
  def customerList = new ArrayList<>()
  json.each {
    aCustomer ->
      def user = userManager.getUserByName(aCustomer.name.toString())
      aCustomer.properties.each {
        aProperty ->
          userPropertyManager.getPropertySet(user).setString("jira.meta." + aProperty.key.toString(), aProperty.value.toString())
          propertyCount++
      }
      customerList.add(user)
  }

  def response = new ArrayList<>()
  response.add( new JsonSlurper().parseText('{ "properties_changed": ' + propertyCount + ' }') )
  response.add( customerList )

  return Response.ok( new JsonBuilder(response).toPrettyString() ).build();
}

内联脚本编辑器抱怨这一行:def user = userManager.getUserByName(aCustomer.name.toString()),更确切地说,aCustomer.name下面有一条红色波浪线,错误是

[Static type checking] - No such property: name for class:
java.lang.object
 @ line 28, column 44.

<击>

编辑:根据@ GlennV的回答,这并不重要,可以忽略。

此脚本的先前(工作)迭代,在另一台服务器上运行,使用电子邮件地址,请参阅How to get a user by email in JIRA Script Runner。但是,如上所述,现在我不是通过电子邮件地址而是通过用户名获取用户。

这是我用来测试的userprops.json文件:

[
  {
    "name": "felicity.smoak",
    "email": "felicity.smoak@queenconsolidated.com",
    "properties": {
      "Company": "Queen Consolidated",
      "Foo": "bar"
    }
  },
  {
    "name": "johnny.cash",
    "email": "johnny.cash@nashville.com",
    "properties": {
      "Company": "Nashville",
      "Nickname": "The Man In Black"
    }
  }
]

我使用这个curl命令进行测试:

curl -X POST \
    -i \
    -H "X-Atlassian-Token: nocheck" \
    -H "Content-type: text/json" \
    --data "@userprops.json" \
    -u "$JIRA_USER":"$JIRA_PASSWORD" \
    http://"$JIRA_SERVER"/rest/scriptrunner/latest/custom/setUserProperties

$JIRA_USER$JIRA_PASSWORD$JIRA_SERVER只是我用来为Stack Overflow匿名化的占位符。实际值是正确的。

这是输出:

HTTP/1.1 404 Not Found
Server: nginx
Date: Wed, 07 Sep 2016 14:55:38 GMT
Content-Type: application/json;charset=UTF-8
Content-Length: 0
Connection: keep-alive
X-AREQUESTID: 0123456789
X-ASEN: SEN-123456789
Set-Cookie: JSESSIONID=1A2B3C4D5E6F1A2B3C4D5E6F1A2B3C4D5E6F; Path=/; Secure; HttpOnly
X-Seraph-LoginReason: OK
Set-Cookie: atlassian.xsrf.token=ABCD-EFGH-IJKL-MNOP|abcdef0123456789abcdef0123456789abcdef0123456789|lin; Path=/; Secure
X-ASESSIONID: xyz123
X-AUSERNAME: amedee.vangasse
Cache-Control: no-cache, no-store, no-transform
X-Content-Type-Options: nosniff

所以我找不到根据Scriptrunner documentation找到它的REST端点。

如果我使用任何我知道的网址是错误的,那么我会得到一个预期的“哎呀,你找到了一个死链接。”错误页面。只有使用正确的URL我才能得到404 +没有其他输出。

此外,当我添加doSomething示例并尝试获取它时,我得到404和内容长度为0.对任何其他错误的URL执行GET会得到404和内容长度为很少KiB。

-Dplugin.script.roots=参数未在setenv.sh中定义,也不是,因为脚本是内联的。只有文件系统上的脚本才需要设置脚本根,并且仅适用于默认scripts目录之外的脚本,如Scriptrunner documentation中所述。

还在Atlassian Answers上询问。

编辑:我按照Glenn的建议将customerList.add(user)向下移了一行,我在atlassian-jira.log中收到了此错误:

2016-09-09 11:01:43,683 http-nio-8086-exec-23 ERROR amedee.vangasse 661x42160x1 qq01uq 213.224.9.178,127.0.0.1 /rest/scriptrunner/latest/custom/customadmin/com.onresolve.scriptrunner.canned.common.rest.CustomRestEndpoint [c.a.p.r.c.error.jersey.ThrowableExceptionMapper] Uncaught exception thrown by REST service: Cannot get property 'name' on null object
java.lang.NullPointerException: Cannot get property 'name' on null object
        at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:60)
        at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:172)
        at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:47)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296)
        at com.onresolve.scriptrunner.runner.RestEndpointManager$_onFullSystemStart_closure5.doCall(RestEndpointManager.groovy:141)
        ... 3 filtered
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
        at groovy.lang.Closure.call(Closure.java:426)
        at groovy.lang.Closure.call(Closure.java:442)
        at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2030)
        at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2015)
        at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2056)
        at org.codehaus.groovy.runtime.dgm$162.invoke(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:274)
        at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
        at com.onresolve.scriptrunner.runner.RestEndpointManager.onFullSystemStart(RestEndpointManager.groovy:131)
        at com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint.refresh(UserCustomScriptEndpoint.groovy:364)
        at com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint.saveConfiguredItems(UserCustomScriptEndpoint.groovy:359)
        at com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint.addListener(UserCustomScriptEndpoint.groovy:127)
        ... 3 filtered
        at java.lang.reflect.Method.invoke(Method.java:497)
        at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
        ... 13 filtered
        at com.atlassian.plugins.rest.module.RestDelegatingServletFilter$JerseyOsgiServletContainer.doFilter(RestDelegatingServletFilter.java:154)
        ... 1 filtered
        at com.atlassian.plugins.rest.module.RestDelegatingServletFilter.doFilter(RestDelegatingServletFilter.java:68)
        ... 86 filtered
        at com.atlassian.jira.security.JiraSecurityFilter.doFilter(JiraSecurityFilter.java:70)
        ... 16 filtered
        at com.atlassian.plugins.rest.module.servlet.RestSeraphFilter.doFilter(RestSeraphFilter.java:37)
        ... 73 filtered
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)

这也不是nginx代理的问题,因为当我进入服务器并在localhost上curl时,我得到相同的404。

1 个答案:

答案 0 :(得分:2)

Script Runner使用Groovy的CompileStatic提供有关编译错误的提示。当有足够的类型信息时,这可以正常工作。

在上面的代码中,您的 json 实例不包含有关其包含的元素的任何类型信息,因此Groovy(在编译时)不知道 aCustomer 实例有一个名称字段,因此它会对此发出警告。但是,您的代码没有任何问题,因此如果您向REST资源发送请求,它应该可以正常工作。

如果您的请求返回的状态代码不是2xx,则可能还有其他错误。

关于404.这意味着 Not Found ,因此您发送请求的URL中存在错误,或者您的REST脚本无法正确用于Script Runner。我会先检查$ JIRA_SERVER的值。如果您将其粘贴到浏览器中,则应正确加载JIRA。如果可以,那么我将检查Script Runner是否知道需要查找脚本的路径。是否在setenv.sh(或setenv.bat)中定义了 -Dplugin.script.roots = 参数?有关此内容的更多详细信息,请here