<p dir="auto"><strong><a href="https://jira.spring.io/secure/ViewProfile.jspa?name=mads1980" rel="nofollow">Manuel Dominguez Sarmiento</a></strong> opened <strong><a href="https://jira.spring.io/browse/SPR-8887?redirect=false" rel="nofollow">SPR-8887</a></strong> and commented</p>
<p dir="auto">This is the exception we get when using the latest Spring 3.1 RC2 together with Quartz 2.1.1</p>
<p dir="auto">[ERROR] 2011-11-29 14:33:57 [JobRunShell-scheduler_Worker-1] - Job DEFAULT.deviceIndexerJob threw an unhandled Exception:<br>
java.lang.IncompatibleClassChangeError: Found interface org.quartz.JobExecutionContext, but class was expected<br>
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:79)<br>
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)<br>
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)<br>
[ERROR] 2011-11-29 14:33:57 [JobRunShell-scheduler_Worker-2] - Job DEFAULT.shortCodeIndexerJob threw an unhandled Exception:<br>
java.lang.IncompatibleClassChangeError: Found interface org.quartz.JobExecutionContext, but class was expected<br>
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:79)<br>
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)<br>
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)</p>
<p dir="auto">The source for QuartzJobBean does not seem to indicate any kind of problem. Even though JobExecutionContext was a class in Quartz 1.x and is now an interface in Quartz 2.x, the methods invoked on it are present in both.</p>
<p dir="auto">The problem is that the Spring binary has been compiled against Quartz 1.x, and changing a class into an interface (or viceversa) is an incompatible change according to the Java spec, so we get IncompatibleClassChangeError even if the source compiles fine against both Quartz versions.</p>
<p dir="auto">Recompiling QuartzJobBean against Quartz 2.x solves the issue, however this is an undesirable solution. I guess the solution would be to invoke the offending methods using reflection.</p>
<p dir="auto">Our workaround was simply creating an alternative MethodInvokingJobDetailFactoryBean simplified for our use and compiled directly against Quartz 2.x, but this should be solved for the general public.</p>
<p dir="auto">BTW, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398112884" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/13081" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/13081/hovercard" href="https://github.com/spring-projects/spring-framework/issues/13081">#13081</a> is somehow related but is clearly a different issue, which in fact has already been solved in 3.1 RC2</p>
<hr>
<p dir="auto"><strong>Affects:</strong> 3.1 RC2</p>
<p dir="auto"><strong>Issue Links:</strong></p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398115852" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/13530" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/13530/hovercard" href="https://github.com/spring-projects/spring-framework/issues/13530">#13530</a> QuartzJobBean doesn't work with Quartz 2.0 at runtime (<em><strong>"duplicates"</strong></em>)</li>
</ul>
<p dir="auto"><strong><a href="https://jira.spring.io/secure/ViewProfile.jspa?name=wim.deblauwe" rel="nofollow">Wim Deblauwe</a></strong> opened <strong><a href="https://jira.spring.io/browse/SPR-5402?redirect=false" rel="nofollow">SPR-5402</a></strong> and commented</p>
<p dir="auto">I saw a NullPointerException in the logs of my tomcat (started using maven cargo):</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="[INFO] [talledLocalContainer] java.lang.NullPointerException
[INFO] [talledLocalContainer] 	at java.lang.String.indexOf(String.java:1734)
[INFO] [talledLocalContainer] 	at java.lang.String.indexOf(String.java:1716)
[INFO] [talledLocalContainer] 	at org.springframework.jms.JmsException.getMessage(JmsException.java:87)
[INFO] [talledLocalContainer] 	at java.lang.Throwable.getLocalizedMessage(Throwable.java:267)
[INFO] [talledLocalContainer] 	at java.lang.Throwable.toString(Throwable.java:343)
[INFO] [talledLocalContainer] 	at java.lang.String.valueOf(String.java:2827)
[INFO] [talledLocalContainer] 	at java.io.PrintWriter.println(PrintWriter.java:710)
[INFO] [talledLocalContainer] 	at java.lang.Throwable.printStackTrace(Throwable.java:509)
[INFO] [talledLocalContainer] 	at org.apache.log4j.spi.ThrowableInformation.getThrowableStrRep(ThrowableInformation.java:76)
[INFO] [talledLocalContainer] 	at org.apache.log4j.spi.LoggingEvent.getThrowableStrRep(LoggingEvent.java:407)
[INFO] [talledLocalContainer] 	at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:305)
[INFO] [talledLocalContainer] 	at org.apache.log4j.WriterAppender.append(WriterAppender.java:160)
[INFO] [talledLocalContainer] 	at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
[INFO] [talledLocalContainer] 	at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
[INFO] [talledLocalContainer] 	at org.apache.log4j.Category.callAppenders(Category.java:206)
[INFO] [talledLocalContainer] 	at org.apache.log4j.Category.forcedLog(Category.java:391)
[INFO] [talledLocalContainer] 	at org.apache.log4j.Category.error(Category.java:322)"><pre class="notranslate"><code class="notranslate">[INFO] [talledLocalContainer] java.lang.NullPointerException
[INFO] [talledLocalContainer] 	at java.lang.String.indexOf(String.java:1734)
[INFO] [talledLocalContainer] 	at java.lang.String.indexOf(String.java:1716)
[INFO] [talledLocalContainer] 	at org.springframework.jms.JmsException.getMessage(JmsException.java:87)
[INFO] [talledLocalContainer] 	at java.lang.Throwable.getLocalizedMessage(Throwable.java:267)
[INFO] [talledLocalContainer] 	at java.lang.Throwable.toString(Throwable.java:343)
[INFO] [talledLocalContainer] 	at java.lang.String.valueOf(String.java:2827)
[INFO] [talledLocalContainer] 	at java.io.PrintWriter.println(PrintWriter.java:710)
[INFO] [talledLocalContainer] 	at java.lang.Throwable.printStackTrace(Throwable.java:509)
[INFO] [talledLocalContainer] 	at org.apache.log4j.spi.ThrowableInformation.getThrowableStrRep(ThrowableInformation.java:76)
[INFO] [talledLocalContainer] 	at org.apache.log4j.spi.LoggingEvent.getThrowableStrRep(LoggingEvent.java:407)
[INFO] [talledLocalContainer] 	at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:305)
[INFO] [talledLocalContainer] 	at org.apache.log4j.WriterAppender.append(WriterAppender.java:160)
[INFO] [talledLocalContainer] 	at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
[INFO] [talledLocalContainer] 	at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
[INFO] [talledLocalContainer] 	at org.apache.log4j.Category.callAppenders(Category.java:206)
[INFO] [talledLocalContainer] 	at org.apache.log4j.Category.forcedLog(Category.java:391)
[INFO] [talledLocalContainer] 	at org.apache.log4j.Category.error(Category.java:322)
</code></pre></div>
<p dir="auto">The problem can be seen by looking at the code of JmsMessage.java:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="public String getMessage() {
     String message = super.getMessage();
     Throwable cause = getCause();
     if (cause instanceof JMSException) {
          Exception linkedEx = ((JMSException) cause).getLinkedException();
          if (linkedEx != null &amp;&amp; cause.getMessage().indexOf(linkedEx.getMessage()) == -1) {
               message = message + &quot;; nested exception is &quot; + linkedEx;
          }
     }
     return message;
}"><pre class="notranslate"><code class="notranslate">public String getMessage() {
     String message = super.getMessage();
     Throwable cause = getCause();
     if (cause instanceof JMSException) {
          Exception linkedEx = ((JMSException) cause).getLinkedException();
          if (linkedEx != null &amp;&amp; cause.getMessage().indexOf(linkedEx.getMessage()) == -1) {
               message = message + "; nested exception is " + linkedEx;
          }
     }
     return message;
}
</code></pre></div>
<p dir="auto">The line that does the <code class="notranslate">indexOf()</code> can give a NPE if <code class="notranslate">linkedEx.getMessage()</code> returns <code class="notranslate">null</code></p>
<hr>
<p dir="auto"><strong>Affects:</strong> 2.5.6</p>
<p dir="auto"><strong>Issue Links:</strong></p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398091774" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/9948" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/9948/hovercard" href="https://github.com/spring-projects/spring-framework/issues/9948">#9948</a> JmsUtils.buildExceptionMessage throws NPE if the linked exception doesn't have a message (<em><strong>"duplicates"</strong></em>)</li>
</ul>