I've never been a particular fan of Sun's marketing department - especially when they demand that we use bizarre non-abbreviations like "Jave EE" in preference to "JEE" or arbitrary bumped version numbers in place of orderly progressions. Normally their evil touch causes irritation only, but today it was the origin of a configuration bug that had me fairly confused.
The symptom is in Eclipse, where I was getting a dialog reading: "Cannot open default editor. String index out of range: 2" whenever I tried to use the F3 short cut to navigate to a source file. I do that a lot because I can never remember all the parameters for EJB 3 annotations (despite being an alleged expert) and it's a quick way to look up their names and types.
Since I use Eclipse all the time, and I do this all the time, I was fairly sure it wasn't a bug in Eclipse, or that if it was a bug in Eclipse that it was an obscure one caused by something Maven specific. I use Maven a fair amount too, but I'm using some unusual plugins and do sometimes get odd problems stemming from this.
As a quick aside, I'd note that Maven's documentation is mediocre, and the documentation for many (most?) of the plugins is downright appalling, but that the advantages are enough to compensate for this.
Anyway, I had made various changes to the configuration, the build was working fine in Maven (and hence was checked in), so it had to be something to do with the generated Eclipse config using the eclipse:eclipse target. Various voodoo invocations of the cleaning targets and rebuildings didn't make the problem vanish (it never does but I've never quite broken the wishful thinking habit). So I started poking around the logs. Here's the culprit from the workspace/.metadata/.log file:
java.lang.StringIndexOutOfBoundsException: String index out of range: 2
at java.lang.String.charAt(String.java:687)
at org.eclipse.jdt.internal.core.JavaModelManager$CompilationParticipants.indexForSourceLevel(JavaModelManager.java:332)
at org.eclipse.jdt.internal.core.JavaModelManager$CompilationParticipants.getCompilationParticipants(JavaModelManager.java:218)
at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.notifyParticipants(ReconcileWorkingCopyOperation.java:198)
at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.executeOperation(ReconcileWorkingCopyOperation.java:75)
at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:720)
at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:779)
at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1122)
at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1094)
at org.eclipse.jdt.internal.corext.util.JavaModelUtil.reconcile(JavaModelUtil.java:702)
at org.eclipse.jdt.internal.ui.actions.SelectionConverter.codeResolve(SelectionConverter.java:198)
at org.eclipse.jdt.internal.ui.actions.SelectionConverter$1$CodeResolveRunnable.run(SelectionConverter.java:184)
at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:113)
That indexForSourceLevel gives the game away. Eclipse is doing a hard-coded charAt on the source level in its configuration file. Sure enough, if I look in the generated configuration files I find this as the contents of project/.settings/org.eclipse.jdt.core.prefs:
#Mon Oct 22 15:47:59 BST 2007 org.eclipse.jdt.core.compiler.codegen.targetPlatform=5 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.source=5 org.eclipse.jdt.core.compiler.compliance=5
Evidently Eclipse is expecting to find "1.5" and isn't.
"1.5".charAt(2) will return the "official" version of 5, but "5".charAt(2) will duly give you the above exception.
Where did this arise from? I had specified the source and target versions in maven as 5. Here's the pertinent snippet:
<-- DO NOT USE THIS EXCERPT - IT WILL BREAK GENERATED ECLIPSE CONFIG -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>5</source>
<target>5</target>
</configuration>
</plugin>
So very irritating. I'm not even sure if this is my fault for misreading/not reading the Maven documentation properly, but I think it ought to have given me an error message if it's wrong - the build completes cleanly from within Maven. You might blame the plugin that's generating the Eclipse output, I suppose. A bit unfair though, since it presumably has to cater to future insane Sun decisions on versioning. Eclipse is only reading its own config files so while the error message isn't very helpful it would be unreasonable to blame the Eclipse developers.
I blame Sun marketing for confusing me.
Anyway, the fix is to amend the above excerpt from the maven configuration to use the Programmer-friendly version number:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>