I must admit I haven’t been able to do as much as I had hoped during the last two days, but I did experiment with a new, more flexible format for the annotations. It’s a bit more verbose, but it essentially gives me what I had wanted (see end of this posting).
The preferred (and most future-proof) way of specifying threads now uses the value
element, an array of @ThreadDesc
annotations. The choice of value
as name has the advantage that the programmer can drop the value=
part if only the value
element is assigned to. The @ThreadDesc
annotation now contains the four elements name
, id
, group
and eventThread
(notice singular form on the first three), but only one of the four may be used at the same time, i.e. @ThreadDesc(name="foo")
and @ThreadDesc(id=5)
are legal, but @ThreadDesc(name="foo",id=5)
is not.
The old elements of @NotRunBy
and @OnlyRunBy
, i.e. threadNames
, threadIds
, threadGroups
and eventThread
are still available and can be mixed with the new value
element in any way, as long as anything regarding the event thread is not specified more than once, like in the following (illegal) annotation: @OnlyRunBy(eventThread=true, value=@ThreadDesc(eventThread=true))
.
Here are some examples of the new style:
@NotRunBy({@ThreadDesc(name="bar"), @ThreadDesc(id=1)})
@NotRunBy({@ThreadDesc(name="main"), @ThreadDesc(name="fum")})
@OnlyRunBy(@ThreadDesc(eventThread=true))
@OnlyRunBy(value={@ThreadDesc(name="main3"), @ThreadDesc(group="foo")},
threadGroups={"bar"}, threadIds={3, 4})
The major advantage is that I can add additional elements to the @ThreadDesc
annotation, such as conditionals as discussed previously.
I also changed the way class-level annotations affect methods and floowed Corky’s advice: An annotation on a class, from now on only influences methods that were defined by that class, or are going to be defined in subclasses. Let’s look at a quick example:
abstract class Base {
@OnlyRunBy(eventThread=true)
public abstract void run();
public abstract void doSomething();
}
public boolean equals(Object other) { ... }
In this class only the run
method is annotated (and all methods in subclasses); >doSomething
is not annotated.
Let’s look at a subclass:
@OnlyRunBy(eventThread=true)
class Sub extends Base {
public void run() { ... }
public void doSomething() { ... }
public abstract void doSomethingElse() { ... }
}
Here, we have a class-level annotation: In my initial version, this annotation would have applied to all three methods in the Sub
class; however, that caused a lot of warnings if subtyping was taken seriously. Now the annotation only applies to the doSomethingElse
method, because both run
and doSomething
were already defined in the Base
class. The Sub.run
method nonetheless is annotated to allow only the event thread to run since Base.run
is annotated with @OnlyRunBy(eventThread=true)
and that applies to all subclasses as well.