This discussion is archived
5 Replies Latest reply: Jan 29, 2009 10:47 AM by jschellSomeoneStoleMyAlias RSS

Any possible workaround to use annotations that require an enum constant...

843793 Newbie
Currently Being Moderated
I am doing code generation and following the generation gap pattern (http://www.research.ibm.com/designpatterns/pubs/gg.html). For JPA i add a few annotation like @Table or @Inheritance to the generated-once client class and not the always-generated base class. However the problem is that if the values of those annotations change, it doesnt get reflected in the generated-once code, since its only generated once - the 1st time and never touched again.

So was trying in some way to get the annotations be on the base class thats always generated and did whats mentioned in this newsgroup post http://www.eclipse.org/newsportal/article.php?id=79805&group=eclipse.platform#79805

However it doesnt work since java doesnt like non enum constants in the annotation.

I wonder if there is some approach people have come across to address this kind of problem? (apart from say generating an orm.xml always to put annotations in there)
  • 1. Re: Any possible workaround to use annotations that require an enum constant...
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Priyajeet wrote:
    I am doing code generation and following the generation gap pattern (http://www.research.ibm.com/designpatterns/pubs/gg.html). For JPA i add a few annotation like @Table or @Inheritance to the generated-once client class and not the always-generated base class. However the problem is that if the values of those annotations change, it doesnt get reflected in the generated-once code, since its only generated once - the 1st time and never touched again.
    Huh?

    If you have code generated from a source and the source changes then you must generate the code again. Simple as that.

    And if that is a problem then something at at best is wrong with your build process or at worse it is wrong with your usage of the generated code.

    That pattern that you quote actually mixes generated and manually maintained data. Do you have one or two generated targets?
    If you only have one then your question doesn't make sense.
    If you have two, and you certainly can, then what I said above still applies - it must be regenerated.

    Finally note that there is nothing hard and fast mandated about code generation. You can generate codes is all sort of ways, parent classes, child classes, partial classes even entire hierarchies.
  • 2. Re: Any possible workaround to use annotations that require an enum constant...
    843793 Newbie
    Currently Being Moderated
    yeah we have 2 different generated targets.
    So we generate two artifacts -

    1] the base class thats always generated and never hand touched.
    2] the child client class thats only generated once, this is where a user adds his handwritten code

    the annotation comes on 2, hence when the source changes we cannot re generate 2 as it might have handwritten code.
    forcing the person to manually maintain the annotations.

    i am trying to find a way to avoid this.
    one way could have been generating the orm.xml always and put the annotations in there, but i want to know if there is any other way?

    The base class is annotated with only @MappedSuperclass, while the @Table and @Inheritance annotations go on the generated-once client class.
    For non enum value annotations, like @Table I can put a protected static final String TABLE = "TableName" and then on the generated once class I can do this

    @Table(name=Parent.TABLE) instead of @Table(name="TableName")
    However this method doesnt work for @Interitance which takes an enum value.
    javac complains that an enum constant is required for than annotation.

    Edited by: Priyajeet on Jan 27, 2009 8:52 PM


    // This class is always generated and never hand touched
    @MappedSuperclass
    class Parent
    {
      public static final String TABLE = "CHILD";
      public static final InheritanceType INH = InheritanceType.SINGLE_TABLE;
      ...
    }
    
    //This class is generated only once and may have handwritten code
    @Entity
    @Table(name=Parent.TABLE) // WORKS FINE
    @Inheritance(strategy=Parent.INH) // THIS IS THE ERROR POINT, SINCE IT WANTS AN ENUM CONSTANT
    class Child extends Parent
    {
      ...
    }
    Edited by: Priyajeet on Jan 27, 2009 8:58 PM
  • 3. Re: Any possible workaround to use annotations that require an enum constant...
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Priyajeet wrote:
    yeah we have 2 different generated targets.
    So we generate two artifacts -

    1] the base class thats always generated and never hand touched.
    2] the child client class thats only generated once, this is where a user adds his handwritten code

    the annotation comes on 2, hence when the source changes we cannot re generate 2 as it might have handwritten code.
    forcing the person to manually maintain the annotations.
    You missed to point of the pattern.

    Forget 1. It has nothing to do with it. (It can still be generated.)

    2 is what you want to seperate into two functional units, one generated one not.
  • 4. Re: Any possible workaround to use annotations that require an enum constant...
    843793 Newbie
    Currently Being Moderated
    Thats what I am generating. One class is getting split into two. One always generated, while the other generated once.

    Consider this UML diagram where A --> B means A extends B

    4 Files get generated

    1] ABase extends B (always generated)
    2] A extends ABase (generated-once)
    3] BBase (always generated)
    4] B extends BBase (generated once)

    It is 2 and 4 that will get the annotations for JPA - @Entity, @Table and @Inheritance.
    1 and 3 will get @MappedSuperclass.

    So my problem above that I mention applies to the Child (A or B) and not Parent (ABase or BBase)

    The seperation into functional units are joined by inheritance.
    Java doesnt have partial class methodology.
    So inheritance joins the 2 functional units.
  • 5. Re: Any possible workaround to use annotations that require an enum constant...
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Priyajeet wrote:
    Thats what I am generating. One class is getting split into two. One always generated, while the other generated once.
    You are still missing the point of the pattern.

    The pattern is
    <Class that is NOT generated> becomes <generated class> <manual class>

    And as I already said the fact that you have another generated class doesn't mean that you can't apply the pattern to second class.
    Consider this UML diagram where A --> B means A extends B

    4 Files get generated

    1] ABase extends B (always generated)
    2] A extends ABase (generated-once)
    3] BBase (always generated)
    4] B extends BBase (generated once)

    It is 2 and 4 that will get the annotations for JPA - @Entity, @Table and @Inheritance.
    1 and 3 will get @MappedSuperclass.

    So my problem above that I mention applies to the Child (A or B) and not Parent (ABase or BBase)

    The seperation into functional units are joined by inheritance.
    Java doesnt have partial class methodology.
    So inheritance joins the 2 functional units.
    That entire explanation doesn't matter. Actually the pattern doesn't matter either.

    Code generation, all code generation is simple.
    You take 'source', run it through a 'tool' and the output is 'code'.

    For that to work you MUST have 'source' and a 'tool' that produces the 'code' that you want. If one of those pieces is missing you can't use code generation.

    The variations on that are infinite. The only limitation is complexity and that at some point you reach a point of diminishing returns where it costs more to do the code generation (including maintainance) than it does to do it manually.

    So your options are
    1. Find some way to generate it all.
    2. Find some way to seperate some of the code out so some can be generated and the other is manual (and this is sort of the point of the pattern.)
    3. Do it manually.

    There is no magic. I would also like to suggest that you forget about the pattern entirely. It is clever but it is more of a intro to code generation and you appear to be limiting the possibilities by that pattern and you do not need to do that.