Discussions

News: How should we override annotations via XML?

  1. How should we override annotations via XML? (27 messages)

    As soon as annotations were discussed for technology such as EJB 3, many people asked "Erm. What about the deployer role? Can we override the annotation settings via a descriptor?". Cedric Beust and Bill Burke have put forward two proposals for how this could be handled. What do you think?

    Cedric's Proposal
    The overriding is specified in an external XML file which could look like this:

    <override>
      <annotation-class names="javax.ejb3.TransactionAttribute" />

      <scope>
        <package names="com.foo" />
        <class names="Account" />
        <method names="deposit withdraw" />
      </scope>

      <overridden-values>
        <value name="value"
               old-value="javax.ejb3.TransactionAttributeType.SUPPORTS" />
               new-value="javax.ejb3.TransactionAttributeType.REQUIRED" />
      </overridden-values>
    </override>
    Read Cedric Beust in Overriding annotations

    Bill's Proposal
    The proposal has these goals:

    • Any annotation should be overridable in XML
    • Any annotation should be insertable/declarable through XML.
    • XML should be a viable replacement for any annotation of any J2EE component.
    • Annotations should be optional and not required for any component definition in J2EE.
    <session>
       <remote>com.acme.PetStoreRemote</remote>
       <local>com.acme.PetStoreLocal</local>
       <ejb-class>com.acme.PetStoreBean</ejb-class>


       <annotation method="public void setEM(javax.ejb.EntityManager)">
          @javax.ejb.Inject
       </annotation>

       <class-annotation>
         @javax.ejb.Tx(javax.ejb.TxType.SUPPORTS)
       </class-annotation>

       <annotation method="public void buy(int productId)">
          @javax.ejb.MethodPermissions({"allowed"})
       </annotation>

       <annotation methodName="get*">
          @javax.ejb.Unchecked
       </annotation>

       <!-- VENDOR SPECIFIC -->
       <class-annotation>
           @org.jboss.SecurityDomain("LDAP Repository")
       </class-annotation>

    </session>
    Read Bill Burke in XML overrides for EJB3

    Threaded Messages (27)

  2. What about the idea of not using annotations at all? My understanding is that we'd have that option. Some people (like me) might consider the idea of incorporating annotations with deployment specifics into source code a bad idea, and would like the option at least of specifying everything externally. Consider, for example, a class being used for Hibernate persistence. The beauty of hibernate is that the class has no knowledge whatsoever of Hibernate; it's completely dissociated from the details of persistence. It also has no dependencies on hibernate classes. I'm not exactly sure how Tiger annotations will work, but I know that in C#, if you want to use attributes (the equivalent to annotations), you need to import the attribute class before you can use it to mark up. If there's a dependency on an EJB annotation in my model class, that's no different from a dependency on an EJB interface. It's still an external dependency that doesn't need to be there at compile time (or that I may not be able to enforce, given a set of legacy classes).

    Given the option, I'd rather manage the mapping to persistence externally, like I do now. I'm scared by everyone's love affair with annotations. I think that while they may be useful in some cases, they bring as much baggage as "descriptor hell". The worse thing about descriptor hell was verbose descriptors. Solve that (as Hibernate did), and I much prefer that option over annotations.
  3. After reading Gavin's article Gavin's article earlier this week I think annotations, used smartly, would not tie the classes into one specific persistance mechanism. They would instead tag a method or class with a more abstract idea " @Stateful, @Stateless, @Entity, @Table, @Remote, @ManyToOne". I can live with these annotations in my classes if it means that any annotation-compliant framework can then let me tie them in.
  4. Abstract is good[ Go to top ]

    I agree that having annotations for abstract ideas is great.

    For this to really work, we need to make sure that the right people are all together to specify what should be involved in the annotations.

    E.g. What should @Stateful take? Is this JUST about Stateful SB? In that case the EJB expert group can decide, but what about stateful web services?

    It smells like a need for seperate annotation specifications that have all of the stake holders (as has happened with some of the Web Services annotations).

    Dion
  5. overriding is good[ Go to top ]

    I am all for a seperate XML file for Overriding semantics. I cant follow a previous poster who doesnt want to use anotations at all, i mean, how many times does the deployer decide that this specific method is stateful instead of stateless, this is a perfect choice for an annotation.

    For the proposals, i like Bills suggestion, i mean i dont care what kind of old annotation i am overriding and Bills one is a little bit more compact.

    Marc
  6. I think annotations are, as they stand, a mix of a lot of things.

    * Some things, you want to provide when designing an application.

    * Other stuff is set when you know your customer and his environment.

    * Some stuff should even be overridable at runtime by the people supporting your application.

    * I, for one, would also like to be able to list test cases for a piece of code _within_ the code - if the notation is terse enough.

    The opposite also holds:

    * Only the designer should be allowed to control access.

    * If, say, a mail address or some other information not known during the design is not set at deploy time, the application should stop immediately.

    * License keys and the like should not be configurable by anyone after deployment without authorization.

    Java has a very unstructured approach to this. We have JMX, which only addresses part of this. We now have annotations - which don't seem to be targeted at any one of the first three items, or even address the differences.

    What we see now is, in my opinion, a discussion mostly based in people discussing annotations with different usage models in mind.

    As I see this, there are two ways forward. One way is to try and lump all opinions together. This will problably make the annotation system quite unworkable.

    The other way is to try to differentiate between different usage models of annotations. I think this could make annotations a truly powerful tool.
  7. What about the idea of not using annotations at all? My understanding is that we'd have that option. Some people (like me) might consider the idea of incorporating annotations with deployment specifics into source code a bad idea, and would like the option at least of specifying everything externally. Consider, for example, a class being used for Hibernate
    I'm with you. Annotations should contain additional information only, never something that the application depends upon.
    Check out the function of footnotes in books, that's what an annotation is supposed to be.

    Abusing them to just pull more stuff into a sourcefile is bad practice, just as bad as defining unit tests as Javadoc blocks which are then parsed into Java sourcecode using javadoc upon compilation (as suggested by someone a few months ago).

    They COULD be useful for things like mapping Java class attributes to screen components (automating the generation of boilerplate getters and setters), and maybe auto generation of Javadoc comment blocks, but not much more.
  8. I'm with you. Annotations should contain additional information only, never something that the application depends upon.
    Why?

    That's how Enterprise software works these days: Java alone is just not sufficient, we *need*metadata. J2EE and non-J2EE frameworks alike use metadata, it just happens to be in XML right now.

    Or please suggest an alternative...

    --
    Cedric
  9. Stuff like IDL is an alternative, it is compromise for both ways. This "IDL" can be the same JAVA source file with interface declaration and it can be deployed with class files as metadata (if somebody wants to edit metadata at runtime for some reason), you write and maintain this file any way.
    Configuration is not metadata, so it can be XML or "properties" ( I see no major difference, but it must be better to integrate it with "global" server configuration and to modify it without any redeployment).
  10. Stuff like IDL is an alternative, it is compromise for both ways. This "IDL" can be the same JAVA source file
    It can't, or it's not IDL.

    And if you are going to reuse the same Java source, then why use something else than annotations?

    --
    Cedric
  11. It can't, or it's not IDL.And if you are going to reuse the same Java source, then why use something else than annotations?-- Cedric
    Yes, annotations must be used for "interface declaration language", there is no meaning to use some OMG language and to map it to JAVA, JAVA with annotations has all features to define interface and there is no problems to generate C++ code from JAVA metadata, compiled class file is portable binary file, but I prefer text.
    This file must not be used for configuration, configuration must be used for parameters only and not for metadata.
    Difference is very clear, metadata is the part of interface, it is the same as method declaration and it is the part of contract. Configuration is a set of runtime parameters only.
  12. maximum override[ Go to top ]

    I think its great... as long as their is some way I can put something in my Java code that will override the XML that overrides the annotations in my Java code, which replaces the "evil" XML deployment descriptors, which we added in the first place so we don't have to hard-code this stuff into our Java code.

    Sure, the extra override may be a tad confusing, but we could make the whole thing configurable my XML... to simplify things.
  13. Any annotation should be overridable in XML
  14. Any annotation should be insertable/declarable through XML.
  15. XML should be a viable replacement for any annotation of any J2EE component.
  16. Annotations should be optional and not required for any component definition in J2EE.
  17. As I noted in the different thread I had some fun time deploing CMPs on Weblogic before I realised that ejbc generated different stub code depending on settings in deployment descriptor.

    If EJB spec (and EJB developers) still want to maintain that EJBs can be fine-tuned at deployment time after the code is compiled, than all above statements are right on, but vendors should finally bring their tools to the specs. If the idea of deployment tuning is going to be abandoned, then who cares, annotations, shmannotations, it is all in the source code and should be recompiled anyway.
  18. I like the notion of the specific "override"-tag in Cedrics approach, it seems semantically more clear (ie "I know that I am going to override a 'hardcoded' annotation").

    As far as defining the scope, I like Bills approach better ... having a separate tag for "package" and "class" seems overkill.

    Generally, I think both scope definitions are a bit "verbose", since overriding of a annotation should be more of an exception than the rule: when a annotation is defined by the developer it is there for a very good reason otherwise it would be left to the deployer for configuration (unlike AOP, where pointcutting with regex's makes more sense). Therefore I'd think a verys simple override instruction would do:

       [override
            annotation="com.foo.Account::void deposit(int,int)"
            old-value="javax.ejb3.TransactionAttributeType.SUPPORTS"
            new-value="javax.ejb3.TransactionAttributeType.REQUIRED"]

    Sorry for the sick xml mock, but I can never memorize how to post in which way on what site (preview, please;) ...
  19. What's so wrong with just using (a modified version of) the good old deployment descriptors from EJB 2.1.

    Yeah i know, they are a bit verbose, but with the simplifications of Home/Remote interfaces, it should be possible to simplify a lot.

    Combine that with som sensible defaults (like making sessionbeans stateless by default, at let the container manae transactions by default), they should be pretty short.

    It will of course require some standardization of the traditionally vendor-specific descriptors used for OR-mapping/CMP
  20. Both proposals seem to assume it's a good thing that the XML should include reference to the annotations. I believe that's the wrong starting point. If I'm writing XML in a schema-aware editor it can make intelligent checks, validate, etc.. If I'm using it to edit a document that's a hybrid of annotation syntax and XML then any tool (XSLT documentation generator, code generator, editor, whatever) has to grok annotations as well as XML. I'd prefer a schema-verified, XML-only syntax for the descriptors which could be used in place of annotations or as an override. You'd have to say that the XML version takes precedence and allow for absent elements (that would be defined in the annotations) but I believe it would be cleaner.
  21. This business of overriding annotations just does not seem right to me. By introducing annotation overriding, we effectively take away any way to fully understand the behavior of the system just by looking at source code or XML. Taking transaction XML example at hand, there is no way to tell transactional behavior of a method just by looking at XML or just by looking at the code. If code specifies attribute "NEVER", then your method still may run with attribute "REQUIRED", and vice versa... kind of takes away the elegancy of the whole approach.

    Is this only supposed to be usable with GUI tools support?

    Regards,
    --Dmitriy.

    P.S. If I had to choose between XML examples above, I would pick Cedric’s. I think it is semantically clearer.
  22. I agree with you Dmitriy. I like XDoclet's approach:

    @Bla(param1="${param1}")

    So param1 value is basically only a placeholder, and the real value is externally defined in a properties file loaded by Ant. This apprach clearly communicates that param1 is externally defined, but on the other hand when we look at the code we know @Bla is used.

    In case of JSR 175, would be great if the spec supported such a mechanism, so for example we would have:
    @Bla(param1=Annotation.EXTERNAL)

    Of course it's partially possible to define this constant in the current spec too, using generics perhaps.

    On the other hand overriding is inevitable imho. No matter ejb3 spec defines a mechanism or not, I think a smart guy will eventually write a "annotation assembler/disassembler" which lets user extract annotation by looking at class file bytecode, and then changing or even injecting new annotation to the class file. Such a utility would be very helpful, and I'm sure an Ant task would then appear to automate it and then that task would support defining annotations in properties and xml files. So I like Bill's suggestion more, because at least for this generic annotation assembler/disassembler utility his suggested format is more consistent and general.

    And yet again, on the other hand, I think the above approaches are a push-based solution to the problem. We basically change the annotations in compile time.

    Another approach could have been a plugable annotation loader class defined by jsr175. Hibernate supports such a mechanism with its programmable Configuration class. In Confluence for example, we created a deleagting Configuration class which loaded some of the hibernate configuration from a separate admin defined xml file stored in his home dir. Or in another case (backup/restore) I gave hibernate another Configuration which changed some lazy/proxy/etc settings for some classes, and those very specific settings made the code in that case a lot faster.

    In my opinion because of the level of reliance on annotation in the ejb3 on annotation, annotations should be considered the master copy of metadata: if I query for ejb3 annotations in a class it should mean I get the valid and final metadata for that class, and not something which is overriden by another xml file accompanying the jar file. Overriding the way Bill and Cedric define it should imho happen only in compile time.

    Ara.
  23. 2c[ Go to top ]

    Copy/paste from blog.hibernate.org:

    Cedric and Bill have proposed solutions. My preference is basically similar to Bill's, but here's how I would write it:

    <class name="org.hibernate.Item">
        @Entity
        @Table(name="AUCTION_ITEM")
        <method sig="getBar()">@Transient</method>
        <method sig="doSomething(int, String)">
            @Tx(REQUIRES_NEW)
        </method>
    </class>

    I like this, because the same approach can be used outside of the context of J2EE. I really wish something like this would have been included in JSR-175.

    But then, I think of "overriding" as a different problem to "xml deployment descriptors", and so I think we need two solutions. I think Cedric and Bill are trying to kill two birds with one stone, so maybe their proposals are better....
  24. Think big[ Go to top ]

    Bill's goals, and his emphasis that this applies to ANY annotation, are exactly right. This isn't just about EJBs or about overriding; it's about how to use Java annotations.

    Given the goals, Bill's syntax seems reasonable. No syntax quibbling from me; first I want all of the annotation-dependent specs to take this approach, and secondly I'd be happy to have them share a syntax, whatever it may be. The sooner it's in J2SE the happier I'll be.
  25. Some things that could be useful[ Go to top ]

    Three things I would like to see at the annotation stage:

    1) Marking an annotation as abstract (or some other word) meaning that it had to be set through an XML overide or admin mechanism at deployment time. This would be a great way for developers to ensure that all information that changed on deployment (moving from dev->test->stage->prod) would be captured and verifyable by the runtime.

    Something like @WebService(name="GetStuff", @abstract endPoint)

    2) Marking an annotation as final (or again, some otherWord) such that the particular value could not be overridden by any means and so would throw exceptions if this was attempted on deployment

    Something like @final @Transaction(REQUIRED)

    3) Simple assignment of system, environment and other variables to annotations. These could be values defined in the OS, as properties in an app server, at jvm startup, or in deployment XML files. This would allow, for example, a schema name to be set in only one annotation overide file, or even in an app server admin console as an application property.

    Somthing like @Schema($CustomerDatasourceSchema)

    Reading the original annotation spec, I couldn't see any reference to such things, but I may have just scanned it too quickly.
  26. XPath variables[ Go to top ]

    We could have lots of fun by using XPath to grab things in:

    @Schema(/Annotations/DataSource/CustomerDatasourceSchema)

    ;0

    D
  27. Annotations should be used for things that "if you change them, then you better look at the code". For example, changing from BMT to CMT for a session bean. XML should be used for configuration things. This would better fit the purpose of JSR 175 and the bigger picture of how this fits in. Don't forget the developer that gets an EJB from someone else to include in their project but no source.

    The problem with the deployment descriptors was that they had both meta-data and configuration in XML format. But they are great for configuration.

    If you have to put in configuration data as annotations, then you should be overriding it based on the concepts you are configuring. You don't need a general "lets override any annotation" solution. You just need to change the configuration of the thing. Keep the syntax to the problem at hand.
  28. I contemplated for a long while whether I should comment on this subject (again), but sorry, I could not resist the temptation to make myself seem like a stubborn luddite, afraid of everything new.

    Actually, I have acute problems of grasping what surplus value annotations would brings us. IMHO they just add yet another vector of information. Yeah, sure, they will make things easier when defining simple properties, but with EJB development, that would force us to query whether a property was defined
       a) in the source (by implementing an interface),
       b) in the comments (via annotations),
       c) in an XML descriptor.
    To make things worse, if we allow these properties to be overridden by each other, we will have to remember the rules of precedence that apply. This is difficult enough for us to get right when writing a statement containing different operators, and that is just one line of sourcecode and not defined using multiple files in wildly different locations and of diverse formats. I foresee an inexhaustible source of fresh bugs which are hard to detect.

    Moreover, for many developers the current XML descriptors already are a sort of information overload. Does anyone of you know all the tags, how they can be nested, which attributes they define and what they effect? With annotations we add a whole new list of keywords, a new syntax, and presumably new semantics as well.

    I agree that annotations might have a value, but only if they are used to replace XML descriptors. That would force EJB developers to learn yet another technology, but hey, we're young and eager, aren't we? On the other hand, mixing both XML descriptors and annotations is -- in my eyes -- just a way of code obfuscation. And for what purpose? Again, what was the surplus value of annotations?

    Just asking,
    Lars
  29. What are the implications of this for subclasses. From what I gather EJB 3 = pojo’s and in java we normally we override things through subclassing. If I have a subclass of an EJB with annotations which are overridden in an external xml file which ones are applied to the sub class? This gets worse if I have a tree of subclassed ejb’s with a parallel tree of overrides in external files. The permutations get scary. Options I can think of are:

    1) Annotations are not inherited. This sounds bad as I could now end up having to provide an implementation of each inherited method in order to attach my annotations to it, or I am forced into an external file which is what we were trying to avoid in the first place. Horrid!

    2) They are inherited but directly from the parent – no external overrides inherited. In this case overrides have to be reapplied all the way through the subclasses in the external file. Unpleasant but works.

    3) We specify some sort of rule to the override which specifies how to apply the override to subclasses.

    I guess number 3 doesn’t sound too bad but I think we need to bear in mind that right from the start java has been about OO.


    Carl Marais
  30. I see no problems with this stuff, use annotations for metadata and use external files for configuration. There is no meaning to
    override metadata or contract in external file ("interface"), but it is a very bad idea to dublicate configuration or to "hide" it in code, it is not a good idea to have configuration in "interface" too (it can cause security problems). It must be trivial to decide about this stuff.
  31. I’m beginning to doubt the usage of annotations in EJB3. In fact, annotation overriding is required to support deployment time configuration of EJB in EJB3 model, yet such overriding looks increasingly like a design smell to me. Previous poster pointed out ugliness of this situation with class hierarchies and I would only add that such overriding will surely require some sort of special code/annotation browser support by IDE to be sanely used (the same plague that obstructs most of today’s AOP usage – look at Rickard Oberg posts or AspectJ for Eclipse).

    Furthermore, I have yet to see a plausible general use case (besides EJB deployment time configuration which can likely be a rather result of annotations-based approach and not a desired use case) for annotation overriding. It rather seems to me logically to disallow any overriding between Java annotations and XML annotations (you can have both but they cannot be overridden). And when I say plausible it means not “art for art’s sake” exercise but something that yields unambiguous design advantage over the non-overriding.

    Regards,
    Nikita.
  32. Annotations are good for most of the cases it has been suggested in ejb3. It is only a problem where it is more of a configuration data rather than metadata, which is why there is a need for override.

    Fortunately, there are not many cases where we will ever need to override. I don't think we should override transaction annotations or allow to override *any* annotation. Do you want to see someone overriding @Stateless with @Stateful or transaction REQUIRED with NEVER? IMO, the annotation member values which would mostly require override are security roles, dependency injections, and entity table, schema, column etc.

    But I don't want to see XML as a mechanism for override. The motivation for Annotation was that it would be an elegant replacement for the incredibly clumsy XML descriptors, so why go back to the same thing to circumvent the limitations in annotations ?

    The first thing that came in my mind as an override mechanism is what a few posters mentioned, placeholders, which IMO is most elegant solution. So it might look like,
    @Column(name=${cust.desc.name}, length=${cust.desc.length})
    But compiler won't allow that (I have not tested it but don't see any such thing in JSR-175). Only for String members it is still possible:
    @Column(name="${cust.desc.name}", length=512)

    If it is possible to use ${placeholder} as a member value (not just for strings), it will be possible to achieve the following model:

       1 class + n configuration(s) = n types of ejb(s)

    where configuration can be a file with simple properties format. Each ejb type can have m instances with identical configuration.