DRAFT PROPOSAL Pot Pourri - Augmented Stack Traces, ServiceProvider annotation and processor, Enhanced For Loop utility class
Bruce Chapman & Barbara Carey
cadenza at paradise.net.nz
Sat Mar 1 20:36:19 PST 2008
DRAFT PROPOSAL Pot Pourri - Augmented Stack Traces, ServiceProvider
annotation and
processor, Enhanced For Loop utility class
Bruce Colin Chapman
cadenza at paradise.net.nz
I propose three independant additions to the JDK APIs.
o Augmented Stack traces
o ServiceProvider Annotation and Processor
o Enhanced For loop Utility Class
Augmented Stack Trace
=====================
Exceptions allow contextual information to be added at the point they
are thrown (actually
the point they are created but its generally the same location) via
Throwable's message
mechanism. Additional context may be added further up the stack if the
exception is caught
and wrapped in another exception containing the original as a cause and
a new message with
the additional context information. Contextual information is useful and
often critical to
resolving faults.
I propose a mechanism to add contextual information (a short String) to
an Exception's
stack trace at the StackTraceElement corresponding to where the
mechanism is invoked from.
This will be particularly useful when traversing composite pattern data
structures as each
Node can catch any exceptions, augment them with its identity in some
form, and rethrow the
exception. Any stack trace will then include the path to the node that
was being processed
when the exception was thrown.
Also in Java Server Faces, exceptions thrown from managed beans invoked
from EL expressions
in a page can be hard to track down because neither the component
containing the EL
expression or the expression text itself is shown in the stack trace.
Using the proposed
mechanism, both the ID of the component being processed, and the EL
expression itself could
be included in any stack traces for exceptions thrown while processing
the EL expression.
This mechanism provides a relatively easy way for key contextual
information to be added to
an exception's stacktrace as the exception passes through a method.
As an example usage
String expr = ...; // an expression that will be interpreted
try {
eval(expr);
} catch (KnownException k1) {
StackTraceElement.augment(k1,expr);
throw k1;
} catch (RuntimeException re) {
StackTraceElement.augment(re,expr);
throw re;
}
StackTraceElement will be extended so that a StackTraceElement will have
a private String
field to contain the augmented context. This will default to null.
Throwable.printStackTrace() will be modified to print the augmented
context String field
(but only the first (say) 60 characters if it is longer) when it is a
available. The
context information will be printed on a line below the rest of the
StackTraceElement.
StackTraceElement will have a static method which will take a Throwable,
and a String. The
string will be added to the Throwable's StackTraceElement which
corresponds to the caller
of the static method.
Assistance From Sun
-------------------
None required.
Obtaining the current stack trace depth can be done by getting a current
stack trace and
looking at its length. However experiments show this to be inefficient
from a performance
perspective. Although the proposal can be implemented with existing JVM
code, a method
similar to Throwable.fillinStackTrace() which merely returns the length
that the stack
trace would be if it were to be filled in would improve performance.
Such a method is not
part of this proposal but would aid performance of it.
A Complete Implementation
-------------------------
A Complete implementation includes working implementation which can be
invoked in a way
similar to the example above and which when an exception is processed,
its stackTrace will
print with the augmented data visually associated to the correct
StackTraceElement. A
complete implementation will include tests for normal use cases, and
corner cases that
become apparent during development. A complete implementation will
include javadocs of at
least a comparable standard to the JDK javadocs.
Service Provider Annotation and Processor
=========================================
Java 6 introduced java.util.ServiceLoader class to perform service
loading as previously
specified in the jar spec (IIRC) but whose implementation was in a sun.*
package.
One of the difficulties of using this mechanism is correctly generating the
/META-INF/services/ file. Although not difficult there is no
verification that the file is
correctly placed and named. Errors in the file's path cause the feature
to appear to
silently fail because the required file doesn't exist the Service
Provider is not found.
Managing the content of the file is not difficult but can be tedious.
I propose a new Annotation with a corresponding AnnotationProcessor
which will create and
maintain the META-INF/services files for any classes that declare
themselves as being
service providers.
There are two approaches to be investigated. One will be implemented.
Approach 1.
The annotation will have a single value member to specify the class of
the Service, it is
for this service that the file will be managed.
Approach 2.
The Service provider annotation will be a marker annotation. Another
marker annotation will
be used to identify abstract classes and interfaces which are services
(designed to have
providers loaded by ServiceLoader). In this approach a service
provider's corresponding
service will be discovered by looking for a supertype annotated as a
service. This approach
would involve identify all existing Services and annotating them.
A hybrid approach is also possible, prefer 2 but 1 can be used when the
Service is not
annotated.
The Annotation processor will manage the META-INF/services/* files. It
will behave
correctly in the face of incremental compiles. Specifically
Given two classes A and B each annotated as service providers of C then
o IF A and B are compiled together META-INF/services/C will contain A
and B.
o After a clean, if only A is compiled, META-INF/services/C will contain A
o IF B is then compiled, META-INF/services/C will contain both A and B
o If the annotation is then removed from A, and A is recompiled,
META-INF/services/C will
contain B (A will be removed from META-INF/services/C).
Assistance from Sun
--------------------
None.
A Complete Implementation
-------------------------
A Complete implementation includes a working implementation. A complete
implementation will
include tests for normal use cases, and corner cases that become
apparent during
development. A complete implementation will include javadocs of at least
a comparable
standard to the JDK javadocs.
Enhanced For loop Utility Class
===============================
I propose a new utility class in java.util with static methods for
creating Iterables from
various types that are not Iterables so that they may be looped over
using JDK5's enhanced
for loop.
The class will be called "In".
It will contain (at least) the following methods
to loop over an Enumeration
static <T> Iterable<T> each(Enumeration<T> enumeration)
To loop (with a single loop) over a number of separate Iterables in sequence
static <T> Iterable<T> sequence(Iterable<? super T>... subsequences)
to Loop (with a single loop) over two Iterables at the same time
static <T,U> Iterable<Pair<T,U>> tandem(Iterable<T> left, Iterable<U> right)
(This would also involve creating java.util.Pair to model a 2 tuple)
I propose to look for other cases where such a helper method would be
valuable, and
implement those. Some ideas are SQL RowSets, parts of DOM with indexed
access and possibly
looping over the lines in a BufferedReader. Inter package dependencies
need to be managed
correctly for these so may not be desirable. Also they needs to be done
in such a way as to
avoid checked exceptions that may be thrown in the process of
implementing next().
The Iterables returned may possibly also be the implementations of
Iterator (for
lightweightness) in which case the Iterables will only be able to have
their iterator()
method called once, otherwise an IllegalStateException will be thrown.
When used only in
enhanced for loops this restriction will have no effect. This is for
further investigation.
Assistance from Sun
--------------------
None.
A Complete Implementation
-------------------------
A Complete implementation includes a working implementation of
java.util.Pair and
java.util.In with at least the functionality of the three static methods
described above. A
complete implementation will include tests for normal use cases, and
corner cases that
become apparent during development. A complete implementation will
include javadocs of at
least a comparable standard to the JDK javadocs.
Original Work
=============
Relevance To Community
======================
Each of these API additions adds to ease of development.
Augmented Stack Trace provides a means for API developers to provide
additional information
for diagnosing the cause of unexpected exceptions where appropriate.
This assists users of
those APIs. The leveraged benefit when a commonly used framework adds
this information can
be enormous.
ServiceProvider Annotation and Processor automates the process of
creating and managing
META-INF /services files and as a by product the annotations provide
autmatic documentation
of Service Providers.
Enhanced For loop Utility Class extends the applicability of the
enhanced for loop to a
large number of cases where currently it cannot be used.
While ServiceProvider Annotation and Processor has a somewhat specialist
audience, the
other two will provide benefits to almost any java developer.
Project Management
==================
The project will be run as one (or maybe three) projects within the
OpenJDK Core Libraries
Group. An open repository will be used for source management, and a
mailing list will be
used to keep interested parties up to date, and to inform design decisions.
Project Plan
============
18 March 2008:
Inception
8 Apr:
Project setup complete. openJDK orientation complete.
22 Apr:
Design and Strawman and API Docs Draft completed for review (all 3
parts)
6 May:
Design and API docs review complete
20 May:
Design and API Docs Completed
4 July:
Test Suite and Implementation complete
Project complete
4 Aug:
Project stage complete
Sole Work
=========
The idea for java.util.In.each(Enumeration) has been published under a
different class name
in the Java Specialist newsletter. The rest of this proposal is my sole
work.
Developer's Experience
======================
The developer is Bruce Chapman. Bruce served on the JSR 269 (Annotation
Processing) expert
group. Bruce has around 10 years experience developing with Java.
Copyright
=========
This proposal is hereby contributed under the terms of the Sun
Contributor Agreement. The
implementation will be contributed under the terms of the Sun
Contributor Agreement.
More information about the challenge-discuss
mailing list