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