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