users@javaee-spec.java.net

[javaee-spec users] [jsr342-experts] _at_Priority

From: Bill Shannon <bill.shannon_at_oracle.com>
Date: Fri, 07 Dec 2012 09:48:29 -0800

Those of you tracking CDI 1.1 will notice that it has defined a new
way to control the order in which interceptors are run. An interceptor
can define a "priority" and interceptors are run in priority order.
To support this use, and other similar cases, we'd like to define a
@Priority annotation in the Common Annotations spec. Interceptors
annotated with @Priority would be *enabled by default*, and run at
the specified priority. The priority can be overridden in beans.xml.

The common annotation definition would be something as simple as this:

-----
package javax.annotation;

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

/**
 * The Priority annotation can be applied to classes to indicate
 * in what order the classes should be used. The effect of using
 * the Priority annotation in any particular instance is defined
 * by other specifications that define the use of a specific class.
 * <p>
 * For example, the Interceptors specification defines the use of
 * priorities on interceptors to control the order in which
 * interceptors are called.
 *
 * @since Common Annotations 1.2
 */
@Target({TYPE})
@Retention(RUNTIME)
@Inherited
@Documented
public @interface Priority {
    /**
     * The priority value.
     */
    int value();
}
-----

A key question for this group is... What should the name of this
annotation be?

We've been calling it @Priority, but other reasonable names are
@Order, @Rank, @SortIndex, and probably a dozen others you can
think of.


In addition, the CDI spec defines various ranges of priorities that
should be used for different purposes. We would define some constants
for these ranges:

-----
package javax.interceptor;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
 * <p>Specifies that a class is an interceptor.</p>
 *
 * <pre>
 * &#064;Interceptor
 * public class ValidationInterceptor { ... }
 * </pre>
 *
 * <p>This annotation is optional if the
 * {_at_link javax.interceptor.Interceptors Interceptors} annotation or
 * the EJB deployment descriptor are used to associate the
 * interceptor with the target class. It is required when an
 * {_at_linkplain javax.interceptor.InterceptorBinding interceptor binding}
 * is used.</p>
 *
 * @see javax.interceptor.Interceptors
 *
 * @since Interceptors 1.1
 */
@Retention(RUNTIME)
@Target(TYPE)
@Documented
public @interface Interceptor
{
    /**
     * <p>Priorities that define the order in which interceptors are
     * invoked. These values should be used with the
     * {_at_link javax.annotations.Priority Priority} annotation.
     * Interceptors defined by platform specifications should be in the
     * range PLATFORM_BEFORE up until LIBRARY_BEFORE, or starting at
     * PLATFORM_AFTER. Interceptors defined by extension libraries
     * should be in the range LIBRARY_BEFORE up until APPLICATION, or
     * LIBRARY_AFTER up until PLATFORM_AFTER. Interceptors defined
     * by applications should be in the range APPLICATION up until
     * LIBRARY_AFTER. An interceptor that must be invoked before or
     * after another defined interceptor can choose any appropriate
     * value.</p>
     *
     * <p>For example, an extension library might define an interceptor
     * like this:</p>
     *
     * <pre>
     * &#064;Priority(Interceptor.Priority.LIBRARY_BEFORE+1)
     * &#064;Interceptor
     * public class ValidationInterceptor { ... }
     * </pre>
     *
     * @since Interceptors 1.2
     */
    public static class Priority {
        private Priority() { } // don't allow instances

        /**
         * Start of range for early interceptors defined by
         * platform specifications.
         */
        public static final int PLATFORM_BEFORE = 0;

        /**
         * Start of range for early interceptors defined by
         * extension libraries.
         */
        public static final int LIBRARY_BEFORE = 100;

        /**
         * Start of range for interceptors defined by
         * applications.
         */
        public static final int APPLICATION = 1000;

        /**
         * Start of range for late interceptors defined by
         * extension libraries.
         */
        public static final int LIBRARY_AFTER = 2000;

        /**
         * Start of range for late interceptors defined by
         * platform specifications.
         */
        public static final int PLATFORM_AFTER = 3000;
    }
}
-----

Interceptor.Priority could instead be a separate InterceptorPriority class.
Or they could be defined directly on the Interceptor class as
Interceptor.PRIORITY_PLATFORM_BEFORE, etc. Let me know if you think
either would be better. Note that it can't be an enum because we want
to allow arithmetic. Any comments to improve the javadocs are greatly
appreciated.

Comments?