The Object Teams Blog

Adding team spirit to your objects.

Archive for the ‘Examples’ Category

Runtime Specialization – At Last

with one comment

Between a rock and a hard place

Not long ago, I had to pull Object Teams out of the Eclipse simultaneous release train. Reason: the long standing issue of using BCEL for bytecode weaving, for which no Java 8 compatible version has yet been released. With the Eclipse platform moving to Java 8, this had escalated to a true blocker. During the last weeks I investigated two options in parallel:

  • Upgrade BCEL to a release candidate of the upcoming 6.0 release.
  • Finalize the alternative weaver for OT/J, which is based on ASM, and thus already capable of handling Java 8 byte codes

I soon found out that even BCEL 6.0 will not be a full solution, because it still has no real support for creating StackMapTable attributes for newly generated bytecode, which however is strictly mandatory for running on a JVM 8.

For that reason I then focussed on the OTDRE, the Object Teams Dynamic Runtime Environment. This has been announced long ago, and after all, I promised to show a sneak preview of this feature in my presentation at EclipseCon Europe:

Runtime Specialization
Java has never been so dynamic before

Success at last

Today I can report success in two regards:

  • The Object Teams Development Tooling, which itself is a complex OT/J application, can (mostly) run on the new runtime!
  • I created a first demo example that shows the new capability of runtime weaving in action – it works! 🙂

This is a major milestone! Running OTDT on top of OTDRE is a real stress test for that new component – once again I realize that dog-fooding an entire IDE on its own technology is quite an exciting exercise. While a few exceptions need to be ironed out before the Neon release, I’m confident now, that we’re finally and really on the home stretch of this effort.

But OTDRE is not just a replacement for the traditional runtime, it is also way cooler, as the second success story shows: it is indeed possible now, to throw new teams and roles into a running application. If the application has been generically prepared for this task, the new teams can be automatically activated and immediately start adapting the running application – no specific preplanning needed. With this we are able to achieve a level of dynamism that typically is only possible with dynamic languages. And all this without any compromise to static typing and analysability. This is probably too cool to be allowed.

And after all the hard work on Java 8, also OT/J can finally fully leverage the new version, not only in theory, but also in bytecode.

Less than one week to finalize the presentation. You can be sure this will be a fresh story. Join me on Wednesday, Nov 4,  in Ludwigsburg:

Runtime Specialization - Java has never been so dynamic before -- Session at EclipseCon Europe 2015

PS: The “traditional” Object Teams Runtime Environment isn’t dead, yet. I really want to keep it as an option, because both variants (OTRE / OTDRE) have quite different characteristics, and after all this component has matured over more than 10 years. But with one option already (mostly) working, I can probably wait until a proper release of BCEL 6.0, and still have it back in game before the Neon release.

Advertisements

Written by Stephan Herrmann

October 27, 2015 at 23:05

Compiling OT/Equinox projects using Tycho

with 3 comments

In a previous post I showed how the tycho-compiler-jdt Maven plug-in can be used for compiling OT/J code with Maven.

Recently, I was asked how the same can be done for OT/Equinox projects. Given that we were already using parts from Tycho, this shouldn’t be so difficult, right?

Once you know the solution, finding the solution is indeed easy, also in this case. Here it is:

We use almost the same declaration as for plain OT/J applications:

    <pluginManagement>
	<plugin>
	    <groupId>org.eclipse.tycho</groupId>
	    <artifactId>tycho-compiler-plugin</artifactId>
	    <version>${tycho.version}</version>
	    <extensions>true</extensions>
	    <dependencies>
		<dependency>
		    <groupId>org.eclipse.tycho</groupId>
		    <artifactId>tycho-compiler-jdt</artifactId>
		    <version>${tycho.version}</version>
		    <exclusions>
			<!-- Exclude the original JDT/Core to be replaced by the OT/J variant: -->
			<exclusion>
			    <groupId>org.eclipse.tycho</groupId>
			    <artifactId>org.eclipse.jdt.core</artifactId>
			</exclusion>
		    </exclusions>
		</dependency>
		<dependency>
		    <!-- plug the OT/J compiler into the tycho-compiler-jdt plug-in: -->
		    <groupId>org.eclipse</groupId>
		    <artifactId>objectteams-otj-compiler</artifactId>
		    <version>${otj.version}</version>
		</dependency>
	    </dependencies>
	</plugin>
    </pluginManagement>

So, what’s the difference? In both cases we need to adapt the tycho-compiler-jdt plug-in because that’s where we replace the normal JDT compiler with the OT/J variant. However, for plain OT/J applications tycho-compiler-jdt is pulled in as a dependency of maven-compiler-plugin and must be adapted on this path of dependencies, whereas in Tycho projects tycho-compiler-jdt is pulled in from tycho-compiler-plugin. Apparently, the exclusion mechanism is sensitive to how exactly a plug-in is pulled into the build. Interesting.

Once I figured this out, I created and published a new version of our Maven support for Object Teams: objectteams-parent-pom:2.1.1 — publishing Maven support for Object Teams 2.1.1 was overdue anyway 🙂

With the updated parent pom, a full OT/Equinox hello world pom now looks like this:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <parent>
        <!-- We use Object Teams: -->
        <groupId>org.eclipse</groupId>
        <artifactId>objectteams-parent-pom</artifactId>
        <version>2.1.1</version>
    </parent>
 
    <artifactId>OTEquinox-over-tycho</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <!-- We are building an Eclipse plug-in (or OSGi bundle): -->
    <packaging>eclipse-plugin</packaging>
 
    <repositories>
 
        <!-- This is where we get all Object Teams stuff from: -->
        <repository>
            <id>ObjectTeamsRepository</id>
            <name>Object Teams Repository</name>
            <url>http://download.eclipse.org/objectteams/maven/3/repository</url>
        </repository>
 
        <!-- Add any p2 repositories needed for your application, e.g.: -->
        <repository>
            <id>Juno</id>
            <name>Eclipse Juno Repository</name>
            <url>http://download.eclipse.org/releases/juno</url>
            <layout>p2</layout>
        </repository>
    </repositories>
 
    <build>
        <plugins>
            <plugin>
                <!-- We build this project using Tycho: -->
                <groupId>org.eclipse.tycho</groupId>
                <artifactId>tycho-maven-plugin</artifactId>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
</project>

Looks pretty straight forward, right?

To see the full OT/Equinox Hello World Example configured for Maven/Tycho simply import OTEquiTycho.zip as a project into your workspace.

cheers,
Stephan

Written by Stephan Herrmann

October 31, 2012 at 00:16

Using git for an interactive video – Replay the JDT tutorial

with 2 comments

When preparing the tutorial How to train the JDT dragon, Ayushman and me packed way more material than we could possible teach in 3 hours time.

Luckily, Ayush came up with an idea that enables all of you to go through the exercise all on your own: instead of creating zip files with various stages of the example projects, we pushed everything to github. I apologize to those who were overwhelmed by how we pushed git onto the tutorial participants in Reston.

Now, as EclipseCon is over, here’s what you can do:

  • Fetch the slides: PDF or slideshare
  • Clone the material for the plain JDT part (git: URL), containing two projects for the first two exercises.
    • org.eclipsecon2012.jdt.tutorial1: traverse the Java Model starting from the element selected in the UI
    • org.eclipsecon2012.jdt.quickFix1: implement a quickfix for adding a missing null check
  • Clone the misc repo (git: URL), containing
    • handouts: instructions for the exercises
    • org.eclipsecon2012.jdt.populator: plug-in that was used in the tutorial to create sample content in the runtime workbench; show cases how to programmatically create Java files from String content
  • Clone the OT repo (git: URL), containing
    • AntiDemo: the OT/Equinox hello-world: prohibition of class names starting with “Foo”.
    • Reachability: a full blown reachability analysis in < 300 LOC.

The last exercise, “Reachability”, we couldn’t even show in Reston, but luckily this is the most detailed repo: in 13+1 commits I recorded the individual steps of adding inter-procedural reachability analysis piggy-back on top of the JDT compiler. If you replay these commits from the git repo you can watch me creating this little plug-in from scratch. Starting from step 5 you’ll be able to see the results when you fire up a runtime workbench: the analysis will print to stdout what methods it found during each full build.

Look at the commit comments which summarize what I would have explained in demo mode. Still the material is pretty dense as it explains three technologies at the same time:

  1. How does this analysis work?
  2. What points in the JDT do we hook onto?
  3. How is the integration achieved using Object Teams.

Speaking of integration: using the “Binding Editor” you can see all bindings in a tabular view:

Bindings of the Reachability plug-in

The right hand side of the table give the full list of JDT elements we connect to:

  • classes that are extended using a role_obj role
  • methods/fields that are accessed externally via a callout binding callout binding
  • methods that are intercepted using a callin binding (after) callin binding.

As a special bonus, step 14 in the git repo shows how to add problem markers for each unreachable method, so that the JDT will actually offer its existing quickfix for removing:
Unreachable methods
(Yep, both methods are detected as unreachable: calling each other without being called from another reachable method doesn’t help).

I hope you enjoy playing with the examples. For questions please use one of the forums:

Written by Stephan Herrmann

April 7, 2012 at 15:20

The Essence of Object Teams

leave a comment »

When I write about Object Teams and OT/J I easily get carried away indulging in cool technical details. Recently in the Object Teams forum we were asked about the essence of OT/J which made me realize that I had neglected the high-level picture for a while. Plus: this picture looks a bit different every time I look at it, so here is today’s answer in two steps: short and extended.

Short version:

OT/J adds to OO the capability to define a program in terms of multiple perspectives.

Extended version:

In software design, e.g., we are used to describing a system from multiple perspectives or views, like: structural vs. behavioral views, architectural vs. implementation views, views focusing on distribution vs. business logic, or just: one perspective per use case.

A collage of UML diagrams

© 2009, Kishorekumar 62, licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license.

In regular OO programming this is not well supported, an object is defined by exactly one class and no matter from which perspective you look at it, it always has the exact same properties. The best we can do here is controlling the visibility of methods by means of interfaces.

A person is a person is a person!?

By contrast, in OT/J you start with a set of lean base objects and then you may attach specific roles for each perspective. Different use cases and their scenarios can be implemented by different roles. Visualization in the UI may be implemented by another independent set of roles, etc.

A base seen from multiple perspectives via roles.

Code-level comparison?

I’ve been asked to compare standard OO and OT/J by direct comparison of code examples, but I’m not sure if it is a good idea to do, because OT/J is not intended to just provide a nicer syntax for things you can do in the same way using OO. OT/J – as any serious new programming language should do IMHO – wants you to think differently about your design. For example, we can give an educational implementation of the Observer pattern using OT/J, but once you “think Object Teams” you may not be interested in the Observer pattern any more, because you can achieve basically the same effect using a single callin binding as shown in our Stopwatch example.

So, positively speaking, OT/J wants you to think in terms of perspectives and make the perspectives you would naturally use for describing the system explicit by means of roles.

OTOH, a new language is of course only worth the effort if you have a problem with existing approaches. The problems OT/J addresses are inherently difficult to discuss in small examples, because they are:

  1. software complexity, e.g., with standard OO finding a suitable decomposition where different concerns are not badly tangled with each other becomes notoriously difficult.
  2. software evolution, e.g., the initial design will be challenged with change requests that no-one can foresee up-front.

(Plus all the other concerns addressed)

Both, theory and experience, tell me that OT/J excels in both fields. If anyone wants to challenge this claim using your own example, please do so and post your findings, or lets discuss possible designs together.

One more essential concept

I should also mention the second essence in OT/J: after slicing elements of your program into roles and base objects we also support to re-group the pieces in a meaningful way: as roles are contained in teams, those teams enable you to raise the level of abstraction such that each user-relevant feature, e.g., can be captured in exactly one team, hiding all the details inside. As a result, for a high-level design view you no longer have to look at diagrams of hundreds of classes but maybe just a few tens of teams.

Hope this helps seeing the big picture. Enough hand-waving for today, back to the code! 🙂

Written by Stephan Herrmann

September 20, 2011 at 15:39

Follow-up: Object Teams Tutorial at EclipseCon 2011

leave a comment »

At our EclipseCon tutorial we mentioned a bonus excercise, for which we didn’t have the time at the tutorial.

Now it’s time to reveal the solution.

Task

Implement the following demo-mode for the JDT:

• When creating a Java project let the user select:
❒ Project is for demo purpose only
• When creating a class in a Demo project:
insert class name as “Foo1”, “Foo2” …”

So creating classes in demo mode is much easier, and you’ll use the names “Foo1″… anyway 🙂
(See also our slides (#39)).

Granted, this is a toy example, yet it combines a few properties that I frequently find in real life and which cause significant pains without OT/J:

  • The added behavior must tightly integrate with existing behavior.
  • The added behavior affects code at distant locations,
    here two plug-ins are affected: org.eclipse.jdt.ui and org.eclipse.jdt.core.
  • The added behavior affects execution at different points in time,
    here creation of a project plus creation of a class inside a project.
  • The added behavior requires to maintain more state at existing objects,
    here a JavaProject must remember if it is a demo project.

Despite these characteristics the task can be easily described in a few English sentences. So the solution should be similarly concise and delivered as a single coherent piece.

Strategy

With a little knowledge about the JDT the solution can be outlined as this

  • Add a checkbox to the New Java Project wizard
  • When the wizard creates the project mark it as a demo project if the box is checked.
  • Let the project also count the names of Foo.. classes it has created.
  • When the new class wizard creates a class inside a demo project pre-set the generated class name and make the name field unselectable.

From this we conclude the need to define 4 roles, playedBy these existing types:

  • org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageOne.NameGroup:
    the wizard page section where the project name is entered and where we want to add the checkbox.
  • org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo:
    the part of the wizard that triggers setup of the JavaProject.
  • org.eclipse.jdt.core.IJavaProject:
    this is where we need to add more state (isDemoProject and numFooClasses).
  • org.eclipse.jdt.ui.wizards.NewTypeWizardPage:
    this is where the user normally specifies the name for a new class to be created.

Note, that 3 classes in this list resided in org.eclipse.jdt.ui, but IJavaProject is from org.eclipse.jdt.core, which leads us to the next step:

Plug-in configuration

Our solution is developed as an OT/Equinox plug-in, with the following architecture level connections:

This simply says that the same team demohelper.ProjectAdaptor is entitled to bind roles to classes from both org.eclipse.jdt.ui and org.eclipse.jdt.core.
One more detail in these extensions shouldn’t go unmentioned: Don’t forget to set “activation: ALL_THREADS” for the team (otherwise you won’t see any effect …).

Now we’re ready to do the coding.

Implementing the roles

protected class DialogExtender playedBy NameGroup {
 
        protected SelectionButtonDialogField isDemoField;
 
        void createControl(Composite parent) <- after Control createControl(Composite composite)
                with { parent <- (Composite) result }
 
        private void createControl(Composite parent) {
                isDemoField= new SelectionButtonDialogField(SWT.CHECK);
                isDemoField.setLabelText("Project is for demo purpose only");
                isDemoField.setSelection(false);
                isDemoField.doFillIntoGrid(parent, 4);
        }
}
 

Our first role adds the checkbox. The implementation of createControl is straight-forward UI business. Lines 22,23 hook our role method into the one from the bound base class NameGroup. After the with keyword, we are piping the result from the base method into the parameter parent of the role method (with a cast). This construct is a parameter mapping.

Here’s the result:

Next we want to store the demo-flag to instances of IJavaProject, so we write this role:

protected class EnhancedJavaProject playedBy IJavaProject {
 
        protected boolean isDemoProject;
        private int numFooClasses = 1;
 
        protected String getTypeName() {
                return "Foo"+(numFooClasses++);
        }
}
 

Great, now any IJavaProject can play the role EnhancedJavaProject which holds the two additional fields, and we can automatically serve an arbitrary number of class names Foo1 …
In the IDE you will actually see a warning, telling you that binding a role to a base interface currently imposes a few restrictions, but these don’t affect us in this example.

Next comes a typical question: how to transfer the flag from role DialogExtender to role EnhancedJavaProject?? The roles don’t know about each other nor do the bound base classes. The answer is: use a chain of references.

protected class FirstPage playedBy NewJavaProjectWizardPageOne {
 
        DialogExtender getFNameGroup() -> get NameGroup fNameGroup;
 
        protected boolean isDemoProject() {
                return getFNameGroup().isDemoField.isSelected();
        }
}
 
protected class WizardExtender playedBy NewJavaProjectWizardPageTwo {
 
        FirstPage getFFirstPage() -> get NewJavaProjectWizardPageOne fFirstPage;
 
        markDemoProject <- after initializeBuildPath;
        private void markDemoProject(EnhancedJavaProject javaProject) {
                if (getFFirstPage().isDemoProject())
                        javaProject.isDemoProject = true;
        }
}
 
 

Role WizardExtender intercepts the event when the wizard initializes the IJavaProject (line 46). Method initializedBuildPath receives a parameter of type IJavaProject but the OT/J runtime transparently translates this into an instance of type EnhancedJavaProject (this – statically type safe – operation is called lifting). Another indirection is needed to access the checkbox: The base objects are linked like this:

NewJavaProjectWizardPageTwo —fFirstPage—> NewJavaProjectWizardPageOne —fNameGroup—> NameGroup

This link structure is lifted to the role level by the callout bindings in lines 35 and 44.

We’re ready for our last role:

protected class NewTypeExtender playedBy NewTypeWizardPage {                                                              
                                                                                          
        void setTypeName(String name, boolean canBeModified) -> void setTypeName(String name, boolean canBeModified);                                                                      
                                                                                          
        void initTypePage(EnhancedJavaProject prj) <- after void initTypePage(IJavaElement element)
                with { prj <- element.getJavaProject() }
 
        private void initTypePage(EnhancedJavaProject prj) {
                if (prj.isDemoProject)
                        setTypeName(prj.getTypeName(), false);
        }
}
 

Here we intercept the initialization of the type page of a New Java Project wizard (lines 66,67). Another parameter mapping is used to perform two adjustments in one go: fetch the IJavaProject from the enclosing element and lift it to its EnhancedJavaProject role. This follows the rule-of-thumb that base-type operations (like navigating from IJavaElement to IJavaProject) should happen at the right hand side, so that we are ready to lift the IJavaProject to EnhancedJavaProject when the data flow enters the team.

The EnhancedJavaProject can now be asked for its stored flag (isDemoProject) and it can be asked for a generated class name (getTypeName()). The generated class name is then inserted into the dialog using the callout binding in line 64. Looks like this:

See this? No need to think of a good class name 🙂

Wrap-up

So that’s it. All these roles are collected in one team class and here is the fully expanded outline:

All this is indeed one concise and coherent module. In the tutorial I promised to do this no more than 80 LOC, and indeed the team class has 74 lines including imports and white space.

Or, if you are interested just in how this module connects to the existing implementation, you may use the “binding editor” in which you see all playedBy, callout and callin bindings:

The full sources are also available for download.

have fun

Written by Stephan Herrmann

April 14, 2011 at 21:14

Null annotations: prototyping without the pain

with 3 comments


So, I’ve been working on annotations @NonNull and @Nullable so that the Eclipse Java compiler can statically detect your NullPointerExceptions already during compile time (see also bug 186342).

By now it’s clear this new feature will not be shipped as part of Eclipse 3.7, but that needn’t stop you from trying it, as I have uploaded the thing as an OT/Equinox plugin.

Behind the scenes: Object Teams


Today’s post shall focus on how I built that plugin using Object Teams, because it greatly shows three advantages of this technology:

  • easier maintenance
  • easier deployment
  • easier development


Before I go into details, let me express a warm invitation to our EclipseCon tutorial on Thursday morning. We’ll be happy to guide your first steps in using OT/J for your most modular, most flexible and best maintainable code.

Maintenance without the pain

It was suggested that I should create a CVS branch for the null annotation support. This is a natural choice, of course. I chose differently, because I’m tired of double maintenance, I don’t want to spend my time applying patches from one branch to the other and mending merge conflicts. So I avoid it wherever possible. You don’t think this kind of compiler enhancement can be developed outside the HEAD stream of the compiler without incurring double maintenance? Yes it can. With OT/J we have the tight integration that is needed for implementing the feature while keeping the sources well separated.

The code for the annotation support even lives in a different source repository, but the runtime effect is the same as if all this already were an integral part of the JDT/Core. Maybe I should say, that for this particular task the integration using OT/J causes a somewhat noticable performance penalty. The compiler does an awful lot of work and hooking into this busy machine comes at a price. So yes, at the end of the day this should be re-integrated into the JDT/Core. But for the time being the OT/J solution well serves its purpose (and in most other situations you won’t even notice any impact on performance plus we already have further performance improvements in the OT/J runtime in our development pipeline).

Independent deployment

Had I created a branch, the only way to get this to you early adopters would have been via a patch feature. I do have some routine in deploying patch features but they have one big drawback: they create a tight dependency to the exact version of the feature which you are patching. That means, if you have the habit of always updating to the latest I-build of Eclipse I would have to provide a new patch feature for each individual I-build released at Eclipse!

Not so for OT/Equinox plug-ins: in this particular case I have a lower bound: the JDT/Core must be from a build ≥ 20110226. Other than that the same OT/J-based plug-in seemlessly integrates with any Eclipse build. You may wonder, how can I be so sure. There could be changes in the JDT/Core that could break the integration. Theoretically: yes. Actually, as a JDT/Core committer I’ll be the first to know about those changes. But most importantly: from many years’ experience of using this technology I know such breakage is very seldom and should a problem occur it can be fixed in the blink of an eye.

As a special treat the OT/J-based plug-in can even be enabled/disabled dynamically at runtime. The OT/Equinox runtime ships with the following introspection view:

Simply unchecking the second item dynamically disables all annotation based null analysis, consistently.

Enjoyable development

The Java compiler is a complex beast. And it’s not exactly small. Over 5 Mbytes of source spread over 323 classes in 13 packages. The central package of these (ast) comprising no less than 109 classes. To add insult to injury: each line of this code could easily get you puzzling for a day or two. It ain’t easy.

If you are a wizard of the patches feel free to look at the latest patch from the bug. Does that look like s.t. you’d like to work on? Not after you’ve seen how nice & clean things can be, I suppose.

First level: overview

Instead of unfolding the package explorer until it shows all relevant classes (at what time the scrollbar will probably be too small to grasp) a quick look into the outline suffices to see everything relevant:

Here we see one top-level class, actually a team class. The class encapsulates a number of role classes containing the actual implementation.

Navigation to the details

Each of those role classes is bound to an existing class of the compiler, like:

   protected class MessageSend playedBy MessageSend { ...
(Don’t worry about identical names, already from the syntax it is clear that the left identifier MessageSend denotes a role class in the current team, whereas the second MessageSend refers to an existing base class imported from some other package).

Ctrl-click on the right-hand class name takes you to that base class (the packages containing those base classes are indicated in the above screenshot). This way the team serves as the single point of reference from which each affected location in the base code can be reached with a single mouse click – no matter how widely scattered those locations are.

When drilling down into details a typical roles looks like this:

The 3 top items are  “callout” method bindings providing access to fields or methods of the base object. The bottom item is a regular method implementing the new analysis for this particular AST node, and the item above it defines a  “callin” binding which causes the new method to be executed after each execution of the corresponding base method.

Locality of new information flows

Since all these roles define almost normal classes and objects, additional state can easily be introduced as fields in role classes. In fact some relevant information flows of the implementation make use of role fields for passing analysis results directly from one role to another, i.e., the new analysis mostly happens by interaction among the roles of this team.

Selective views, e.g., on inheritance structures

As a final example consider the inheritance hierarchy of class Statement: In the original this is a rather large tree:

Way too large actually to be fully unfolded in a single screenshot. But for the implementation at hand most of these
classes are irrelevant. So at the role layer we’re happy to work with this reduced view:


This view is not obtained by any filtering in the IDE, but that’s indeed the real full inheritance tree of the role class Statement. This is just one little example of how OT/J supports the implementation of selective views. As a result, when developing the annotation based null analysis, the code immediately provides a focused view of everything that is relevant, where relevance is directly defined by design intention.

A tale from the real world

I hope I could give an impression of a real world application of OT/J. I couldn’t think of a nicer structure for a feature of this complexity based on an existing code base of this size and complexity. Its actually fun to work with such powerful concepts.

Did I already say? Don’t miss our EclipseCon tutorial 🙂

Hands-on introduction to Object Teams

See you at

Written by Stephan Herrmann

March 14, 2011 at 00:18

Get for free what Coin doesn’t buy you

with 2 comments

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 Medal Java Extensions
…install and restart, and you’re ready to use your “Medal” IDE:
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”:
Boss Key
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:
Extension
which the package explorer will render as:
Viewed in the Package Explorer
Drilling into the Team class ThrowString you’ll see:
ThrowString Outline
The Team class contains two Role classes:

  • Role DontReport binds to class ProblemReporter (not shown in the Outline), intercepts calls to ProblemReporter.cannotThrowType and if the type in question is String, simply ignores the “error”
  • Role Generate binds to class ThrowStatement to make sure the correct bytecodes for creating a RuntimeException are generated

Also, in the Outline you see both kinds of method bindings that are supported by Object Teams:

  • getExceptionType/setExceptionType are getter/setter definitions for field ThrowStatement.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(&quot;basecall&quot;)
        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):
Compare Menu
which gives you this compare editor:
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 &amp; 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.

Written by Stephan Herrmann

September 12, 2010 at 13:31