FingerprintAction has the following field:

      private final AbstractBuild build;

      This field links to an AbstractBuild, which in turn has the following field:

      protected transient final JobT project;

      Once Jenkin persists a run to a file, the build from the FingerprintAction will be saved, but the project itself will not get saved. An example fragment from one of the build files looks like this:

          <hudson.tasks.Fingerprinter_-FingerprintAction>
            <build class="build">
              <actions>
                <hudson.model.ParametersAction reference="../../../../hudson.model.ParametersAction"/>
                <hudson.model.CauseAction reference="../../../../hudson.model.CauseAction"/>
                <hudson.plugins.copyartifact.CopyArtifact_-EnvAction reference="../../../../hudson.plugins.copyartifact.CopyArtifact_-EnvAction"/>
                <hudson.tasks.Fingerprinter_-FingerprintAction reference="../../.."/>
              </actions>
              <number>17</number>
              <startTime>1358250655935</startTime>
              <result>SUCCESS</result>
              <duration>4488</duration>
              <charset>UTF-8</charset>
              <keepLog>false</keepLog>
              <builtOn></builtOn>
              <workspace>/opt/hudson/files/jobs/Deploy/workspace</workspace>
              <hudsonVersion>1.494</hudsonVersion>
              <scm class="hudson.scm.NullChangeLogParser"/>
              <culprits class="com.google.common.collect.EmptyImmutableSortedSet"/>
            </build>
            ...
      

      When the files are read and the objects are created, the project field remains empty. During intialization, the onLoad() method is called:

          @Override
          protected R retrieve(File d) throws IOException {
              if(new File(d,"build.xml").exists()) {
                  // if the build result file isn't in the directory, ignore it.
                  try {
                      R b = cons.create(d);
                      b.onLoad();
                      if (LOGGER.isLoggable(FINE))
                          LOGGER.log(FINE,"Loaded " + b.getFullDisplayName(),new ThisIsHowItsLoaded());
                      return b;
                  } catch (IOException e) {
                      LOGGER.log(Level.WARNING, "could not load " + d, e);
                  } catch (InstantiationError e) {
                      LOGGER.log(Level.WARNING, "could not load " + d, e);
                  }
              }
              return null;
          }
      

      This method invokes onLoad() on all actions that implement RunAction:

              for (Action a : getActions())
                  if (a instanceof RunAction)
                      ((RunAction) a).onLoad();
      

      The FingerprintAction does implement the RunAction interface, and the method is implemented as follows:

              public void onLoad() {
                  // share data structure with nearby builds, but to keep lazy loading efficient,
                  // don't go back the history forever.
                  if (rand.nextInt(2)!=0) {
                      Run pb = build.getPreviousBuild();
                      if (pb!=null) {
                          FingerprintAction a = pb.getAction(FingerprintAction.class);
                          if (a!=null)
                              compact(a);
                      }
                  }
              }
      

      Build is set, so getPreviousBuild() can be called, this will however fail because the project is null (due to the transient field) and will throw a NullPointerException.

      This causes very strange behavior as sometimes pages are working, sometimes they are not. There are a lot of stack traces around that actually look like as if they were caused by the same problem, for example: https://issues.jenkins-ci.org/browse/JENKINS-16845

      Stack Trace looks like this:

      Caused by: java.lang.NullPointerException
      	at hudson.model.AbstractBuild.getPreviousBuild(AbstractBuild.java:207)
      	at hudson.tasks.Fingerprinter$FingerprintAction.onLoad(Fingerprinter.java:349)
      	at hudson.model.Run.onLoad(Run.java:315)
      	at hudson.model.RunMap.retrieve(RunMap.java:221)
      	at hudson.model.RunMap.retrieve(RunMap.java:59)
      	at jenkins.model.lazy.AbstractLazyLoadRunMap.load(AbstractLazyLoadRunMap.java:638)
      	at jenkins.model.lazy.AbstractLazyLoadRunMap.load(AbstractLazyLoadRunMap.java:601)
      	at jenkins.model.lazy.AbstractLazyLoadRunMap.search(AbstractLazyLoadRunMap.java:344)
      	at hudson.model.AbstractBuild.getPreviousBuild(AbstractBuild.java:207)
      	at hudson.model.AbstractBuild.getPreviousBuild(AbstractBuild.java:100)
      	at hudson.model.RunMap$1.next(RunMap.java:107)
      	at hudson.model.RunMap$1.next(RunMap.java:96)
      	at hudson.widgets.HistoryWidget.getRenderList(HistoryWidget.java:133)
      	... 122 more
      

          [JENKINS-17125] FingerprintAction deserialization leads to NPE

          Dominik Bieringer created issue -
          Dominik Bieringer made changes -
          Description Original: FingerprintAction has the following field:

          {code}private final AbstractBuild build;{code}

          This field links to an AbstractBuild, which in turn has the following field:

          {code}protected transient final JobT project;{code}

          Once Jenkin persists a run to a file, the build from the FingerprintAction will be saved, but the project itself will not get saved. An example fragment from one of the build files looks like this:

          {code}
              <hudson.tasks.Fingerprinter_-FingerprintAction>
                <build class="build">
                  <actions>
                    <hudson.model.ParametersAction reference="../../../../hudson.model.ParametersAction"/>
                    <hudson.model.CauseAction reference="../../../../hudson.model.CauseAction"/>
                    <hudson.plugins.copyartifact.CopyArtifact_-EnvAction reference="../../../../hudson.plugins.copyartifact.CopyArtifact_-EnvAction"/>
                    <hudson.tasks.Fingerprinter_-FingerprintAction reference="../../.."/>
                  </actions>
                  <number>17</number>
                  <startTime>1358250655935</startTime>
                  <result>SUCCESS</result>
                  <duration>4488</duration>
                  <charset>UTF-8</charset>
                  <keepLog>false</keepLog>
                  <builtOn></builtOn>
                  <workspace>/opt/hudson/files/jobs/Deploy/workspace</workspace>
                  <hudsonVersion>1.494</hudsonVersion>
                  <scm class="hudson.scm.NullChangeLogParser"/>
                  <culprits class="com.google.common.collect.EmptyImmutableSortedSet"/>
                </build>
                ...
          {code}

          When the files are read and the objects are created, the project field remains empty. During intialization, the onLoad() method is called:

          {code}
              @Override
              protected R retrieve(File d) throws IOException {
                  if(new File(d,"build.xml").exists()) {
                      // if the build result file isn't in the directory, ignore it.
                      try {
                          R b = cons.create(d);
                          b.onLoad();
                          if (LOGGER.isLoggable(FINE))
                              LOGGER.log(FINE,"Loaded " + b.getFullDisplayName(),new ThisIsHowItsLoaded());
                          return b;
                      } catch (IOException e) {
                          LOGGER.log(Level.WARNING, "could not load " + d, e);
                      } catch (InstantiationError e) {
                          LOGGER.log(Level.WARNING, "could not load " + d, e);
                      }
                  }
                  return null;
              }
          {code}

          This method invokes onLoad() on all actions that implement RunAction:

          {code}
                  for (Action a : getActions())
                      if (a instanceof RunAction)
                          ((RunAction) a).onLoad();
          {code}

          The FingerprintAction does implement the RunAction interface, and the method is implemented as follows:

          {code}
                  public void onLoad() {
                      // share data structure with nearby builds, but to keep lazy loading efficient,
                      // don't go back the history forever.
                      if (rand.nextInt(2)!=0) {
                          Run pb = build.getPreviousBuild();
                          if (pb!=null) {
                              FingerprintAction a = pb.getAction(FingerprintAction.class);
                              if (a!=null)
                                  compact(a);
                          }
                      }
                  }
          {code}

          Build is set, so getPreviousBuild() can be called, this will however fail because the project is null (due to the transient field) and will throw a NullPointerException.

          This causes very strange behavior as sometimes pages are working, sometimes they are not. There are a lot of stack traces around that actually look like as if they were caused by the same problem, for example: https://issues.jenkins-ci.org/browse/JENKINS-16845

          New: FingerprintAction has the following field:

          {code}private final AbstractBuild build;{code}

          This field links to an AbstractBuild, which in turn has the following field:

          {code}protected transient final JobT project;{code}

          Once Jenkin persists a run to a file, the build from the FingerprintAction will be saved, but the project itself will not get saved. An example fragment from one of the build files looks like this:

          {code}
              <hudson.tasks.Fingerprinter_-FingerprintAction>
                <build class="build">
                  <actions>
                    <hudson.model.ParametersAction reference="../../../../hudson.model.ParametersAction"/>
                    <hudson.model.CauseAction reference="../../../../hudson.model.CauseAction"/>
                    <hudson.plugins.copyartifact.CopyArtifact_-EnvAction reference="../../../../hudson.plugins.copyartifact.CopyArtifact_-EnvAction"/>
                    <hudson.tasks.Fingerprinter_-FingerprintAction reference="../../.."/>
                  </actions>
                  <number>17</number>
                  <startTime>1358250655935</startTime>
                  <result>SUCCESS</result>
                  <duration>4488</duration>
                  <charset>UTF-8</charset>
                  <keepLog>false</keepLog>
                  <builtOn></builtOn>
                  <workspace>/opt/hudson/files/jobs/Deploy/workspace</workspace>
                  <hudsonVersion>1.494</hudsonVersion>
                  <scm class="hudson.scm.NullChangeLogParser"/>
                  <culprits class="com.google.common.collect.EmptyImmutableSortedSet"/>
                </build>
                ...
          {code}

          When the files are read and the objects are created, the project field remains empty. During intialization, the onLoad() method is called:

          {code}
              @Override
              protected R retrieve(File d) throws IOException {
                  if(new File(d,"build.xml").exists()) {
                      // if the build result file isn't in the directory, ignore it.
                      try {
                          R b = cons.create(d);
                          b.onLoad();
                          if (LOGGER.isLoggable(FINE))
                              LOGGER.log(FINE,"Loaded " + b.getFullDisplayName(),new ThisIsHowItsLoaded());
                          return b;
                      } catch (IOException e) {
                          LOGGER.log(Level.WARNING, "could not load " + d, e);
                      } catch (InstantiationError e) {
                          LOGGER.log(Level.WARNING, "could not load " + d, e);
                      }
                  }
                  return null;
              }
          {code}

          This method invokes onLoad() on all actions that implement RunAction:

          {code}
                  for (Action a : getActions())
                      if (a instanceof RunAction)
                          ((RunAction) a).onLoad();
          {code}

          The FingerprintAction does implement the RunAction interface, and the method is implemented as follows:

          {code}
                  public void onLoad() {
                      // share data structure with nearby builds, but to keep lazy loading efficient,
                      // don't go back the history forever.
                      if (rand.nextInt(2)!=0) {
                          Run pb = build.getPreviousBuild();
                          if (pb!=null) {
                              FingerprintAction a = pb.getAction(FingerprintAction.class);
                              if (a!=null)
                                  compact(a);
                          }
                      }
                  }
          {code}

          Build is set, so getPreviousBuild() can be called, this will however fail because the project is null (due to the transient field) and will throw a NullPointerException.

          This causes very strange behavior as sometimes pages are working, sometimes they are not. There are a lot of stack traces around that actually look like as if they were caused by the same problem, for example: https://issues.jenkins-ci.org/browse/JENKINS-16845

          Stack Trace looks like this:

          {code}
          Caused by: java.lang.NullPointerException
          at hudson.model.AbstractBuild.getPreviousBuild(AbstractBuild.java:207)
          at hudson.tasks.Fingerprinter$FingerprintAction.onLoad(Fingerprinter.java:349)
          at hudson.model.Run.onLoad(Run.java:315)
          at hudson.model.RunMap.retrieve(RunMap.java:221)
          at hudson.model.RunMap.retrieve(RunMap.java:59)
          at jenkins.model.lazy.AbstractLazyLoadRunMap.load(AbstractLazyLoadRunMap.java:638)
          at jenkins.model.lazy.AbstractLazyLoadRunMap.load(AbstractLazyLoadRunMap.java:601)
          at jenkins.model.lazy.AbstractLazyLoadRunMap.search(AbstractLazyLoadRunMap.java:344)
          at hudson.model.AbstractBuild.getPreviousBuild(AbstractBuild.java:207)
          at hudson.model.AbstractBuild.getPreviousBuild(AbstractBuild.java:100)
          at hudson.model.RunMap$1.next(RunMap.java:107)
          at hudson.model.RunMap$1.next(RunMap.java:96)
          at hudson.widgets.HistoryWidget.getRenderList(HistoryWidget.java:133)
          ... 122 more
          {code}

          Dominik Bieringer added a comment - - edited

          The way I solved it for now is the following:

          diff --git a/core/src/main/java/hudson/tasks/Fingerprinter.java b/core/src/main/java/hudson/tasks/Fingerprinter.java
          index 6600bd4..d22ade7 100644
          --- a/core/src/main/java/hudson/tasks/Fingerprinter.java
          +++ b/core/src/main/java/hudson/tasks/Fingerprinter.java
          @@ -294,7 +294,7 @@
                */
               public static final class FingerprintAction implements RunAction {
                   
          -        private final AbstractBuild build;
          +        private AbstractBuild build;
           
                   private static final Random rand = new Random();
           
          @@ -356,6 +356,7 @@
                   }
           
                   public void onAttached(Run r) {
          +        	this.build = (AbstractBuild)r;
                   }
           
                   public void onBuildComplete() {
          
          diff --git a/core/src/main/java/hudson/model/RunMap.java b/core/src/main/java/hudson/model/RunMap.java
          index 9207cfc..fad5b9d 100644
          --- a/core/src/main/java/hudson/model/RunMap.java
          +++ b/core/src/main/java/hudson/model/RunMap.java
          @@ -218,6 +218,10 @@
                       // if the build result file isn't in the directory, ignore it.
                       try {
                           R b = cons.create(d);
          +                for (Action cur : b.getActions())
          +                	if (cur instanceof RunAction)
          +                		((RunAction) cur).onAttached(b);
          +                
                           b.onLoad();
                           if (LOGGER.isLoggable(FINE))
                               LOGGER.log(FINE,"Loaded " + b.getFullDisplayName(),new ThisIsHowItsLoaded());
          

          Dominik Bieringer added a comment - - edited The way I solved it for now is the following: diff --git a/core/src/main/java/hudson/tasks/Fingerprinter.java b/core/src/main/java/hudson/tasks/Fingerprinter.java index 6600bd4..d22ade7 100644 --- a/core/src/main/java/hudson/tasks/Fingerprinter.java +++ b/core/src/main/java/hudson/tasks/Fingerprinter.java @@ -294,7 +294,7 @@ */ public static final class FingerprintAction implements RunAction { - private final AbstractBuild build; + private AbstractBuild build; private static final Random rand = new Random(); @@ -356,6 +356,7 @@ } public void onAttached(Run r) { + this .build = (AbstractBuild)r; } public void onBuildComplete() { diff --git a/core/src/main/java/hudson/model/RunMap.java b/core/src/main/java/hudson/model/RunMap.java index 9207cfc..fad5b9d 100644 --- a/core/src/main/java/hudson/model/RunMap.java +++ b/core/src/main/java/hudson/model/RunMap.java @@ -218,6 +218,10 @@ // if the build result file isn't in the directory, ignore it. try { R b = cons.create(d); + for (Action cur : b.getActions()) + if (cur instanceof RunAction) + ((RunAction) cur).onAttached(b); + b.onLoad(); if (LOGGER.isLoggable(FINE)) LOGGER.log(FINE, "Loaded " + b.getFullDisplayName(), new ThisIsHowItsLoaded());
          kutzi made changes -
          Link New: This issue is related to JENKINS-16845 [ JENKINS-16845 ]

          kutzi added a comment -

          Not related to the fingerprint plugin but to core.

          kutzi added a comment - Not related to the fingerprint plugin but to core.
          kutzi made changes -
          Component/s New: core [ 15593 ]
          Component/s Original: fingerprint [ 16622 ]
          kutzi made changes -
          Assignee Original: Marc Sanfacon [ marcsanfacon ] New: Kohsuke Kawaguchi [ kohsuke ]

          Jose Sa added a comment -

          In 1.502 some jobs fail to load due to the NullPointer exception in getPreviousBuild.

          Jose Sa added a comment - In 1.502 some jobs fail to load due to the NullPointer exception in getPreviousBuild.

          I suspect that this is an instance of JENKINS-15156. One of the issues with that is that AbstractProject#builds was not being properly re-initialized by the lazy-loading code.

          JENKINS-15156 is mostly fixed in 1.504 but there are still a few fixes that will be in the soon to be released 1.505.

          Richard Mortimer added a comment - I suspect that this is an instance of JENKINS-15156 . One of the issues with that is that AbstractProject#builds was not being properly re-initialized by the lazy-loading code. JENKINS-15156 is mostly fixed in 1.504 but there are still a few fixes that will be in the soon to be released 1.505.
          Jesse Glick made changes -
          Link New: This issue duplicates JENKINS-16845 [ JENKINS-16845 ]

            jglick Jesse Glick
            homes2001 Dominik Bieringer
            Votes:
            2 Vote for this issue
            Watchers:
            10 Start watching this issue

              Created:
              Updated:
              Resolved: