It would be nice to define a plain Java interface using @Data

3,257 views
Skip to first unread message

canwilf

unread,
Jun 18, 2010, 5:18:24 PM6/18/10
to Project Lombok
I would like to define interfaces as conveniently using @Data.

Could there be a rule so that if @Data was used on an interface it
would make
standard set get interface statements?

Thanks,
Canwilf

PS Great Project!

@Data
public interface Hello {
String hello
}


Would transform to:

public interface Hello {
String getHello();
void setHello(String s)
}



Reinier Zwitserloot

unread,
Jun 18, 2010, 9:36:07 PM6/18/10
to Project Lombok
No can do, unfortunately. We have to start with legal java, and
"String hello" in an interface isn't legal. Even if a semi-colon is
added, it's still not legal; fields in interfaces are implicitly
public, static, and final, and public static final fields require a
value for initialization. Technically we COULD add these methods if
you wrote:

@Data
public interface Hello {
String hello = "dummy";
}

but there's no way for us to tell the difference between a field that
exists only as a pointer to generate getter/setter for it, and as an
actual interface-based constant.

canwilf

unread,
Jun 19, 2010, 1:20:46 AM6/19/10
to Project Lombok
How about if it was a plain method without get/set and a rule that any
get/set would not be modified:

@Data
public interface Hello {
String hello();
int getAge();
}

Would become:

public interface Hello {

String getHello();
void setHello(String hello);

int getAge();
}

Wilf

Maaartin-1

unread,
Jun 19, 2010, 1:58:29 AM6/19/10
to project...@googlegroups.com
On 10-06-19 03:36, Reinier Zwitserloot wrote:
> No can do, unfortunately. We have to start with legal java, and
> "String hello" in an interface isn't legal. Even if a semi-colon is
> added, it's still not legal; fields in interfaces are implicitly
> public, static, and final, and public static final fields require a
> value for initialization. Technically we COULD add these methods if
> you wrote:
>
> @Data
> public interface Hello {
> String hello = "dummy";
> }
>
> but there's no way for us to tell the difference between a field that
> exists only as a pointer to generate getter/setter for it, and as an
> actual interface-based constant.
>

I've never seen a declaration like this, in fact I haven't known it was
possible. Everybody writes "public final static" for defining a
constant. So the rule could be to generate getter/setter for everything
declared without "static" and to do nothing if "static" is present. This
assumes you can find out if static was explicitly given.

Maybe the approach converting plain methods without get/set into
properties is nicer, but what if there's a method you want to keep it as
is? Annotating it with @Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE) is not very nice.

Reinier Zwitserloot

unread,
Jun 19, 2010, 2:08:24 AM6/19/10
to project...@googlegroups.com
We can find out if it was explicitly given, but this is obviously a no go. It may not be particularly common, but it's legal, and folks do it. If lombok were to take their fields and add getX and setX methods, those who use this constants technique would be completely caught out and think lombok's severely broken. We can't do this.

Same goes for trying to convert "String hello();" - how is lombok supposed to figure out this isn't a normal interface method, and instead something that should be turned into get/set?

If we're ever going to support this it'll likely be by way of annotating something or other with @Getter and @Setter. However, this feels rather low priority - adding get/set to interfaces is far rarer than classes, and its going to be a lot more confusing.

--Reinier Zwitserloot




--
You received this message because you are subscribed to the Google
Groups group for http://projectlombok.org/

To post to this group, send email to project...@googlegroups.com
To unsubscribe from this group, send email to
project-lombo...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/project-lombok?hl=en

Maaartin-1

unread,
Jun 21, 2010, 4:22:02 PM6/21/10
to project...@googlegroups.com
On 10-06-19 08:08, Reinier Zwitserloot wrote:
> We can find out if it was explicitly given, but this is obviously a no
> go. It may not be particularly common, but it's legal, and folks do
> it. If lombok were to take their fields and add getX and setX methods,
> those who use this constants technique would be completely caught out
> and think lombok's severely broken. We can't do this.

I'd say this simply can't happen. When anybody places @Data on an
interface, they must this about it a bit. Using this syntax the only
possibility to get @Data do anything is replacing dummy members by
setters and getters, so there's no surprising disappearing of fields.
The possibility to prevent this behavior by explicitly using "static"
makes it fully usable. However it's not nice.

> Same goes for trying to convert "String hello();" - how is lombok
> supposed to figure out this isn't a normal interface method, and
> instead something that should be turned into get/set?

Agreed.

> If we're ever going to support this it'll likely be by way of
> annotating something or other with @Getter and @Setter.

I have a possibly better proposal: Annotating the class with @Getter
adds a getter to each given setter. Annotating with @Setter works the
other way round. So nothing disappers and it's about the same like for
classes; the only difference is that the starting point is an accessor
instead of a field, which is obviously necessary.

> However, this feels rather low priority - adding get/set to interfaces
> is far rarer than classes, and its going to be a lot more confusing.

Agreed.

Reinier Zwitserloot

unread,
Jun 21, 2010, 4:53:36 PM6/21/10
to project...@googlegroups.com
Heh, I came to the same conclusion as you did independently: Continue not allowing @Data on interfaces, but allow @Getter and @Setter.

We could accept:

"int hello;"

as signalling the need to create getHello and setHello, and subsequently delete the field. Without lombok such code wouldn't compile (field is implicit public static final and thus needs to be initialized with something), but that's only an advantage. Seems like the clear better choice over:

"int hello();"

I presume you (canwilf, Maaartin) agree with this assessment, or did I miss something?

If it looks good, add an issue and we'll tackle it at the same time we make "@Setter" and "@Getter" legal on classes.

--Reinier Zwitserloot



canwilf

unread,
Jun 21, 2010, 11:05:54 PM6/21/10
to Project Lombok
I'd prefer:

@Property int hello;

vs @Getter @Setter int hello;

What do you think?


On Jun 21, 4:53 pm, Reinier Zwitserloot <rein...@zwitserloot.com>
wrote:
> Heh, I came to the same conclusion as you did independently: Continue not
> allowing @Data on interfaces, but allow @Getter and @Setter.
>
> We could accept:
>
> "int hello;"
>
> as signalling the need to create getHello and setHello, and subsequently
> delete the field. Without lombok such code wouldn't compile (field is
> implicit public static final and thus needs to be initialized with
> something), but that's only an advantage. Seems like the clear better choice
> over:
>
> "int hello();"
>
> I presume you (canwilf, Maaartin) agree with this assessment, or did I miss
> something?
>
> If it looks good, add an issue and we'll tackle it at the same time we make
> "@Setter" and "@Getter" legal on classes.
>
> --Reinier Zwitserloot
>
> > Groups group forhttp://projectlombok.org/
>
> > To post to this group, send email to project...@googlegroups.com
> > To unsubscribe from this group, send email to
> > project-lombo...@googlegroups.com<project-lombok%2Bunsu...@googlegroups.com>

Reinier Zwitserloot

unread,
Jun 21, 2010, 11:46:34 PM6/21/10
to project...@googlegroups.com
Properties are far more complex beasts that also have change (vetoable?) listeners and other such infrastructure. We aren't tackling it just yet.

--Reinier Zwitserloot



Groups group for http://projectlombok.org/


To post to this group, send email to project...@googlegroups.com
To unsubscribe from this group, send email to
project-lombo...@googlegroups.com

canwilf

unread,
Jun 22, 2010, 11:17:56 AM6/22/10
to Project Lombok
> Properties are far more complex beasts that also have change (vetoable?)
> listeners and other such infrastructure. We aren't tackling it just yet.

Agreed.

So then, how about we confirm as a final proposal this code:

@Getter @Setter
interface Hello{
String hello;
}

becomes...

interface Hello{
String getHello();
void setHello(String hello);
}


The I can finally realize my dream of programming to interfaces
without getting arthritis from defining get/set on a bazillion
interfaces.
Maybe this should be a Java language change one day so that all
uninitialized fields in pure interfaces become accessor method
definitions!

Canwilf

On Jun 21, 11:46 pm, Reinier Zwitserloot <rein...@zwitserloot.com>
wrote:
> Properties are far more complex beasts that also have change (vetoable?)
> listeners and other such infrastructure. We aren't tackling it just yet.
>
> --Reinier Zwitserloot
>
> > <project-lombok%2Bunsu...@googlegroups.com<project-lombok%252Buns...@googlegroups.com>

Reinier Zwitserloot

unread,
Jun 22, 2010, 12:01:55 PM6/22/10
to project...@googlegroups.com
Sounds like a plan. I'm 99.5% certain we can actually do that with lombok 0.9 (the remaining 0.5% is for being unable to delete the constant in a way that doesn't screw up the compiler). Can you add an issue for this at our issue tracker, with a link to this thread? Thanks!

--Reinier Zwitserloot



Groups group for http://projectlombok.org/


To post to this group, send email to project...@googlegroups.com
To unsubscribe from this group, send email to
project-lombo...@googlegroups.com

Roel Spilker

unread,
Jun 22, 2010, 12:03:55 PM6/22/10
to project...@googlegroups.com
Hi Canwilf,

That was the idea. Apart from that, you could also specify @Getter of
@Setter on an individual field to generate or suppress the generation
of getters and setters. We might actually be able to also generate
getters and setters on uninitialized fields since that is currently
not valid Java.

Roel

> Groups group for http://projectlombok.org/


>
> To post to this group, send email to project...@googlegroups.com
> To unsubscribe from this group, send email to
> project-lombo...@googlegroups.com

Moandji Ezana

unread,
Jun 23, 2010, 8:53:24 AM6/23/10
to project...@googlegroups.com
Out of curiosity, when do you put getters and setters on interfaces? Instinctively, it feels like a code smell to me, so I was wondering what your usecase was.

Moandji

canwilf

unread,
Jun 23, 2010, 2:09:38 PM6/23/10
to Project Lombok
I have different implementations that provide the same business logic:

Book b = (Book) new BookXml() // xml element reader/writer
Book b = (Book) new BookDAO() // db access object
etc.

Book.class is the interface I can use everywhere.
But then to make Book I have Publisher, Author.
And to make those I have Contact, Address, Notes, Emails, etc.
So, all are composites of reusable interfaces.

... interface Book extends Title, ISBN, hasAuthor, hasPublisher

So, making these small grained and larger grained interfaces makes
sense and is convenient when completed.
But it is a lot of typing! Just save me having to make getNAME()
setNAME everywhere please!

Is that code smell?
Got a better way?

I'm open to suggestions.
Since you asked :-)
canwilf

Maaartin-1

unread,
Jun 23, 2010, 3:46:45 PM6/23/10
to project...@googlegroups.com
On 10-06-21 22:53, Reinier Zwitserloot wrote:
> Heh, I came to the same conclusion as you did independently: Continue
> not allowing @Data on interfaces, but allow @Getter and @Setter.
>
> We could accept:
>
> "int hello;"
>
> as signalling the need to create getHello and setHello, and subsequently
> delete the field. Without lombok such code wouldn't compile (field is
> implicit public static final and thus needs to be initialized with
> something), but that's only an advantage. Seems like the clear better
> choice over:
>
> "int hello();"
>
> I presume you (canwilf, Maaartin) agree with this assessment, or did I
> miss something?

IIRC, you said, you'd have to start with legal Java, but if you can do
this, that's perfect.

> If it looks good, add an issue and we'll tackle it at the same time we
> make "@Setter" and "@Getter" legal on classes.

Theoretically, it could be nice to have a shortcut for @Getter and
@Setter (I think this was the meaning of proposing @Property), but it's
not that important when the whole interface can be annotated.

Btw., with my annotation rewriting proposal from 2010-04-18 everybody
could define such a joint annotation themselves. But I assume, something
like this will take some time.


I suppose that

@Getter @Setter
interface I {
@Setter(Access.NONE)
int hello;
}

creates getHello() only, right? And

@Getter
interface I {
@Setter
int hello;
}

creates both getHello() and setHello(), right? Simply the more specific
annotation wins, that's flexible and consistent.

Reinier Zwitserloot

unread,
Jun 23, 2010, 4:13:33 PM6/23/10
to project...@googlegroups.com
Indeed. When I said it had to be legal java, I oversimplified - it has to pass the parser. "int hello;" in an interface won't compile but not because it can't be parsed, so we can most likely do that.

--Reinier Zwitserloot




--

Moandji Ezana

unread,
Jun 24, 2010, 3:24:23 AM6/24/10
to project...@googlegroups.com
On Wed, Jun 23, 2010 at 8:09 PM, canwilf <can...@gmail.com> wrote:
I have different implementations that provide the same business logic:

Book b = (Book) new BookXml() // xml element reader/writer
Book b = (Book) new BookDAO() // db access object
etc.

 Isn't the DAO pattern about separating the domain object from the persistence mechanism? It seems a bit odd to put them together.

Personally, I'd just have a regular Book class and pass them to a DbDAO or an XmlDAO for persistence.

I'm getting off-topic here, but is the real meaning of "programming to interfaces" about using Java Interfaces or crafting business-oriented object interfaces that are somewhat decoupled from the internal data structure? I've always assumed the latter and found Java Interfaces to be generally abused in application code. I'm open to being corrected, but from my POV, it shouldn't matter whether something is a class or an interface, what matters is the API and its contract.

Moandji

Graham Allan

unread,
Jun 26, 2010, 9:18:27 AM6/26/10
to project...@googlegroups.com
I had a thought on this feature, which is probably technically impossible and
possibly offensive, but I thought I would throw it out there to see what you
think.

What about having an annotation, named @ExtractInterface (or similar), which
pulls all public methods, and creates a new interface type filled with those,
the same as with Eclipse's extract interface feature?

Thus a class like so:

@ExtractInterface
class Thing {
public void setHello(String newHello) { ... }
public String getHello() { ... }
}

Would generate:

interface IThing { // the naming would have to be a consideration
public void setHello(String newHello);
public String getHello();
}

This would (hypothetically) interact with other lombok annotations well:

@ExtractInterface
class Thing {
@Getter @Setter String hello;
}

... would produce the same interface as above.

My thoughts are that this proposal would satisfy the specific request to place
getters and setters on an interface, but would have wider uses as well. For
instance, I have recently been working on part of a project where I have many
types implementing interface Foo, and an AbstractFoo providing default
behaviour. It's expected that plugins will be able to provide an
implementation, choosing between implementing Foo or extending AbstractFoo. If
I could place @ExtractInterface on AbstractFoo I wouldn't need to track
changes in multiple places (hopefully it seems pretty DRY).

I would imagine that there will be objections to this, and areas which would
need to be covered (copying javadoc for example) but I thought I would get
your thoughts.

Best regards,
Graham

Maaartin-1

unread,
Jun 26, 2010, 11:51:27 AM6/26/10
to project...@googlegroups.com
On 10-06-26 15:18, Graham Allan wrote:
> I had a thought on this feature, which is probably technically impossible and
> possibly offensive, but I thought I would throw it out there to see what you
> think.
>
> What about having an annotation, named @ExtractInterface (or similar), which
> pulls all public methods, and creates a new interface type filled with those,
> the same as with Eclipse's extract interface feature?

I had a similar idea, but the other way round, but I'm unsatified with
it. I' prefer to start with the interface as it's the more important
thing - it would be bad if changes in the implementing class promoted
without notice. In the direction from interface to a class there's not
obviouls what could be done, maybe properties could get a real
implementation while all other methods could get a no-op implementation
in a concrete class (and be ignored in an abstract class).

> Thus a class like so:
>
> @ExtractInterface
> class Thing {
> public void setHello(String newHello) { ... }
> public String getHello() { ... }
> }
>
> Would generate:
>
> interface IThing { // the naming would have to be a consideration
> public void setHello(String newHello);
> public String getHello();
> }

I'd prefer to be explicit using @ExtractInterface(IThing.class).

> This would (hypothetically) interact with other lombok annotations well:
>
> @ExtractInterface
> class Thing {
> @Getter @Setter String hello;
> }
>
> ... would produce the same interface as above.
>
> My thoughts are that this proposal would satisfy the specific request to place
> getters and setters on an interface, but would have wider uses as well. For
> instance, I have recently been working on part of a project where I have many
> types implementing interface Foo, and an AbstractFoo providing default
> behaviour. It's expected that plugins will be able to provide an
> implementation, choosing between implementing Foo or extending AbstractFoo. If
> I could place @ExtractInterface on AbstractFoo I wouldn't need to track
> changes in multiple places (hopefully it seems pretty DRY).

IMHO, this is an important and common use case. My above objection
("changes in the implementing class promoted without notice") doesn't
apply here.

> I would imagine that there will be objections to this, and areas which would
> need to be covered (copying javadoc for example)

Sometimes you need a different javadoc, e.g., writing "Compute...." in
IFoo and writing "Do nothing" in the dummy implementation AbstractFoo.
But this is not strictly necessary (cf. MouseAdapter).

Reinier Zwitserloot

unread,
Jun 27, 2010, 2:06:42 PM6/27/10
to Project Lombok
An idea worth considering, especially as for RMI projects you are
usually forced to create an interface. Definitely need to figure out a
way to be able to say: This method is public, but should NOT be
extracted along with the rest of the public methods.

Unfortunately it's not really the job of lombok. This is a classic job
for traditional annotation processors, which are perfectly capable of
generating entirely new files based on a file that will in fact be
_using_ that file. The only pragmatic thing lombok could do there is
silently add "implements IThing", but that's not nearly enough to
justify lombok adding this feature, and adding considerable logistics
at the backend to support it - lombok right now cannot generate new
files.

Reinier Zwitserloot

unread,
Jun 27, 2010, 2:07:45 PM6/27/10
to Project Lombok
Oh, and if either of you or someone else wants to give it a try, let
me know, I can give you some pointers on how to write annotation
processors. Between lombok and writing quite a few normal ones, I'm
somewhat knowledgable on the subject :P

Maaartin-1

unread,
Jun 27, 2010, 3:34:25 PM6/27/10
to project...@googlegroups.com
On 10-06-27 20:06, Reinier Zwitserloot wrote:
> An idea worth considering, especially as for RMI projects you are
> usually forced to create an interface. Definitely need to figure out a
> way to be able to say: This method is public, but should NOT be
> extracted along with the rest of the public methods.

Sure. I can even imagine extracting multiple interfaces, but quite often
extracting all public methods would do, just like MouseAdapter ->
MouseListener. IMHO, the "classical" solution should be fine:

public @interface ExtractInterface {
Class<?>[] value();
}

@ExtractInterface(IThing.class)
public class Thing implements IThing {
@ExtractInterface({})
public void youGoNowhere() {}
}

> Unfortunately it's not really the job of lombok. This is a classic job
> for traditional annotation processors, which are perfectly capable of
> generating entirely new files based on a file that will in fact be
> _using_ that file.

I could imagine that both IThing and Thing exists, where IThing is an
interface already declaring a couple of methods and Thing is an abstract
class declaring some other methods. The goal is to add all methods of
Thing to IThing. Sure, this is not as common as the base case.

> The only pragmatic thing lombok could do there is
> silently add "implements IThing", but that's not nearly enough to
> justify lombok adding this feature, and adding considerable logistics
> at the backend to support it - lombok right now cannot generate new
> files.

Sure, adding "implements IThing" is quite useless, but everybody could
profit from integrated features instead of having to install additional
stuff. However, I see you need to concentrate on other things.

Reinier Zwitserloot

unread,
Jun 27, 2010, 4:45:06 PM6/27/10
to project...@googlegroups.com
Sort of. Lombok easily could, annotation processors not really. The rule is this: You can create any file and fill it with whatever you like, and if you create a source file, it'll be picked up, and existing files that are affected by this new file (e.g. because they are dependent on it) will be recompiled. The generated file may even itself contain annotations and these will trigger further processors if need be.

Annotation Processors are found automatically via the classpath.

Lombok may feel like an annotation processor but it isn't one; it merely uses the Annotation Processor system to hook itself into javac.

To do something like this, you'd first create an annotation, then create a subclass of Processor, add the appropriate meta-annotations to it to say that you trigger only on the @ExtractInterface annotation, then ask the RoundEnvironment which types have been annotated with that annotation, extract whatever information you need (though, @ExtractInterface(IThing.class) probably won't work, as IThing doesn't exist at that point. Maybe it will, though. @ExtractInterface("IThing") will most definitely work, though), ask the processing environment to create a new source file, and write to it as if its a plain file (literally dump "public interface IThing { .... }" into an OutputStream.

If you'd like an example, you can look at lombok.ast's TemplateProcessor, though that's a rather complex beast that generates gigantic (and complex) amounts of code.

Here's a bare minimum:


@SupportedAnnotationTypes("pkg.ExtractInterface")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class ExtractInterfaceProcessor extends AbstractProcessor {
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element element : roundEnv.getElementsAnnotatedWith(GenerateAstNode.class)) { 
TypeElement type = (TypeElement)element;
String annotatedName = type.getQualifiedName().toString();
// Trick 1: If you grab the parameter to @ExtractInterface via the annotation mirror and not via .getAnnotation(), I think you can
// fetch "IThing" from "IThing.class". But, you'd have to check yourself, I'm not entirely sure that'll work.
String nameOfInterface = /* calculating name is exercise for reader */;
JavaFileObject file = processingEnv.getFiler().createSourceFile(nameOfInterface, element); Writer out = file.openWriter();
out.write("package " + packageNameOf(annotatedName) + "\n\n");
out.write("public interface " + simpleName + " {\n");
out.write(".....");
}
}
}

Grabbing the methods in the annotated type is done via TypeElement's .getEnclosedElements() method. Each Element that is an instanceofExecutableElement is a constructor or a method.



--Reinier Zwitserloot



On Sun, Jun 27, 2010 at 9:49 PM, Maaartin-1 <graj...@seznam.cz> wrote:
On 10-06-27 20:07, Reinier Zwitserloot wrote:
> Oh, and if either of you or someone else wants to give it a try, let
> me know, I can give you some pointers on how to write annotation
> processors. Between lombok and writing quite a few normal ones, I'm
> somewhat knowledgable on the subject :P

I'm sort of interested but it depends on how much work it is. I tried
Google but it gave me nothing really readable.

Is it possible to do something like http://paranamer.codehaus.org using
annotation processors and/or lombok?

Maaartin-1

unread,
Jun 28, 2010, 5:53:23 AM6/28/10
to project...@googlegroups.com
On 10-06-27 22:45, Reinier Zwitserloot wrote:
> To do something like this, you'd first create an annotation, then create
> a subclass of Processor, add the appropriate meta-annotations to it to
> say that you trigger only on the @ExtractInterface annotation, then ask
> the RoundEnvironment which types have been annotated with that
> annotation, extract whatever information you need (though,
> @ExtractInterface(IThing.class) probably won't work, as IThing doesn't
> exist at that point. Maybe it will, though. @ExtractInterface("IThing")
> will most definitely work, though),

Ok, but using strings is generally a bad idea. Replacing an existing
class this way doesn't work due to the "duplicate class" error.

Using IThing.class works partly. I can obtained all the information as
strings only:

for (final AnnotationMirror annotationMirror :
typeElement.getAnnotationMirrors()) {
final DeclaredType annotationType = annotationMirror.getAnnotationType();
final ExtractInterface annotation =
annotationType.asElement().getAnnotation(ExtractInterface.class);
}

Using "annotationType.toString()" gives me the information, but
"annotation" is always null. Even if it wasn't, according to
http://java.sun.com/javase/6/docs/api/javax/lang/model/element/Element.html#getAnnotation(java.lang.Class)
it wouldn't help. I need two things:
- find out if the annotation is ExtractInterface
- get the value() not necessarily as a class (its name would suffice)
Currently, I see no way how to do it except by parsing
annotationType.toString(), which is very strange at best. Any better idea?

So I tried it with a interface name generated by simply prepending "I"
and it sort of works using javac. I'll look now how to integrate it into
eclipse. There may be problems with generics, etc.; maybe generating a
class file instead could be easier.

Reinier Zwitserloot

unread,
Jun 28, 2010, 6:25:42 AM6/28/10
to project...@googlegroups.com
No, toString() parsing is par for the course in mirrors. There's no consistent, unified resolution model by the time your annotation processor runs, because if there had been, you couldn't add new types. You're working very close to the raw source, and raw source is expressed in strings.

Integrating into eclipse is not particularly difficult; create a jar file containing your annotation processor as well as a services file:

META-INF/services/javax.annotation.processing.Processor

this file should be a text file containing one line, which is the fully qualified class name of your processor. E.g. for lombok this file contains:

lombok.core.AnnotationProcessor


In eclipse, for any project, go into its properties, "Java Compiler", "Annotation Processing", and check the "Enable annotation processing" and "Enable processing in editor" checkboxes. Then pick the "Factory Path" subpage and add your jar here. Eclipse will ask for permission to recompile your whole project, and boom, it'll all work. If you ever make a change to your processor, you need to rebuild the jar, refresh eclipse's dir state (click on project, hit F5) (unless you're on mac/linux and have auto-refresh on), go back to this page, uncheck the processor, hit apply, then check it, and hit OK - unfortunately eclipse, at least version 3.5, doesn't refresh this itself.

In IDEA you're out of luck, this IDE is way behind on annotation processing. On netbeans, in 6.8, you're out of luck. On 6.9, however, I hear support is _excellent_.

--Reinier Zwitserloot




--

Maaartin-1

unread,
Jun 28, 2010, 8:24:56 AM6/28/10
to project...@googlegroups.com
On 10-06-28 12:25, Reinier Zwitserloot wrote:
> No, toString() parsing is par for the course in mirrors. There's no
> consistent, unified resolution model by the time your annotation
> processor runs, because if there had been, you couldn't add new types.
> You're working very close to the raw source, and raw source is expressed
> in strings.

Agreed, however toString() is much worse than necessary. Something like
getClassName() would be a fine replacement where you can't get the Class
itself.

> Integrating into eclipse is not particularly difficult; create a jar
> file containing your annotation processor as well as a services file:
>
> META-INF/services/javax.annotation.processing.Processor

I tried to place it in the project directory, then in its src, then in
existing META-INF (somewhere in WebContent) and finally in the jar file,
the last one worked.

> this file should be a text file containing one line, which is the fully
> qualified class name of your processor. E.g. for lombok this file contains:
>
> lombok.core.AnnotationProcessor
>
>
> In eclipse, for any project, go into its properties, "Java Compiler",
> "Annotation Processing", and check the "Enable annotation processing"
> and "Enable processing in editor" checkboxes. Then pick the "Factory
> Path" subpage and add your jar here. Eclipse will ask for permission to
> recompile your whole project, and boom, it'll all work. If you ever make
> a change to your processor, you need to rebuild the jar, refresh
> eclipse's dir state (click on project, hit F5) (unless you're on
> mac/linux and have auto-refresh on), go back to this page, uncheck the
> processor, hit apply, then check it, and hit OK - unfortunately eclipse,
> at least version 3.5, doesn't refresh this itself.

Even if it did. On my current OS parody the jar gets locked, so I need
to leave eclipse every time when I need to change it.

So, it's not "particularly difficult", it's just about 10 times more
complicated than it should be. Specifying a list of annotation
processors and a classpath for them is the useful part; creating the jar
and clicking around is unnecessary overhead.

> In IDEA you're out of luck, this IDE is way behind on annotation
> processing. On netbeans, in 6.8, you're out of luck. On 6.9, however, I
> hear support is _excellent_.

Ok, I currently stick with eclipse, anyway.

Reinier Zwitserloot

unread,
Jun 28, 2010, 9:25:48 AM6/28/10
to project...@googlegroups.com
Heh, I forgot how useless windows is when developing :P

If you uncheck the jar in the list and hit ok, it should unlock, no?

--Reinier Zwitserloot

Roel Spilker

unread,
Jun 28, 2010, 9:36:48 AM6/28/10
to project...@googlegroups.com
Uhm, I don't know if this is helpful, but I usually have3 a separate root folderin my eclipse project called SPI. In that folder I have a META-INF/services path containing the SPI files (javax.annotation.processing.Processor) If you mark the SPI folder as source folder, eclipse will compy the content to the bin folder and during runtime your Service Providers will be discovered.

That said, to use an annotation processor inside Eclipse, you do need a jar file.

Roel


-----Oorspronkelijk bericht-----
Van: rei...@zwitserloot.com [mailto:project...@googlegroups.com] Namens Reinier Zwitserloot
Verzonden: maandag 28 juni 2010 15:26
Aan: project...@googlegroups.com
Onderwerp: Re: [project lombok] Re: It would be nice to define a plain Java interface using @Data

Graham Allan

unread,
Jun 28, 2010, 4:42:12 PM6/28/10
to project...@googlegroups.com
> > The only pragmatic thing lombok could do there is
> > silently add "implements IThing", but that's not nearly enough to
> > justify lombok adding this feature, and adding considerable logistics
> > at the backend to support it - lombok right now cannot generate new
> > files.
>
> Sure, adding "implements IThing" is quite useless, but everybody could
> profit from integrated features instead of having to install additional
> stuff. However, I see you need to concentrate on other things.

It may not be useless. Reinier or someone more familiar will have to back me
up or shoot me down on this one, but isn't there a caveat with annotation
processing in that the source file containing the annotation must not be
modified? I.E. you can't have a class Thing without the "implements IThing"
that is then modified by the annotation processor to implement it in the source
file[1].

If that is indeed the case, manually entering "implements IThing" isn't that
much of a deal. But if you're specifically looking to reduce boilerplate, it's
fair game. I guess this is where lombok could come in, and it would probably
be the simplest transformer out there :-)

Hopefully someone can help me out if I've made a mistake.

Regards,
Graham

[1] The only source I have for this is coming from a question I asked on
StackOverflow: http://stackoverflow.com/questions/687553/the-drawbacks-of-
annotation-processing-in-java/705812#705812)

Reinier Zwitserloot

unread,
Jun 28, 2010, 8:01:14 PM6/28/10
to Project Lombok
Indeed, you can't modify the existing source file, but it seems quite
a stretch to use lombok to implement this feature just so folks using
@ExtractInterface can avoid typing "implements IName". Yes, it's
boilerplate, yes, it's a light DRY violation (you just mentioned it in
the annotation too), but I don't think it qualifies as the kind of
thing that's so annoying you wish fervently for a nice solution.

My main problem with it is that the 'create new file' part of it is
NOT part of the lombok infrastructure right now, and it's quite a bit
of work to add it. One could of course make a mixed bag: An annotation
processor _AND_ a lombok processor, with the lombok processor just
adding the implements line, but the additional complexity in setting
that up properly does not seem to be worth the hassle.

Maaartin-1

unread,
Jun 29, 2010, 3:38:55 AM6/29/10
to project...@googlegroups.com
On 10-06-28 15:25, Reinier Zwitserloot wrote:
> Heh, I forgot how useless windows is when developing :P

It's always useless, unless you need a botnet to send a lot of spam.

> If you uncheck the jar in the list and hit ok, it should unlock, no?

No, it does not. Probably the eclipse guys don't use the parody so they
didn't notice.


On 10-06-28 15:36, Roel Spilker wrote:
> Uhm, I don't know if this is helpful, but I usually have3
> a separate root folderin my eclipse project called SPI.
> In that folder I have a META-INF/services path containing
> the SPI files (javax.annotation.processing.Processor)
> If you mark the SPI folder as source folder,
> eclipse will compy the content to the bin folder
> and during runtime your Service Providers will be discovered.
>
> That said, to use an annotation processor inside Eclipse, you do need a jar file.

Initially, I put it all (Thing, ExtractInterface, and
ExtractInterfaceGenerator) into a single directory and it worked using
javac on the command line. I wonder why eclipse must make things
complicated. I'd like to do something like

interface ExtractInterfaceConfig {
String simpleName(String classPackageName, String classSimpleName);
String packageName(String classPackageName, String classSimpleName);
}

which would provide the interface name in case none is given. This does
not belong to any jar, this is a way how the user could configure it.
I'm afraid this can't be done easily, but I think such a flexibility is
very useful, even more for lombok, where there are (could be) much more
things to configure, e.g.,
- using "is" a getter prefix (should be sort of global option)
- details of toString (s. below)
The most flexible way to configure things is a piece of program.

interface ToStringConfig {
String prefix(String className);
String suffix(String className);
String separator(String className);
String entry(String className, String name, String value);
boolean useGettersInsteadOfFields();
}

I wonder if this is possible somehow, the user configuration should
reside somewhere in the project itself, surely not in any jar. Is it
possible for annotation processors? Is it possible for lombok?

Reinier Zwitserloot

unread,
Jun 29, 2010, 7:53:37 AM6/29/10
to Project Lombok
Global options for lombok is something we're still working on. There's
a bunch of problems with that: If you have some java file named
"Foo.java", with a @Data annotation and you've turned 'boolean-getters-
start-with-is-not-get' off in your lombok global settings, then that
Foo.java on your system means something different than the same
Foo.java on someone's system when that flag is on. That's not a good
thing. There are a bunch of different granularities to think of:

- code snippets
- source files
- source modules
- entire system

Each deeper level loses semantic meaning. However, raw language
features have always continued to make sense even on the snippet
level. With lombok settings, most likely the granularity of those
settings-dependent lombok features would drop down all the way to
source module level, possibly even 'entire system' level.

So far we haven't run into a single setting that's worth all that
hassle, though if you add them all up...

Reinier Zwitserloot

unread,
Jun 29, 2010, 7:56:40 AM6/29/10
to Project Lombok
For lombok we could indeed use SPI-like discovery on your source dir (-
ish, we'd have to work on resolution, right now lombok does not have
any sense of source files or library classes of the project that's
being compiled other than the file it's working on. Having APIs in
place to access other stuff is part of resolution). For your own
annotation processors, you can always use your own version of SPI
discovery, though for eclipse specifically you'd have to add the jar
(here we go again!) with the SPI file + interface implementation in
the list of jars used for annotation processing. Not the nicest of
solutions. You can of course take a page from lombok here and 'abuse'
the API by checking if the ProcessingEnvironment object in
'processingEnv' is in fact an eclipse processing environment, and if
so, cast to that, and use it to escape your way back to the IProject
object. From here you can query AST models.

On Jun 29, 9:38 am, Maaartin-1 <grajc...@seznam.cz> wrote:

Maaartin-1

unread,
Aug 15, 2010, 4:30:20 PM8/15/10
to project...@googlegroups.com
On 10-06-29 02:01, Reinier Zwitserloot wrote:
> Indeed, you can't modify the existing source file, but it seems quite
> a stretch to use lombok to implement this feature just so folks using
> @ExtractInterface can avoid typing "implements IName". Yes, it's
> boilerplate, yes, it's a light DRY violation (you just mentioned it in
> the annotation too), but I don't think it qualifies as the kind of
> thing that's so annoying you wish fervently for a nice solution.

Agreed, but assuming the interface already exists, lombok could do more:

- optionally expand the interface by all public methods from the class
(unless annotated to be ignored)

- optionally expand the class by providing some simple implementation
when told to do so: getters and setters could do what expected, other
methods could get an empty or throwing implementation (recently I needed
a PriorityQueue with only two working methods).

> My main problem with it is that the 'create new file' part of it is
> NOT part of the lombok infrastructure right now, and it's quite a bit
> of work to add it. One could of course make a mixed bag: An annotation
> processor _AND_ a lombok processor, with the lombok processor just
> adding the implements line, but the additional complexity in setting
> that up properly does not seem to be worth the hassle.

But aren't there more useful features which will require creating new
files anyway? There are plans for @Builder annotation, this implies one
or more new classes, doesn't it?

Btw., there's already an @ExtractInterface annotation:
http://code.google.com/p/javadude/wiki/AnnotationsQuickRef

Reply all
Reply to author
Forward
0 new messages