我正在尝试使用 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": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2741424b4e444e535e09544a48464c67565242424944484954484b4e43465342430944484a" rel="noreferrer noopener nofollow">[email protected]</a>",
"properties": {
"Company": "Queen Consolidated",
"Foo": "bar"
}
},
{
"name": "johnny.cash",
"email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="670d080f09091e490406140f270906140f110e0b0b024904080a" rel="noreferrer noopener nofollow">[email protected]</a>",
"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
示例并尝试 GET 时,我得到了 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 代理的问题,因为当我 ssh 进入服务器和本地主机上的 curl
时,我得到相同的 404。
最佳答案
Script Runner 使用 Groovy 的 CompileStatic提供有关编译错误的提示。当有足够的类型信息可用时,这可以正常工作。
但是,在上面的代码中,您的 json 实例不包含有关其所包含元素的任何类型信息,因此 Groovy(在编译时)不知道 aCustomer> 实例有一个 name 字段,因此它会发出警告。不过,您的代码没有任何问题,因此如果您向 REST 资源发送请求,它应该可以正常工作。
如果您的请求返回 2xx 以外的状态代码,则可能存在其他问题。
关于 404。这意味着未找到,因此要么您发送请求的 URL 存在错误,要么您的 REST 脚本无法正确供 Script Runner 使用。我会首先检查 $JIRA_SERVER 的值。如果将其粘贴到浏览器中,它应该正确加载 JIRA。如果没问题,那么我会检查 Script Runner 是否知道它需要查找脚本的路径。 -Dplugin.script.roots= 参数是否在 setenv.sh (或 setenv.bat)中定义?有关此内容的更多详细信息,请访问 here .
关于groovy - 尝试使用 JIRA Scriptrunner 自定义 REST 端点时出现 404,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39371582/