|
| 1 | +# DRAFT Annotation Rules |
| 2 | + |
| 3 | +This is a collection of rules for how annotations should work. |
| 4 | +Some of these duplicate what's in the specs (in particular, |
| 5 | +the platform spec and the Common Annotations spec). |
| 6 | +You can consider these to be rules about how annotations |
| 7 | +currently work, as well as rules about how new annotations |
| 8 | +should be designed to work to be consistent with current |
| 9 | +annotations. Of course, there are exceptions, called out below. |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +### Annotations and inheritance |
| 14 | + |
| 15 | +This section describes how annotations interact with inheritance. |
| 16 | +Note that, in general, we do not use the @Inherited annotation |
| 17 | +on our annotations. @Inherited only applies to annotations at |
| 18 | +the class level. If multiple classes in a hierarchy are annotated |
| 19 | +with an @Inherited annotation, only the annotation furthest from |
| 20 | +the base class is returned. For resource annotations, we want |
| 21 | +all such annotations to apply, so @Inherited would give the wrong |
| 22 | +results. For component-defining annotations, we don't want the |
| 23 | +fact that a superclass is a component to cause all subclasses to |
| 24 | +be components, so we don't use @Inherited for component-defining |
| 25 | +annotations. |
| 26 | + |
| 27 | +Some frameworks have defined additional annotations that specify |
| 28 | +how **their** annotations behave with regard to inheritance. |
| 29 | +For example, see the JPA @Inheritance and @DiscriminatorColumn |
| 30 | +annotations. |
| 31 | + |
| 32 | +Note that CDI is an exception to this, and recommends that scopes and interceptor bindings are declared @Inherited. It also recommends that stereotypes may be @Inherited depending on their intended usage. It recommends that qualifiers are not declared @Inherited. |
| 33 | +##### General rules |
| 34 | + |
| 35 | +A resource annotation (@Resource, @EJB, etc.) on a superclass |
| 36 | +is **not** overridden by a similar annotation on a subclass. |
| 37 | + |
| 38 | +In general, annotations on interfaces are ignored. |
| 39 | + |
| 40 | +A method-level annotation on a superclass method is ignored if the |
| 41 | +subclass overrides the method; only annotations on the subclass |
| 42 | +method apply. |
| 43 | + |
| 44 | +Since a class always "overrides" methods in an interface, annotations on |
| 45 | +the interface method are ignored. |
| 46 | + |
| 47 | +A method-level annotation on a superclass method or field that is **not** |
| 48 | +overridden "shows through" and still applies. (Note that it is not possible |
| 49 | +to override a field.) |
| 50 | + |
| 51 | +A method-level annotation on a private superclass method or field remains |
| 52 | +in effect. |
| 53 | + |
| 54 | +##### Exceptions |
| 55 | + |
| 56 | +JAX-RS allows per-method annotations on the methods of an interface. |
| 57 | +If the implementing class doesn't declare **any** JAX-RS annotations |
| 58 | +on a method (other annotations are allowed), the JAX-RS annotations |
| 59 | +on the interface's method apply. Any JAX-RS annotation on a method |
| 60 | +overrides **all** JAX-RS annotations on the corresponding interface method. |
| 61 | + |
| 62 | +JAX-RS defines a similar rule for annotations on methods of a superclass, |
| 63 | +again violating the general rule above. If a subclass overrides a method |
| 64 | +but does not include any JAX-RS annotations on the method declaration, the |
| 65 | +JAX-RS annotations from the superclass apply. |
| 66 | + |
| 67 | +>XXX - what happens if the class implements multiple interfaces with the same method but different annotations? |
| 68 | +>Santiago - The spec is mute about this case. It does say that annotations from superclasses take precedence over annotations in implemented interfaces. |
| 69 | +
|
| 70 | +In some cases, an annotation on a method will "show through" to subclasses |
| 71 | +that override the method. Since this prevents the normal approach of |
| 72 | +"disabling" the annotation by omitting it, the annotation will need an |
| 73 | +attribute that undoes its normal effect. For example, JAX-WS has |
| 74 | +@WebMethod(exclude=true) and Connectors has @ConfigProprty(ignore=true). |
| 75 | +Generally this style is discouraged. |
| 76 | + |
| 77 | +EJB allows the @Local and @Remote annotations to appear on interfaces. |
| 78 | + |
| 79 | +The JPA annotations @Table, @SecondaryTable, and @SecondaryTables |
| 80 | +interact with the @Inheritance annotation to control how they behave |
| 81 | +with respect to inheritance. |
| 82 | + |
| 83 | +CDI producer fields or methods are not inherited by subclasses, even if they |
| 84 | +are not overridden. The superclass would not know how to produce an |
| 85 | +instance of the subclass. |
| 86 | + |
| 87 | +CDI introduces specialization, which affects inheritance. If a subclass is defined @Specializes, then |
| 88 | + |
| 89 | +* all qualifiers are inherited, regardless of whether they are declared @Inherited |
| 90 | +* the EL name of the bean is inherited (@Named is not declared @Inherited) |
| 91 | + |
| 92 | + |
| 93 | +The following component-defining annotations do have @Inherited on them due to historical accident. In common usage, these annotations are not involved in inheritance hierarchies so it was decided to leave them in a state of non-compliance with these rules rather than risk introducing unforeseen problems. |
| 94 | + |
| 95 | +* javax.faces.validator.FacesValidator |
| 96 | +* javax.faces.view.facelets.FaceletsResourceResolver |
| 97 | +* javax.faces.render.FacesBehaviorRenderer |
| 98 | +* javax.faces.render.FacesRenderer |
| 99 | +* javax.faces.convert.FacesConverter |
| 100 | +* javax.faces.component.behavior.FacesBehavior |
| 101 | +* javax.faces.component.FacesComponent |
| 102 | + |
| 103 | + |
| 104 | + |
| 105 | +### @Documented |
| 106 | + |
| 107 | +Many annotations are used to effect the implementation of a class. |
| 108 | +For example, the Resource annotations define resources that are |
| 109 | +used by the implementation of the class. The resources used by a |
| 110 | +class are rarely part of the API specification of the class. |
| 111 | + |
| 112 | +In some cases, annotations add to the API specification of a class, |
| 113 | +and contain important information that a user of the class will need |
| 114 | +to know. Annotations of this sort should be marked with @Documented; |
| 115 | +these annotations will then appear in the javadoc for the class. |
| 116 | + |
| 117 | +> XXX - We haven't done a good job of applying @Documented to our annotations. We need to reconsider this issue. |
| 118 | +
|
| 119 | +All CDI annotations are marked @Documented. |
| 120 | + |
| 121 | +### Component-defining annotations |
| 122 | + |
| 123 | +A component-defining annotation (e.g., @Stateless, @WebService) on a |
| 124 | +superclass does not apply to a subclass. |
| 125 | + |
| 126 | +A component-defining annotation (e.g., @Stateless, @WebService) on an |
| 127 | +interface does not apply to a class that implements the interface. |
| 128 | +(This is an instance of the general rule that annotations on interfaces |
| 129 | +are ignored.) |
| 130 | + |
| 131 | + |
| 132 | + |
| 133 | +### Class vs. method annotations |
| 134 | + |
| 135 | +##### General rules |
| 136 | + |
| 137 | +Class level annotations that effect the semantics of the class |
| 138 | +are local to the defining class. |
| 139 | +These class level annotations are a shorthand for annotating |
| 140 | +methods defined in that class. Class level annotations |
| 141 | +play no direct role in inheritance unless the annotation |
| 142 | +is marked @Inherited. See above for why we don't use |
| 143 | +@Inherited for annotations that need to combine, although |
| 144 | +it is useful for annotations that simply need to override |
| 145 | +the same annotation in a superclass (e.g., @ServletSecurity). |
| 146 | + |
| 147 | +After the effect of class level annotations is considered |
| 148 | +for each class, the methods defined on that class end up |
| 149 | +with attributes that are a result of a direct annotation |
| 150 | +or a result of applying the class level annotation. |
| 151 | + |
| 152 | +When a subclass overrides a method, none of the attributes |
| 153 | +of the superclass method apply. When a subclass does not |
| 154 | +override a method, the attributes of the method are the |
| 155 | +effective attributes for the method from the parent class. |
| 156 | + |
| 157 | +A method default rule such as "all public methods are web |
| 158 | +service methods" acts as an implicit class level annotation. |
| 159 | + |
| 160 | +Some class level annotations don't effect the semantics of |
| 161 | +the class, but are just attached to some class "for convenience". |
| 162 | +For example, @Resource doesn't effect the semantics of the class. |
| 163 | +Many JPA annotations don't effect the specific class they're |
| 164 | +attached to, but instead effect the persistence unit the class |
| 165 | +is a part of. |
| 166 | + |
| 167 | +##### Exceptions |
| 168 | + |
| 169 | +In some cases, annotations on subclass and superclass methods |
| 170 | +"combine". For example, the interceptor annotations on superclass |
| 171 | +methods apply even if the subclass overrides the method and provides |
| 172 | +its own interceptor annotations. The interceptors from both the |
| 173 | +superclass and the subclass are invoked, from superclass down to |
| 174 | +subclass. |
| 175 | + |
| 176 | +##### Package level annotations |
| 177 | + |
| 178 | +We've made very little use of package level annotations in Java EE. |
| 179 | +Where they are used, they effectively act as another level of defaulting |
| 180 | +above classes. That is, package level annotations are overridden by |
| 181 | +class level annotations, which in turn are overridden by method level |
| 182 | +annotations. |
| 183 | + |
| 184 | +For annotations that can be used at the class level and at the package |
| 185 | +level, the implementation should look for the annotation on the class |
| 186 | +first [XXX - possibly following the superclass hierarchy if the annotation is not |
| 187 | +marked @Inherited]. If the annotation isn't found, the implementation |
| 188 | +should look for the annotation on the package for the class [XXX - possibly |
| 189 | +following the superclass hierarchy and considering the package for each |
| 190 | +superclass if the annotation isn't marked @Inherited]. |
| 191 | + |
| 192 | +JAXB uses package level annotations in this way. |
| 193 | + |
| 194 | +> XXX - It's unclear what the inheritance rules for package level annotations should be. |
| 195 | +
|
| 196 | + |
| 197 | + |
| 198 | +### Annotations vs. deployment descriptors |
| 199 | + |
| 200 | +In general, information in deployment descriptors should override |
| 201 | +information in annotations. In some cases, the information combines, |
| 202 | +such as for injection target specifications or for interceptors. |
| 203 | +In rare cases, an annotation can override a deployment descriptor entry; |
| 204 | +see the web fragments section below. |
| 205 | + |
| 206 | +From (the proposed update to) the Java EE platform spec: |
| 207 | + |
| 208 | + The following list describes the rules for how a deployment |
| 209 | + descriptor entry may override a Resource annotation. |
| 210 | + |
| 211 | + - The relevant deployment descriptor entry is located based on |
| 212 | + the JNDI name used with the annotation (either defaulted or |
| 213 | + provided explicitly). |
| 214 | + |
| 215 | + - The type specified in the deployment descriptor must be |
| 216 | + assignable to the type of the field or property. |
| 217 | + |
| 218 | + - The description, if specified, overrides the description |
| 219 | + element of the annotation. |
| 220 | + |
| 221 | + - The injection target, if specified, defines additional |
| 222 | + injection points for the resource. |
| 223 | + |
| 224 | + - The mapped-name element, if specified, overrides the |
| 225 | + mappedName element of the annotation. |
| 226 | + |
| 227 | + - The res-sharing-scope element, if specified, overrides the |
| 228 | + shareable element of the annotation. In general, the |
| 229 | + Application Assembler or Deployer should not change this |
| 230 | + value as doing so is likely to break the application. |
| 231 | + |
| 232 | + - The res-auth element, if specified, overrides the |
| 233 | + authenticationType element of the annotation. In general, the |
| 234 | + Application Assembler or Deployer should not change this |
| 235 | + value as doing so is likely to break the application. |
| 236 | + |
| 237 | + - The lookup-name element, if specified, overrides the lookup |
| 238 | + element of the annotation |
| 239 | + |
| 240 | + It is an error to request injection of two resources into the |
| 241 | + same target. The behavior of an application that does so is |
| 242 | + undefined. |
| 243 | + |
| 244 | + |
| 245 | + |
| 246 | +### Web fragment descriptors vs web.xml and annotations |
| 247 | + |
| 248 | +An ejb-jar.xml in a war file is treated the same as a web-fragment.xml |
| 249 | +in terms of the interaction with web.xml for resources. |
| 250 | + |
| 251 | +A Resource entry in a web fragment descriptor overrides annotations |
| 252 | +**only in the corresponding library**, using the rules above. |
| 253 | + |
| 254 | +A Resource entry in a web.xml file overrides **all** attributes of any |
| 255 | +corresponding Resource entry in a web fragment descriptor, **except** |
| 256 | +for the injection targets, which are combined. |
| 257 | + |
| 258 | +A Resource entry in a web.xml file overrides a Resource annotation on a |
| 259 | +class in WEB-INF/classes using the rules above. |
| 260 | + |
| 261 | +A Resource annotation on a class in WEB-INF/classes overrides **all** |
| 262 | +attributes of any corresponding Resource entry in a web fragment descriptor. |
| 263 | +**This may be the only place where an annotation overrides a deployment |
| 264 | +descriptor entry.** |
| 265 | + |
| 266 | + |
| 267 | + |
| 268 | +### Repeated annotations |
| 269 | + |
| 270 | +In some cases it's desirable to allow a particular annotation to |
| 271 | +occur multiple times on a single element, usually with different |
| 272 | +parameters. The convention for allowing @SomeAnnotation to be |
| 273 | +repeated is to define a pluralized version of the annotation: |
| 274 | + |
| 275 | +```java |
| 276 | + public @interface SomeAnnotations { |
| 277 | + SomeAnnotation[] value(); |
| 278 | + } |
| 279 | +``` |
| 280 | + |
| 281 | +Used as: |
| 282 | + |
| 283 | +```java |
| 284 | + @SomeAnnotations({ |
| 285 | + @SomeAnnotation("value1"), |
| 286 | + @SomeAnnotation("value2") |
| 287 | + }) |
| 288 | + public class MyClass { ... } |
| 289 | +``` |
| 290 | + |
| 291 | +We're hoping that Java SE 8 will support this style more directly |
| 292 | +in the compiler, allowing: |
| 293 | + |
| 294 | +```java |
| 295 | + @SomeAnnotation("value1") |
| 296 | + @SomeAnnotation("value2") |
| 297 | + public class MyClass { ... } |
| 298 | +``` |
| 299 | + |
| 300 | + |
| 301 | + |
| 302 | +### Annotations vs. interfaces |
| 303 | + |
| 304 | +In some cases we use annotations to mark which classes and which methods |
| 305 | +should be used by the container for which purposes, and in other cases we |
| 306 | +specify this interface with a Java language interface. The following rules are |
| 307 | +used to choose which to use when: |
| 308 | + |
| 309 | +1. When defining an API that an application is going to implement and |
| 310 | + the container is going to call, use an interface, unless one of the |
| 311 | + following rules applies. |
| 312 | +2. If an application class is providing an API that's exposed to other |
| 313 | + applications, and that class also needs to provide methods that the |
| 314 | + container will call for lifecycle functions (or other container support |
| 315 | + or management functions), use an annotation to mark those methods so |
| 316 | + that the application has flexibility in the choice of names for those |
| 317 | + methods. |
| 318 | +3. If an application is going to expose an interface that another |
| 319 | + application (or user) is going to use **without** Java, use annotations |
| 320 | + to mark the methods that correspond to this interface. This avoids the |
| 321 | + need to define a Java interface that's never going to be used by anyone |
| 322 | + other than the one class implementing the interface. |
| 323 | +4. If there can be more than one occurrence of a method for a given |
| 324 | + purpose, use an annotation. |
| 325 | +5. If an interface is chosen and the interface has many methods, |
| 326 | + consider providing an "adapter" class that implements all the methods |
| 327 | + with nop implementations. Applications can then subclass this adapter |
| 328 | + class to avoid the need to implement all methods. It's often better to |
| 329 | + decompose the interface into multiple smaller interfaces. |
| 330 | + |
| 331 | + |
| 332 | +### Annotation Style |
| 333 | + |
| 334 | +Use correct types instead of strings for annotation attributes when possible. |
| 335 | + |
| 336 | +> XXX - Need guidance on use of Class vs. String for class names |
| 337 | +
|
| 338 | +For optional attributes, prefer these default values: |
| 339 | +* String - "" |
| 340 | +* int - -1 |
| 341 | +* Class - void.class |
| 342 | +* [] - \{ } |
| 343 | + |
| 344 | +Use enumerated types rather than magic String values when the set of |
| 345 | +possible options is finite and fairly small. |
| 346 | + |
| 347 | +Avoid nesting annotations more than one level. |
| 348 | + |
| 349 | +Rather than adding more and more different aspects to an annotation, |
| 350 | +try to separate the concerns by creating different annotations that |
| 351 | +may be applied together or independently. |
| 352 | + |
| 353 | +Use "value()" as the element name in an annotation that only has one |
| 354 | +element or if, when using the annotation, that one element is the |
| 355 | +one most commonly specified. |
| 356 | + |
| 357 | + |
| 358 | + |
| 359 | +### Open Issues |
| 360 | + |
| 361 | + |
| 362 | +Need to check JAXB annotations. |
| 363 | + |
| 364 | +Need to write up something that describes when it's appropriate to only |
| 365 | +add an annotation, or only add a deployment descriptor entry, vs. having |
| 366 | +both. |
| 367 | + |
| 368 | + |
0 commit comments