JenkinsInstance getItemByFullName(jobName, Job.class) always return null

Jenkins setup:

Jenkins: 2.440.3
OS: Linux - 3.10.0-1160.el7.x86_64
Java: 17.0.11 - Eclipse Adoptium (OpenJDK 64-Bit Server VM)
---
ace-editor:1.1
alauda-devops-credentials-provider:v3.17.0-fix.311.5.g47b23b79-feat-upgrade-jenkins-2.440.3
alauda-devops-pipeline:v3.17.0-fix.311.5.g47b23b79-feat-upgrade-jenkins-2.440.3
alauda-devops-sync:v3.17.0-fix.311.5.g47b23b79-feat-upgrade-jenkins-2.440.3
alauda-kubernetes-support:v3.17.0-fix.311.5.g47b23b79-feat-upgrade-jenkins-2.440.3
antisamy-markup-formatter:162.v0e6ec0fcfcf6
apache-httpcomponents-client-4-api:4.5.14-208.v438351942757
asm-api:9.7-33.v4d23ef79fcc8
authentication-tokens:1.53.v1c90fd9191a_b_
badge:1.9.1
bitbucket:241.v6d24a_57f9359
blueocean:1.27.12
blueocean-autofavorite:1.2.5
blueocean-bitbucket-pipeline:1.27.12
blueocean-commons:1.27.12
blueocean-config:1.27.12
blueocean-core-js:1.27.12
blueocean-dashboard:1.27.12
blueocean-display-url:2.4.2
blueocean-events:1.27.12
blueocean-git-pipeline:1.27.12
blueocean-github-pipeline:1.27.12
blueocean-i18n:1.27.12
blueocean-jira:1.27.12
blueocean-jwt:1.27.12
blueocean-personalization:1.27.12
blueocean-pipeline-api-impl:1.27.12
blueocean-pipeline-editor:1.27.12
blueocean-pipeline-scm-api:1.27.12
blueocean-rest:1.27.12
blueocean-rest-impl:1.27.12
blueocean-web:1.27.12
bootstrap4-api:4.6.0-6
bootstrap5-api:5.3.3-1
bouncycastle-api:2.30.1.77-225.v26ea_c9455fd9
branch-api:2.1169.va_f810c56e895
caffeine-api:3.1.8-133.v17b_1ff2e0599
checks-api:2.2.0
cloudbees-bitbucket-branch-source:886.v44cf5e4ecec5
cloudbees-disk-usage-simple:203.v3f46a_7462b_1a_
cloudbees-folder:6.901.vb_4c7a_da_75da_3
command-launcher:107.v773860566e2e
commons-lang3-api:3.13.0-62.v7d18e55f51e2
commons-text-api:1.11.0-109.vfe16c66636eb_
configuration-as-code:1775.v810dc950b_514
copyartifact:722.v0662a_9b_e22a_c
credentials:1337.v60b_d7b_c7b_c9f
credentials-binding:677.vdc9d38cb_254d
data-tables-api:2.0.6-1
display-url-api:2.204.vf6fddd8a_8b_e9
docker-commons:439.va_3cb_0a_6a_fb_29
docker-workflow:572.v950f58993843
durable-task:555.v6802fe0f0b_82
echarts-api:5.5.0-1
favorite:2.208.v91d65b_7792a_c
font-awesome-api:6.5.2-1
git:5.2.2
git-client:4.7.0
git-server:117.veb_68868fa_027
gitea:1.4.7
gitee:1170.v3d4640b_34233
github:1.38.0
github-api:1.318-461.v7a_c09c9fa_d63
github-branch-source:1789.v5b_0c0cea_18c3
gitlab-api:5.3.0-91.v1f9a_fda_d654f
gitlab-branch-source:704.vc7f1202d7e14
google-oauth-plugin:1.330.vf5e86021cb_ec
gson-api:2.10.1-15.v0d99f670e0a_7
handlebars:3.0.8
handy-uri-templates-2-api:2.1.8-30.v7e777411b_148
htmlpublisher:1.33
http_request:1.18
ignore-committer-strategy:1.0.4
instance-identity:185.v303dc7c645f9
ionicons-api:73.vb_f522f227457
jackson2-api:2.17.0-379.v02de8ec9f64c
jakarta-activation-api:2.1.3-1
jakarta-mail-api:2.1.3-1
javax-activation-api:1.2.0-6
javax-mail-api:1.6.2-9
jaxb:2.3.9-1
jdk-tool:73.vddf737284550
jenkins-design-language:1.27.12
jersey2-api:2.42-147.va_28a_44603b_d5
jira:3.13
jjwt-api:0.11.5-112.ve82dfb_224b_a_d
joda-time-api:2.12.7-29.v5a_b_e3a_82269a_
jquery-detached:1.2.1
jquery3-api:3.7.1-2
jsch:0.2.16-86.v42e010d9484b_
json-api:20240303-41.v94e11e6de726
json-path-api:2.9.0-58.v62e3e85b_a_655
junit:1265.v65b_14fa_f12f0
kubernetes:4214.vf10083a_42e70
kubernetes-client-api:6.10.0-240.v57880ce8b_0b_2
kubernetes-credentials:0.11
label-linked-jobs:6.0.1
localization-support:1.2
localization-zh-cn:371.v23851f835d6b_
lockable-resources:1255.vf48745da_35d0
mailer:472.vf7c289a_4b_420
mapdb-api:1.0.9-40.v58107308b_7a_7
matrix-auth:3.2.2
matrix-project:822.824.v14451b_c0fd42
mercurial:1260.vdfb_723cdcc81
metrics:4.2.21-449.v6960d7c54c69
mina-sshd-api-common:2.12.1-101.v85b_e08b_780dd
mina-sshd-api-core:2.12.1-101.v85b_e08b_780dd
momentjs:1.1.1
oauth-credentials:0.646.v02b_66dc03d2e
oic-auth:4.257.v5360e8489e8b_
okhttp-api:4.11.0-172.vda_da_1feeb_c6e
pipeline-build-step:540.vb_e8849e1a_b_d8
pipeline-graph-analysis:216.vfd8b_ece330ca_
pipeline-groovy-lib:704.vc58b_8890a_384
pipeline-input-step:495.ve9c153f6067b_
pipeline-milestone-step:119.vdfdc43fc3b_9a_
pipeline-model-api:2.2198.v41dd8ef6dd56
pipeline-model-definition:2.2198.v41dd8ef6dd56
pipeline-model-extensions:2.2198.v41dd8ef6dd56
pipeline-rest-api:2.34
pipeline-stage-step:312.v8cd10304c27a_
pipeline-stage-tags-metadata:2.2198.v41dd8ef6dd56
pipeline-stage-view:2.34
pipeline-utility-steps:2.16.2
plain-credentials:179.vc5cb_98f6db_38
plugin-util-api:4.1.0
popper-api:1.16.1-3
popper2-api:2.11.6-4
prism-api:1.29.0-15
prometheus:763.vf8c26b_a_34b_d6
pubsub-light:1.18
resource-disposer:0.23
scm-api:690.vfc8b_54395023
script-security:1336.vf33a_a_9863911
snakeyaml-api:2.2-111.vc6598e30cc65
sonar:2.17.2
sse-gateway:1.26
ssh-credentials:337.v395d2403ccd4
sshd:3.322.v159e91f6a_550
structs:337.v1b_04ea_4df7c8
subversion:1256.vee91953217b_6
token-macro:400.v35420b_922dcb_
trilead-api:2.142.v748523a_76693
variant:60.v7290fc0eb_b_cd
workflow-aggregator:596.v8c21c963d92d
workflow-api:1291.v51fd2a_625da_7
workflow-basic-steps:1058.vcb_fc1e3a_21a_9
workflow-cps:3894.3896.vca_2c931e7935
workflow-cps-global-lib:612.v55f2f80781ef
workflow-durable-task-step:1336.v768003e07199
workflow-job:1400.v7fd111b_ec82f
workflow-multibranch:773.vc4fe1378f1d5
workflow-scm-step:427.v4ca_6512e7df1
workflow-step-api:657.v03b_e8115821b_
workflow-support:907.v6713a_ed8a_573
ws-cleanup:0.45

Hi It is my first time asking the question in Jenkins community I am not sure if it is the right place is not please tell me!

I have a question my custom plugin alauda-devops-sync does not call the following code correctly and the returned job is always null!

Jenkins j = Jenkins.getInstanceOrNull();
Job<?, ?> job = (Job) j.getItemByFullName(jobName, Job.class);

However, if I call it in the script console it will work well.

I have no idea how to debug this. Have you ever seen the same thing?

I would add some logging to the plugin and see if the jobName is actually what you expect. Maybe for some reason it is not the fullname but only the simple name (without parent folders). Then it would only be found when it is in the root of Jenkins.

Thanks for your reply!

I have added the log for printing jobName and used the printed jobName to execute the following code in console script and I get the expected result

id = "e2eproject/e2eproject-graph#53";

Run run = Run.fromExternalizableId(id);

Jenkins j = Jenkins.getInstanceOrNull();
if (j == null) {
  println("jenkins is null")
} else {
  println("jenkins is not null")
}

int hash = id.lastIndexOf('#');
String jobName = id.substring(0, hash);
println("hash is " + hash);
println("jobName is " + jobName);


Job<?, ?> job = j.getItemByFullName(jobName, Job.class);
if (job == null) {
   println("job is null");
} else {
   println("job is " + job);
}

---
output: 

jenkins is not null
hash is 27
jobName is e2eproject/e2eproject-graph
job is org.jenkinsci.plugins.workflow.job.WorkflowJob@53677e3f[e2eproject/e2eproject-graph]

So I am sure that JobName is ok.

The way you retrieve the jobname is not reliable

You can get the job with run.getParent()
No need to extract the jobname from some string and then look it up.

it might also be a permission problem. If the code in the plugin is not running as SYSTEM and the user under which the code is running has no permission to see the job then you will get null for the call to getItemByFullName

1 Like

Yes, I checked the getItemByFullName method and found that before getting the item will check the permission first and if not passed it will return null without any log or exception.

    @CheckForNull
    public <T extends Item> T getItemByFullName(@NonNull String fullName, Class<T> type) throws AccessDeniedException {
        StringTokenizer tokens = new StringTokenizer(fullName, "/");
        ItemGroup parent = this;
        if (!tokens.hasMoreTokens()) {
            return null;
        } else {
            while(true) {
                Item item = ((ItemGroup)parent).getItem(tokens.nextToken());
                if (!tokens.hasMoreTokens()) {
                    if (type.isInstance(item)) {
                        return (Item)type.cast(item);
                    }

                    return null;
                }

                if (!(item instanceof ItemGroup)) {
                    return null;
                }

                if (!item.hasPermission(Item.READ)) {
                    return null;
                }

                parent = (ItemGroup)item;
            }
        }
    }

I added the following code and it returned the job item correctly!

    ACLContext ignored = ACL.as(ACL.SYSTEM);

Thanks for your reply very much it is very helpful!