Archive for the ‘OTDT’ Category
Object Teams with Null Annotations
The recent release of Juno M4 brought an interesting combination: The Object Teams Development Tooling now natively supports annotation-based null analysis for Object Teams (OT/J). How about that? ![]()

The path behind us
Annotation-based null analysis has been added to Eclipse in several stages:
- Using OT/J for prototyping
- As discussed in this post, OT/J excelled once more in a complex development challenge: it solved the conflict between extremely tight integration and separate development without double maintenance. That part was real fun.
- Applying the prototype to numerous platforms
- Next I reported that only one binary deployment of the OT/J-based prototype sufficed to upgrade any of 12 different versions of the JDT to support null annotations — looks like a cool product line
- Pushing the prototype into the JDT/Core
- Next all of the JDT team (Core and UI) invested efforts to make the new feature an integral part of the JDT. Thanks to all for this great collaboration!
- Merging the changes into the OTDT
- Now, that the new stuff was mixed back into the plain-Java implementation of the JDT, it was no longer applicable to other variants, but the routine merge between JDT/Core HEAD and Object Teams automatically brought it back for us. With the OTDT 2.1 M4, annotation-based null analysis is integral part of the OTDT.
Where we are now
Regarding the JDT, others like Andrey, Deepak and Aysush have beaten me in blogging about the new coolness. It seems the feature even made it to become a top mention of the Eclipse SDK Juno M4. Thanks for spreading the word!
Ah, and thanks to FOSSLC you can now watch my ECE 2011 presentation on this topic.
Two problems of OOP, and their solutions
Now, OT/J with null annotations is indeed an interesting mix, because it solves two inherent problems of object-oriented programming, which couldn’t differ more:
1.: NullPointerException is the most widespread and most embarrassing bug that we produce day after day, again and again. Pushing support for null annotations into the JDT has one major motivation: if you use the JDT but don’t use null annotations you’ll no longer have an excuse. For no good reasons your code will retain these miserable properties:
- It will throw those embarrassing NPEs.
- It doesn’t tell the reader about fundamental design decisions: which part of the code is responsible for handling which potential problems?
Why is this problem inherent to OOP? The dangerous operator that causes the exception is this:

right, the tiny little dot. And that happens to be the least dispensable operator in OOP.
2.: Objectivity seems to be a central property on any approach that is based just on Objects. While so many other activities in software engineering are based on the insight that complex problems with many stakeholders involved can best be addressed using perspectives and views etc., OOP forces you to abandon all that: an object is an object is an object. Think of a very simple object: a File. Some part of the application will be interested in the content so it can decode the bytes and do s.t. meaningful with it, another part of the application (maybe an underlying framework) will mainly be interested in the path in the filesystem and how it can be protected against concurrent writing, still other parts don’t care about either but only let you send the thing over the net. By representing the “File” as an object, that object must have all properties that are relevant to any part of the application. It must be openable, lockable and sendable and whatnot. This yields bloated objects and unnecessary, sometimes daunting dependencies. Inside the object all those different use cases it is involved in can not be separated!
With roles objectivity is replaced by a disciplined form of subjectivity: each part of the application will see the object with exactly those properties it needs, mediated by a specific role. New parts can add new properties to existing objects — but not in the unsafe style of dynamic languages, but strictly typed and checked. What does it mean for practical design challenges? E.g, direct support for feature oriented designs - the direct path to painless product lines etc.
Just like the dot, objectivity seems to be hardcoded into OOP. While null annotations make the dot safe(r), the roles and teams of OT/J add a new dimension to OOP where perspectives can be used directly in the implementation. Maybe it does make sense, to have both capabilities in one language
although one of them cleans up what should have been sorted out many decades ago while the other opens new doors towards the future of sustainable software designs.
The road ahead
The work on null annotations goes on. What we have in M4 is usable and I can only encourage adopters to start using it right now, but we still have an ambitious goal: eventually, the null analysis shall not only find some NPEs in your program, but eventually the absense of null related errors and warnings shall give the developer the guarantee that this piece of code will never throw NPE at runtime.
What’s missing towards that goal:
- Fields: we don’t yet support null annotations for fields. This is next on our plan, but one particular issue will require experimentation and feedback: how do we handle the initialization phase of an object, where fields start as being null? More on that soon.
- Libraries: we want to support null specifications for libraries that have no null annotations in their source code.
- JSR 308: only with JSR 308 will we be able to annotate all occurrences of types, like, e.g., the element type of a collection (think of
List<@NonNull String>)
Please stay tuned as the feature evolves. Feedback including bug reports is very welcome!
Ah, and one more thing in the future: I finally have the opportunity to work out a cool tutorial with a fellow JDT committer: How To Train the JDT Dragon with Ayushman. Hope to see y’all in Reston!
Builds are like real software - or even more so
Being a part-time release engineer for the Object Teams project I can only agree with every word Kim writes about the job, I wish I could hire her for our project
She writes:
“Nobody in needs to understand how the build works, they just need to push a button. That’s great. Until the day before a release when your build fails with a cryptic message about unresolved dependencies. And you have no idea how to fix it. And neither does anyone else on the team.”
That puts a sad smile on my face and I’d like to add a little quality metric that seems cruel for today’s build systems, but might actually be useful for any software:
One extreme I experienced was in a PDE/Build-ant-build which I had to set to verbose to get any useful answer but then I had to find the relevant error message deeply buried in literally tens of megabytes of log output. Takes ages to browse that log file. Other tools rank towards the other end of the spectrum saying basically “it didn’t work”.
Why is the worst error message relevant? When you hit that worst message it’s close to saying “game over”. Especially when working on a build I’ve come to the point time and again where all my creativity and productivity came to a grinding halt and for days or weeks I simply made zero progress because I had no idea why that system didn’t work and what it expected me to do to fix the thing. Knock-out.
Obviously I hate that state when I make no progress towards my goal. And typically that state is reached by poor communication from some framework back to me.
Real coolness
I know people usually don’t like to work on improving error messages, but please, don’t think good error messages are any bit less cool than running your software on mars. On the one hand we try to build tools that improve developers’ productivity by a few percent and than the tool will give answers that bring that very productivity down to zero. That’s - inconsistent.
I’m tempted to repeat the p2 story here. Many will remember the merciless dump of data from the sat solver that p2 gave in its early days. Some will consider the problem solved by now. Judge for yourself: what’s the worst-case time a regular Eclipse user will need to understand what p2 is telling him/her by one of its error messages.
The intention of this post is not to blame any particular technology. The list would be quite long anyway. It’s about general awareness (big words, sorry
).
Consider the worst case
Again, why worst case? Because the worst case will happen. And it’s enough if it hits you once to easily compensate all the time savings the tool otherwise brought to you.
Communicate!
Framework developers, tool smiths: let your software communicate with the user and let it be especially helpful when the user is in dire need of help.
One small contribution in this field I’d like to share with you: in the OTDT every error/warning raised by the compiler not only tries to precisely describe what’s wrong but it is directly linked to the corresponding paragraph in the language definition that is violated by the current code. At least this should completely explain why the current code is wrong. It’s a small step, but I feel a strong need for linking specific help to every error message.
But first, the software has to anticipate every single error that will occur in order to produce useful messages. That’s the real reason why creating complex software is so challenging. Be it a build system or the “real” software.
Be cool, give superb error messages!
Mix-n-match language support
I’ve been involved in the release of different versions of the JDT lately, supporting different flavors of Java.
Classical release management
At the core we have the plain JDT, of which we published the 3.7.0 release in June and right now first release candidates are being prepared towards the 3.7.1 service release, which will be the first official release to support Java 7. At the same time the first milestones towards 3.8 are being built. OK, this is almost normal business — with the exception of the service release differs more than usual from its base release, due to the unhappy timing of the release of Java 7 vs. Eclipse 3.7.
First variant: Object Teams
The same release plan is mirrored by the Object Teams releases 2.0.0, 2.0.1RC1, 2.1.0M1. Merging the delta from JDT 3.7 to 3.7.1 into the OTDT was a challenge, given that this delta contained the full implementation of all that’s new in Java 7. Still with the experience of regularly merging JDT/Core changes into the OT variant, the pure merging was less than one day plus a couple more days until all 50000+ tests were green again. The nice thing about the architecture of the OTDT: after merging the JDT/Core, I was done. Since all other adaptations of the JDT are implemented using OT/Equinox adopting, e.g., all the new quick assists for Java 7 required a total of zero minutes integration time.
I took the liberty of branching 2.0.x and 2.1 only after integrating the Java 7 support, which also means that 2.1 M1 has only a small number of OT-specific improvements that did not already go into 2.0.1.
Prototyping annotation based null analysis
As I wrote before, I’m preparing a comprehensive new feature for the JDT/Core: static analysis for potential NullPointerException based on annotations in the code. The latest patch attached to the bug had almost 3000 lines. Recent discussions at ECOOP made me change my mind in a few questions, so I changed some implementation strategies. Luckily the code is well modularized due to the use of OT/Equinox.
Now came the big question: against which version of the JDT should I build the null-annotation add-on? I mean, which of the 6 versions I have been involved in during the last 2 months?
As I like a fair challenge every now and then I decided: all six, i.e., I wanted to support adding the new static analysis to all six JDT versions mentioned before.
Integration details
Anybody who has worked on a Java compiler will confirm: if you change one feature of the compiler chances are that any other feature can be broken by the change (I’m just paraphrasing: “it’s complex”). And indeed, applying the nullity plug-in to the OTDT caused some headache at first, because both variants of the compiler make specific assumptions about the order in which specific information is available during the compilation process. It turned out that two of these assumptions where simply incompatible, so I had to make some changes (here I made the null analysis more robust).
At the point where I thought I was done, I tripped over an ugly problem that’s intrinsic to Java.
The nullity plug-in adapts a method in the JDT/Core which contains the following switch statement:
while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) { IExtendedModifier modifier = null; switch(token) { case TerminalTokens.TokenNameabstract: modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD); break; case TerminalTokens.TokenNamepublic: modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD); break; // more cases } }
I have a copy of this method where I only added a few lines to one of the case blocks.
Compiles fine against any version of the JDT. But Eclipse hangs when I install this plugin on top of a wrong JDT version. What’s wrong?
The problem lies in the (internal) interface TerminalTokens. The required constants TokenNameabstract etc. are of course present in all versions of this interface, however the values of these constants change every time the parser is generated anew. If constants were really abstractions that encapsulate their implementation values, all would be fine, but the Java byte code knows nothing about such an abstraction, all constant values are inlined during compilation. In other words: the meaning of a constant depends solely on the definitions which the compiler sees during compilation. Thus compiling the above switch statement hardcodes a dependency on one particular version of the interface TerminalTokens. BAD.
After recognizing the problem, I had to copy some different versions of the interface into my plug-in, implement some logic to translate between the different encodings and that problem was solved.
What’s next?
Nothing is next. At this point I could apply the nullity plug-in to all six versions of the JDT and all are behaving well.
Mix-n-match
Would you like Java with our without the version 7 enhancements (stable release or milestone)? May I add some role and team classes? How about a dash more static analysis? It turns out we have more than just one product, we have a full little product line with features to pick or opt-out:
| Java 6 | Java 7 | |||
|---|---|---|---|---|
| Indigo | Indigo SR1 | Juno M1 | ||
| no null annotations | Plain JDT | |||
| OTDT | ||||
| with null annotations | Plain JDT | |||
| OTDT | ||||
- OTDT: http://www.eclipse.org/objectteams/download.php
- Null ananlysis: http://wiki.eclipse.org/JDT_Core/Null_Analysis
Just make your choice ![]()
Happy hacking with null annotations and try-with-resources in OT/J.
![]() |
BTW: if you want to hear a bit more about the work on null annotations, you should really come to EclipseCon Europe — why not drop a comment at this submission |
A Short Train Ride
Less than a week ago I happily announced that Object Teams is on the Indigo Train.
Much water has gone under the bridge since then and the above statement is history.
Events where triggered by what was actually a little bug in the b3 aggregator. Only by way of this bug some people noticed that there was a ”’patch feature”’ inside the repository, i.e., a feature (”Object Teams Patch for JDT/Core”) that replaces the jdt.core plugin with a variant.
One part of me is very happy this bug occurred because finally an issue got the attention I had tried to raise at various occasions before. The lesson is:
(see this post, e.g.).
The other part of me got very worried because during that debate some harsh statements occurred that would effectively amount to excluding Object Teams from Eclipse.org. That’s a little more attention than I had intended. As in any heated debate some of the arguments sounded to me more like ideology than anything that could possibly be discussed open-mindedly.
I had mixed feelings regarding the technical scope: the outcry only banned one specific technology: patch features. I don’t see how the goal to protect a project’s bits and bytes against influence from other projects can be achieved without also discussing: access to internal, byte-code weaving and - worst of all, I believe - reflection. To be perfectly open: Object Teams uses all these techniques except for reflection. Personally, I would even argue for banning projects that do use setAccessible(true), but that’s not a realistic option because then quite likely the whole Train would dissolve into a mist.
I am actually guilty of a technical simplification during this debate: I focused too much on the idea that a user would explicitly select features to install, not accounting for the possibility that the jdt.core plugin can well be pulled in invisibly due to dependencies among plugins. So, yes, if Object Teams would still be in the repository, and if a user installed a package without the JDT and if that user did never select to install the JDT and if that user selects another feature that implicitly requires the jdt.core plugin, then that user would unexpectly install the OT variant of the jdt.core. I agree that this is not ideal. I personally would have been happy to take this risk because I know how thoroughly the OT variant is tested for compatibility. And for the remaining minuscule risk I would have been happy to promise same-day fixes. But risk assessment naturally depends on perspective and I understand that others come to different conclusions when weighing the issues.
From two days distance I can already laugh at one implication of the central argument, paraphrased as: the JDT/Core team must be protected against harmful actions from the OT team. When spelling this out in names, one of the sentences reads: “Stephan Herrmann must be protected against harmful actions by Stephan Herrmann”. I should really be careful, because I’ll never be able to escape him!
Where to go?
- As we’re banned from the Train, I willed hurriedly book a plane ticket to Indigo. Make sure we come by a Graduation office on the way.
- I do hope that bug 316702 get’s sufficient attention now. Seriously: if you are so detrimentally determined about patch features, then the UI must report it. And if it reports this, it might as well report other techniques that have similar effects!
- I appreciate any offers for helping OT/J towards a solution that avoids replacing a plugin. As of today and after more than seven years of looking at this, I see no way how this can be done, but that doesn’t mean we shouldn’t try still harder.
![]() |
Unfortunately, the debate consumed all the time and energy I had planned for preparing a presentation at the EclipseCON Audition. However, Lynn finally made my day by letting me know that my submission is the lucky #42. So I’m making progress towards my all-seasons Eclipse collection |
Object Teams is on the Train to Indigo
Object Teams made the next step for even better integration in Eclipse: starting with today’s Indigo Milestone 3 we’re aboard! No further fiddling with URLs of update sites, simply select the Indigo site…
… and directly install the OTDT from there.
For those who haven’t tried Object Teams before, here are steps 1, 2 & 3:
- Walk through the Quick Start
- Read the basic concepts in our OT/J Primer
- Play with more Examples or browse some Object Teams Patterns
Improvements
The main concern of this milestone release was catching up with the Indigo train, so the list of bugs fixed is shorter than usual. But, hey, by upgrading to Eclipse SDK 3.7M3, the OTDT supports also some new JDT coolness, like, e.g., improved static analysis (I happen to have a finger in this pie, too
).
Compatiblity
With each new release it is good to test compatibility with older software. So I loaded my previous experiment (”project medal”) into the new milestone. Much as I expected: that little adaptation of the JDT still works as intended also in the new version, which wasn’t possible with the original implementation. This again shows: in-place patching can never give you, what OT/Equinox excels in: evolvable, modular adaptation.
New Honours, New Synergy
I’m flattered to see my name appear on one more Eclipse web-page:

Thanks to the JDT/Core team for accepting me as a new member!
Actually, I’ve been poking about the JDT source code since 2003 when we started implementing the Object Teams Development Tooling (OTDT) on top of the JDT. So it was only natural that I would stumble upon a bug in the JDT every once in a while (incl. one “greatbug”
). In this specific situation, reporting bugs and trying to help find solutions was more than just good Eclipse citizenship: the discussions in bugzilla also helped me to better understand the JDT sources and thus it helped me developing the OTDT. And that’s what this post is about: synergy!
Personal Goals
Actually, watching the JDT/Core bug inbox provides a constant stream of cool riddles: spooky Java examples producing unexpected compiler/runtime results. Sometimes those are real fun to crack. Which compiler is right, which one isn’t? What’s the programmer trying to do? I’d say there’s no better way to test your Java knowledge
Also, watching this stream helps me stay informed, because every patch will eventually need to be merged into the Object Teams branch of the JDT/Core.
But I also have some pet projects that I’d like to actively push forward. Currently I’m thinking about these two:
- Supporting inter-procedural null analysis
- Making the compiler closer match the OSGi semantics
Inter-procedural null analysis
Naturally, the JDT/Core is a facilitator for tons of cool functionality in the IDE, but it hardly communicates directly with the user. But we have one channel, where the compiler can actually talk to the developer and give advice that’s well worth your bucks: errors and warnings. Did you know, that the compiler can immediately tell you what’s wrong about this piece of code:
void foo(String in) { if (in == null) new IllegalArgumentException("Null is not allowed here"); ... // real work done here }
(Yep, that was bug 236385, see the New&Noteworthy on how to enable).
Many Java developers share the experience that one of the most frequent problems is also one of the most mundane: NPE. Those, who are aware of this easily produce the opposite problem: cluttering there code with meaningless null-checks (many of which have no better action than the above IllegalArgumentException which isn’t much better than throwing the NPE in the first place). The point is, we’d want to know which values can actually be null (and why!) so we write only the necessary null-checks and for those we should think really hard what would be a suitable action, right? (“This shouldn’t happen” is not an answer!).
Thus I’m happy I could get involved in some improvements of the compiler’s flow analysis. I also experienced that null-analysis combined with aggressive optimization is a delicate issue - remember SDK 3.7M2a? Sorry about that, but to my justification I might add that bug 325755 has always been dormantly present, I only woke’em up. I must admit for those 105 minutes my heart beat was a bit above average
.
Anyway, the current null analysis is still fundamentally limited: it knows nothing about nullness of method arguments nor method call results. So it would be a real cool enhancement if we could feed such information into the compiler. Fortunately, the theory of how to do this (you may either think of improved type systems or of design by contract) is a well-explored subject. Actually, bug 186342 already has some patches in this direction. Since discussing in bugs with long history is a bit tedious I created this wiki page. Sadly, it’s not a technical difficulty that’s keeping us from immediately releasing that patch, but a stalled standardization process
.
However, as outlined in the wiki, here comes another synergy: in case we can’t find a solution that will be sufficiently compatible with future standards, I can easily create an early-adopters release, so sorting out the details of implementation and usage can be done in parallel with the standardization process. How that? I’d simply ship the compiler enhancement as an OT/Equinox-enabled plug-in. This would allow us to ship the compiler enhancement as separate plug-in ready to be tried by early adopters.
OSGi-aware compiler
Some of you may have noticed (here, or here, or here, or here or one of the many duplicates) that the compiler’s concept of a (single, linear) classpath is not a good match for compiling OSGi code. I will soon write another wiki page with my current thinkings about that issue. Stay tuned …
Comments?
For both issues I’d appreciate any comments / feedback. I’ll be checking updates of the bugs I listed, or the wiki page or … talk to me during ESE! Let’s move something together.
See you all in Ludwigsburg!
Stephan
Get for free what Coin doesn’t buy you
Ralf Ebert recently blogged about how he extended Java to support a short-hand notation for throwing exceptions, like:
throw "this is wrong";
It’s exactly the kind of enhancement you’d expect from Project Coin, but neither do they have it, nor would you want to wait until they release a solution.
At this point I gave it a few minutes, adapted Ralf’s code, applied Olivier’s suggestion wrapped it in a little plugin et voilà:
Install
Use this p2 repository, check two features…
…install and restart, and you’re ready to use your “Medal” IDE:

So that’s basically the same as what Ralf already showed except:
It’s a module!
In contrast to Ralf’s patch of the JDT/Core my little plugin can be easily deployed and installed into any Eclipse (≥3.6.0). It just requires another small feature called “Object Teams Equinox Integration” or “OT/Equinox” for short.
So we’re all going to use our private own ”’dialects of Java?”’ Hm, firstly, once compiled this is of course plain Java, you wouldn’t be able to tell that the sources looked “funny”.
And: here’s the Boss Key: when somebody sniffs about your monitor, a single click will make Eclipse behave “normal”:

In other words, you can ”’dynamically enable/disable”’ this feature at runtime. The OT/Equinox Monitor view in the snapshot shows all known Team instances in the currently running IDE, and the little check boxes simply send activate() / deactivate() messages to the selected instance.
I coined the name Medal as our own playground for Java extensions of this kind. Feel free to suggest/contribute more!
Implementation
For a quick introduction on how to setup an OT/Equinox project in Eclipse I’d suggest our Quick Start (let me know if anything is unclear). For this particular case the key is in defining one little extension:

which the package explorer will render as:

Drilling into the Team class ThrowString you’ll see:

The Team class contains two Role classes:
- Role DontReport binds to class
ProblemReporter(not shown in the Outline), intercepts calls toProblemReporter.cannotThrowTypeand if the type in question is String, simply ignores the “error” - Role Generate binds to class
ThrowStatementto make sure the correct bytecodes for creating aRuntimeExceptionare generated
Also, in the Outline you see both kinds of method bindings that are supported by Object Teams:
getExceptionType/setExceptionTypeare getter/setter definitions for fieldThrowStatement.exceptionType(callout-to-field in OT/J jargon)- Things like “
adjustType <- after resolve” establish method call interception (callin bindings in OT/J jargon - the “after” is symbolized by the specific icon)
The actual implementation is really simple, like (full listing of the first role):
protected class DontReport playedBy ProblemReporter { cannotThrowType <- replace cannotThrowType; @SuppressWarnings("basecall") callin void cannotThrowType(ASTNode exception, TypeBinding exceptionType) { if (exceptionType.id != TypeIds.T_JavaLangString) // do the actual reporting only if it's not a string base.cannotThrowType(exception, exceptionType); } }
The base-call (base.cannotThrowType) delegates back to the original method, but only if the exception type is not String. The @SuppressWarnings annotation documents that not all control flows through this method will issue a base-call, a decision that deserves a second thought as it means the base plugin (here JDT/Core) does not perform its task fully as usual.
Intercepting resolve has the purpose of replacing type String with RuntimeException so that other parts of the Compiler and the IDE see a well-typed structure.
The method that performs the actual work is generateCode. Since this method is essentially based on the original implementation, the best way to see the difference is (select either the callin method or the callin binding):

which gives you this compare editor:

This neatly shows the two code blocks I inserted, one for creating the RuntimeException instance, the other for invoking its constructor. Or, if you just want to read the full role method:
/* This method is partly copied from the base method. */ @SuppressWarnings({"basecall", "inferredcallout"}) callin void generateCode(BlockScope currentScope, CodeStream codeStream) { if ((this.bits & ASTNode.IsReachable) == 0) return; int pc = codeStream.position; // create a new RuntimeException: ReferenceBinding runtimeExceptionBinding = (ReferenceBinding) this.exceptionType; codeStream.new_(runtimeExceptionBinding); codeStream.dup(); // generate the code for the original String expression: this.exception.generateCode(currentScope, codeStream, true); // call the constructor RuntimeException(String): MethodBinding ctor = runtimeExceptionBinding.getExactConstructor(new TypeBinding[]{this.stringType}); codeStream.invoke(Opcodes.OPC_invokespecial, ctor, runtimeExceptionBinding); // throw it: codeStream.athrow(); codeStream.recordPositionsFrom(pc, this.sourceStart); }
You may also fetch the full sources of this little plug-in (plus a feature for easy deployment) to play around with and extend.
Next?
Ralf mentioned that he’d like to play with ways for also extending the syntax. For a starter on how this can be done with Object Teams I recommend my previous posts IDE for your own language embedded in Java? (part 1) and part 2.
New Refactoring for OT/J: Change Method Signature
IDE Innovation
Every now and then some folks report that the IDE they’re developing now supports this or that cool new feature. Sometimes I envy them for such progress - but more often than not I end up realizing that the OTDT already has that feature or something very similar. Is that just my personal bias (which certainly I have) or are we cheating in some way, or what?
There’s a little detail in the design of the OTDT that turns out to make such a difference as normally can only achieved by cheating: by the way how the OTDT extends and adapts the JDT it is like saying we’re starting the race not at the line saying “START” but at the other one saying “FINISH” and run on from there. While many projects define “JDT-like user experience” as their long-term goal, the OTDT basically has this since the first release. How come? The OTDT basically is the JDT, with adaptations.
There’s a fine point in the word basically. To tell the truth, every feature that the JDT supports for Java development is not automatically fully available in the OTDT for OT/J development. In fact most JDT features need adaptation to provide equal convenience for OT/J development. It’s just that all these adaptations can be brought into the system very very easily - thanks to the self-application of OT/Equinox. And now, here is actually an example of a JDT feature that lacked OT/J support - until yesterday:
Change Method Signature Refactoring
If you refactor mercilessly the “Change Method Signature” refactoring is certainly one of your friends. Add/rename/remove/reshuffle parameters of a method without (too easily) breaking existing code, cool. It knows about the connections from method invocation to method declaration and about overriding. That’s good enough for Java, but not good enough for OT/J since OT/J introduces method bindings (”callout” and “callin”) that create a wiring between methods of different objects. Obviously, if one of the methods being wired changes its signature so must the method binding.
Technically, the JDT implementation of that refactoring bailed out when it asked a parameter/argument for its parent in the AST and found neither a method declaration nor a method invocation. The JDT refactoring does not know about OT/J method bindings, so it just failed to update those.
After a little of coding this is what happens now when you apply “Change Method Signature” on a piece of OT/J code. Assume you have a plain Java class:
public class BaseClass { public void bm(int i, boolean b) { } void other() { bm(3, false); } }
and a TeamClass whose contained RoleClass is bound to BaseClass:
1 2 3 4 5 6 7 8 9 10 | public team class TeamClass { protected class RoleClass playedBy BaseClass { void rm(int i2, boolean b2) <- after void bm(int i, boolean b); private void rm(int i2, boolean b2) { System.out.println((b2?i2:-i2)); } } } |
Here the right-hand side of the callin binding in line 4 refers to the normal method bm(int,boolean) defined in BaseClass.
What happens if you start messing around with the signature of bm?
Like:

I.e., we are adding a parameter str and also change the order of parameters (from i,b to b,str,i). I don’t have to tell you what this refactoring does to BaseClass, but here’s the preview of those changes affecting TeamClass:

(sorry the screenshot is a bit wide, you may have to click to really see).
The preview shows that the refactoring will do three things:
- Update the right-hand side of the method binding.
- Add a parameter mapping (the part starting with “
with“) to ensure that the role methodrmreceives the arguments it needs, the way it needs them. - Do not update any part of the role implementation, because that’s what the parameter mapping is for: shield the role implementation from any outside changes.
Some words on these parameter mappings: each element like “b2 <- b” feeds a value from the right-hand side (representing things at the baseclass side) into the parameter at the left-hand side (representing the role). The list of parameter mappings is not ordered, which means further swapping of base side parameters requires no further action. And indeed the current implementation of the refactoring does not attempt to adjust an existing parameter mapping (which might be a quite complex task). If adjustments are required which the refactoring cannot perform automatically, it will inform the user that perhaps a parameter mapping may need manual adjustment.
The refactoring applies no AI to guess what the intended solution should look like, but it performs a number of obvious adaptations and gives note when these adaptations may not suffice and manual cleanup may be needed.
Implementation
Those who have read previous posts may (almost) know the kind of statistics that follows:
- 299 LOC implementation
- 315 LOC testcode
- 170 LOC testdata
I should really show one of these OT/J based implementation, one of these days. For this post I will just give you an Outline, literally:

Role class Processor is bound to the JDT’s ChangeSignatureProcessor, and the nested roles OccurrenceUpdate and MethodSpecUpdate are bound to two inner classes of ChangeSignatureProcessor, which shows how even class nesting at the base level can be mapped to the team & role level. Instances of the innermost roles will only ever come into being, if a Processor role has detected that it needs to work in order to handle OT/J specific code. Inside each role - apart from regular fields and methods - you see those green arrow-things, denoting method bindings between a role and its base. The highlighted binding to createOccurrenceUpdate is actually the initial entry into the logic of this module. Further down you see how the base behavior reshuffleElements is intercepted to additionally add parameter mappings if needed (and yes, I’m hiding the details of role MethodSpecUpdate, but there are no secrets inside, I just more methods and more method bindings).
Voilà, we indeed have a new refactoring for OT/J. I’ve been planning this one for a while but in the end it took me little more than a day ![]()
Object Teams rocks :)
During the last week or so I modernized a part of the Object Teams Development Tooling (OTDT) that had been developed some 5 years ago: the type hierarchy for OT/J. I’ll mention the basic requirements for this engine in a minute. While most of the OTDT succeeds in reusing functionality from the JDT, the type hierarchy was implemented as a full replacement of the original. This is a pretty involved little machine, which took weeks and months to get right. It provides its logic to components like Refactoring and the Type Hierarchy View.
On the one hand this engine worked well for most uses, but over so many years we did not succeed to solve two remaining issues:
- Give a faithful implementation for
getSuperclass() - This is tricky because a role class in OT/J can have more than one superclass. Failing to implement this method we could not support the “traditional” mode of the hierarchy view that shows both the tree of subclasses of a focus type plus the path of superclasses up to
Object(this upwards path relies ongetSuperclass). - Support region based hierarchies
- Here the type hierarchy is not only computed for supertypes and subtypes of one given focus type, but full inheritance structure is computed for a set of types (a “region”). This strategy is used by many JDT Refactorings, and thus we could not precisely adapt some of these for OT/J.
In analyzing this situation I had to weigh these issues:
- In its current state the implementation strategy was a show stopper for one mode of the type hierarchy view and for precise analysis in several refactorings.
- Adding a region based variant of our hierarchy implementation would mean to re-invent lots of stuff, both from the JDT and from our own development.
- All this seemed to suggest to discard our own implementation and start over from scratch.
Object Teams to the rescue: Let’s re-build Rome in ten days.
As mentioned in my previous post, the strength of Object Teams lies in building layers: each module sits in one layer, and integration between layers is given by declarative bindings:

Applying this to the issue at hand we now actually have three layers with quite different structures:
Java Model
The bottom layer is the Java model that implements the containment tree of Jave elements: A project contains source folders, containing packages, containing compilation units, containing types containing members. In this model each Java type is represented by an instance of IType
Java Type Hierarchy
This engine from the JDT maintains the graph of inheritance information as a second way for navigating between ITypes. Interestingly, this module pretty closely simulates what Object Teams does natively, I may come back to that in a later post.
Object Teams Type Hierarchy
As an extension of Java, OT/J naturally supports the normal inheritance using extends, but there is a second way how an inheritance link can be established: based on inheritance of the enclosing team:
team class EcoSystem { protected class Project { } protected class IDEProject extends Project { } } team class Eclipse extends EcoSystem { @Override protected class Project { } @Override protected class IDEProject extends Project { } }
Here, Eclipse.Project is an implicit subclass of EcoSystem.Project simply because Eclipse is a subclass of EcoSystem and both classes have the same simple name Project. I will not go into motivation and consequences of this language design (that’ll be a separate post — which I actually promised many weeks ago).
Looking at the technical challenge we see that the implicit inheritance in OT/J adds a third layer, in which classes are connected in yet another graph.
Three Layers — Three Graphs
Looking at the IType representation of Eclipse.IDEProject we can ask three questions:
| Question | Code | Answer |
|---|---|---|
| What is your containing element? | type.getParent() |
Eclipse |
| What is your superclass? | hierarchy.getSuperclass(type) |
Eclipse.Project |
| What is your implicit superclass? | ?? | EcoSystem.Project |
Each question is implemented in a different layer of the system. Things get a little complicated when asking a type for all its super types, which requires to collect the answers from both the JDT hierarchy layer and the OT hierarchy. Yet, the most tricky part was giving an implementation for getSuperclass().
An "Impossible" Requirement
There is a hidden assumption behind method getSuperclass() which is pervasive in large parts of the implementation, especially most refactorings:
When searching all methods that a type inherits from other types, looping over
getSuperclass()until you reachObjectwill bring you to all the classes you need to consider, like so:IType currentType = /* some init */; while (currentType != null) { findMethods(currentType, /*some more arguments*/); currentType = hierarchy.getSuperclass(currentType); }
There are lots and lots of places implemented using this pattern. But, how do you do that if a class has multiple superclasses?? I cannot change all the existing code to use recursive functions rather than this single loop!
Looking at Eclipse.IDEProject we have two direct superclasses: Eclipse.Project (normal inheritance, “extends”) and EcoSystem.IDEProject (OT/J implicit inheritance), which cannot both be answered by a single call to getSuperclass(). The programming language theory behind OT/J, however, has a simple answer: linearization. Thus, the superclasses of Eclipse.IDEProject are:
- Eclipse.IDEProject → EcoSystem.IDEProject → Eclipse.Project → EcoSystem.Project
… in this order. And this is how this shall be rendered in the hierarchy view:

The final callenge: what should this query answer:
getSuperclass(ecoSystemIDEProject);
According to the above linearization we should answer: Eclipse.Project, but only if we are in the context of the superclass chain of Eclipse.IDEProject. Talking directly to EcoSystem.IDEProject we should get EcoSystem.Project! In other words: the function needs to be smarter than what it can derive from its arguments.
Layer Instances for each Situation
Let’s go back to the layer thing:

At the bottom you see the Java model (as rendered by the package explorer). In the top layer you see the OT/J type hierarchy (lets forget about the middle layer for now). Two essential concepts can be illustrated by this picture:
- Each layer is populated with objects and while each layer owns its objects, those objects connected with a red line between layers are almost the same, they represent the same concept.
- The top layer can be instantiated multiple times: for each focus type you create a new OT/J hierarchy instance, populated with a fresh set of objects.
It is the second bullet that resolves the “impossible” requirement: the objects within each layer instance are wired differently, implementing different traversals. Depending on the focus type, each layer may answer the getSuperclass(type) question differently, even for the same argument.
The first bullet answers how these layers are integrated into a system: Conceptually we are speaking about the same Java model elements (IType), but we superimpose different graph structure depending on our current context.
but in each layer these objects are connected in a specific way as suites for the task at hand.
Inside the hierarchy layer, we actually do not handle IType instances directly, but we have
roles that represent one given IType each. Those roles contain all the inheritance links needed for answering the various questions about inheritance relations (direct/indirect, explicit/implicit, super/sub).
A cool thing about Object Teams is, that having different sets of objects in different layers (
teams) doesn’t make the program more complex, because I can pass an object from one layer into methods of another layer and the language will quite automagically translate into the object that sits at the other end of that red line in the picture above. Although each layer has its own view, they “know” that they are basically talking about the same stuff (sounds like real life, doesn’t it?).
Summing up
OK, I haven’t shown any code of the new hierarchy implementation (yet), but here’s a sketch of before-vs.-after:
- Code Size
- The new implementation of the hierarchy engine has about half the size of the previous implementation (because it need not repeat anything that’s already implemented in the Java hierarchy).
- Integration
- The previous implementation had to be individually integrated into each client module that normally uses Java hierarchies and then should use an OT hierarchy instead. After the re-implementation, the OT hierarchy is transparently integrated such that no clients need to be adapted (accounting for even more code that could be discarded).
- Linearization
- Using the new implementation,
getSuperclass()answers the correct, context sensitive linearization, as shown in the screenshot above, which the old implementation failed to solve. - Region based hierarchies
- The old implementation was incompatible with building a hierarchy for a region. For the new implementation it doesn’t matter whether it’s built for a single focus type or for a region, so, many clients now work better without any additional efforts.
The previous implementation only scratched at the surface – literally worked around the actual issue (which is: the Java type hierarchy is not aware of OT/J implicit inheritance). The new solution solves the issue right at its core: the new team OTTypeHierarchies assists the original type hierarchy (such that its answers indeed respect OT/J’s implicit inheritance). By performing this adaptation at the issue’s core, the solution automatically radiates to all clients. So I expect that investing a few days in re-writing the implementation will pay off in no time. Especially, improving the (already strong) refactoring support for OT/J is now much, much easier.
Moving your solution into the core could easily result in a design were a few bloated and tangled core modules do all the work, mocking the very idea of modularity. This can be avoided by a technology that is based on some concept of perspectives and self-contained layers, as supported by teams in OT/J.
Need I say, how much fun this re-write was? ![]()
Object Teams Final 0.7.0
On a day like this (2010/07/07), it should be evident what is better than one or a few stars: a strong team!
But when you look at what happens in your software at runtime, all you see is a soup of individuals (called objects) running around all over the place (remember: standard module systems do not create boundaries around runtime objects!).
In all humbleness, are you surprised to learn that it was a German invention back in 2002, that objects should team up?
the Object Teams Development Tooling 0.7.0 is released!
(supersedes version 1.4.0 from objectteams.org)
This is the first release after the move of the project from objectteams.org to Eclipse.org, at what point it is time to express a big thank you to all who helped along the way, Mentors, EMO, Legal, the Tools-PMC, and - of course - the many Contributors. This is: a team-effort!
Now you might say: that’s a pretty scattered team: some people at the Eclipse Foundation in Ottawa, some students in Berlin, people from Austin, and where-not. But that’s actually the point about a team: you start from a set of individuals who initially do not necessarily have any particular relationship. Then you create a team where each individual takes one particular role. This means you further specialize these existing individuals (you don’t want a team of 11 goal keepers, would you? Even with a Manual Neuer giving a perfect forward pass, it takes a Miroslav Klose to make the goal). And then you unite all members of the team towards a common goal, giving the team a new identity, so that team acts like one.
Still, each team member brings into the team the strengths of his particular background, meaning: the individuals do not completely disappear, but some properties of the individuals shine through when they play their roles in the team.
Now, what’s that got to do with software?
Given you already have a core of an application implemented, and now it’s your task to implemented one or two more user stories on top of the existing code. You look at the existing classes and mark those that in some way or other are related to what you need to implement. One user story relates to all classes marked red, another one to those marked greenish etc (and do expect overlap):
How do you implement the user story that involves all the red classes, such that the new implementation sits in a nice new module that concentrates on only this one task/user story?
Consider the red entities as plain individuals, they don’t know about the new task they should contribute to. Also keep in mind, that not all instances of those red classes will participate in the new user story. What we need to do is: specialize a few of those individuals so they can play particular roles wrt the new task and unite those roles within a new team.
If you live in flat-land, this is tremendously difficult, but if you’re able to just add one more dimension to the picture …
… the solution is very straight forward:
Now:
- The implementation of the red user story is a strong, cohesive
team - Its members are
roles specialized in their particular sub-tasks. - Each role relates (↓) to one individual from the application core and specializes what is already given towards what the team requires.
- How exactly each role relates to its base is declared using two kinds of atomic bindings: callout and callin method bindings (see, e.g., this post).
- These roles only affect the system as long as the team context is active, and activation happens per team instance (with options for fine-tuning).
- Other teams may be formed for other purposes / user stories (see the greenish team)
- Even if you start already with this 3-D picture, with Object Teams you can always add one more dimension to your architecture, if needed.







