404 while trying to use a JIRA Scriptrunner custom REST endpoint

Copy/paste from my Stack Overflow question:


I am trying to add a custom JIRA REST endpoint with Script Runner.

The REST endpoint needs to set user properties: a list of users is provided, and for each user a list of user properties.

This is the script I have cobbled together so far:

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())

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

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

A previous (working) iteration of this script, running on another server, used email addresses, see http://stackoverflow.com/questions/36698657/how-to-get-a-user-by-email-in-jira-script-runner. But, as stated above, now I'm not getting users by email address but by username.

This is the userprops.json file I use to test:

    "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"

I test with this curl command:


curl -X POST \
  -i \
  -H "X-Atlassian-Token: nocheck" \
  -H "Content-type: text/json" \
  --data "@userprops.json" \

This is the output:

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-AUSERNAME: amedee.vangasse
Cache-Control: no-cache, no-store, no-transform
X-Content-Type-Options: nosniff

So it's not finding the REST endpoint where I should find it according to the Scriptrunner documentation.
If I use any URL that I *know* to be wrong, then I get an expected "Oops, you've found a dead link." error page. Only with the correct URL I get a 404 + no other output.

Also, when I add the doSomething sample and try to GET that, I get a 404 and a content length of 0. Doing a GET on any other wrong URL gives me a 404 AND a content length of a few KiB.

21 answers

Can you try to add a new one and click the example which is called "simple get" or something, then submit. That should give you a link "doSomething" which you can click from the browser. Can you try that so we can get a bit further. 

I updated my question.

The doSomething sample also gives me a 404 and a content length of 0.

are you using Data Center?

I am using JIRA Software.

Our hosting provider is running the JIRA server in a data center, but I don't see how the physical infrastructure is relevant? Or is "Data Center" something else?

I have enabled HTTP access log in JIRA and get these 2 lines when I curl setUserProperties: i614x41877x1 amedee.vangasse [09/sep/2016:10:14:50 +0200] "POST https://JIRA_SERVER/rest/scriptrunner/latest/custom/setUserProperties HTTP/1.0" - - - - "cirl/7.47.0" "97ojs1" i614x41877x1 amedee.vangasse [09/sep/2016:10:14:50 +0200] "POST https://JIRA_SERVER/rest/scriptrunner/latest/custom/setUserProperties HTTP/1.0" 404 0 0,0390 - "cirl/7.47.0" "97ojs1"

The same for doSomething.

"Data Center" is clustered jira, I think you would know if you were using it.

Did you check the application logs for errors?

In atlassian-jira.log I only have a WARN about X-Atlassian-Token, that the nocheck value has been deprecated since rest 3.0.0 in favor of no-check. I made that change but alas, it made no difference.

I made a small change to the script and I got this error in atlassian-jira.log.

2016-09-09 11:01:43,683 http-nio-8086-exec-23 ERROR amedee.vangasse 661x42160x1 qq01uq, /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)

I deleted my own script and only kept the doSomething demo script. I still get a 404 on https://jira.itextsupport.com/rest/scriptrunner/latest/custom/doSomethingAs long as I get a 404 there, it doesn't make sense to try and debug my own custom script.

I don't understand it. Is it possible to try to use curl to hit tomcat directly, rather than going through your reverse proxy? Is it possible it could be blocking it? Do you have definitely have the jira-administrators group?

JIRA is running on port 8086. When I ssh into the server, I get this:

curl -i http://localhost:8086/rest/scriptrunner/latest/custom/doSomething

HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
X-AREQUESTID: 810x1441x1
X-ASEN: SEN-2166625
Set-Cookie: atlassian.xsrf.token=BZJX-HAWK-8XBK-FU0I|9f21ec4c9d74d7861016f904ba91ebbaacc7ac79|lout; Path=/; Secure
X-AUSERNAME: anonymous
Cache-Control: no-cache, no-store, no-transform
X-Content-Type-Options: nosniff
Content-Type: application/json;charset=UTF-8
Content-Length: 0
Date: Fri, 09 Sep 2016 11:30:31 GMT

I definitely have the jira-administrators group.

what versions of ScriptRunner and JIRA?

JIRA 7.1.8
ScriptRunner 4.3.6

Can you check all the plugin modules are enabled? Have you tried things like restarting etc?

If you prefer create a ticket at https://productsupport.adaptavist.com/servicedesk/customer/portal/2 and we can schedule a web conf to get to the bottom of it.

Hi amedee, 

Something is missing from your curl, try

Could you please try to curl 

curl -u user:passw -i http://localhost:8086/jira/rest/scriptrunner/latest/custom/doSomething

Hi Thanos,

I get a 404 from that curl.
FYI, our JIRA doesn't run in a /jira/ directory. I tried again with  

curl -u user:passw -i http://localhost:8086/jira/rest/scriptrunner/latest/custom/doSomething

Again, 404:

HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
X-AREQUESTID: 902x526221x1
X-ASEN: SEN-2166625
Set-Cookie: JSESSIONID=D1D4107EDD4125562944B45D904801E7; Path=/; Secure; HttpOnly
X-Seraph-LoginReason: OK
Set-Cookie: atlassian.xsrf.token=BZJX-HAWK-8XBK-FU0I|d6c88fab27986dd38cef61a00e89a910dcaee394|lin; Path=/; Secure
X-AUSERNAME: amedee.vangasse
Cache-Control: no-cache, no-store, no-transform
X-Content-Type-Options: nosniff
Content-Type: application/json;charset=UTF-8
Content-Length: 0
Date: Fri, 02 Dec 2016 14:02:10 GMT

I also tried 

curl -u user:passw -i 


That also gave me a 404, but this time coming from nginx (as expected).



Hi Jamie,

I will create a ticket right away!

Hi Jamie!
I tried to create an account with my email address amedee.vangasse@itextpdf.com, but that account already exists, apparently.

I tried to get a password reset link (twice), but the email didn't arrive. Yes I checked the spam folder. 

Hi Amedee,

I deleted your previous account, please try to create a new one.

regards, Thanos

Hello Amedee Van Gasse,


do you already have a solution?

No, I do not have a solution. No time. When I have a solution, I will notify in this thread.

Suggest an answer

Log in or Sign up to answer
Community showcase
Published Nov 27, 2018 in Portfolio for Jira

Introducing a new planning experience in Portfolio for Jira (Server/DC)

In the past, Portfolio for Jira required a high degree of detail–foresight that was unrealistic for many businesses to   have–in   order to produce a reliable long-term roadmap. We're tur...

2,919 views 19 22
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you