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 14:41:17 PST 2008


DRAFT PROPOSAL pot Pourri #1

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 allows 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 origibal as a cause and 
a new message with

the aditional 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.

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.

This mechanism provides a relatively easy way for key contextual 
information to be added to

an exception's stacktrace the exception passes through a method.

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 ret 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
-------------------

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 ineffient 
from a performance

persepctive. Although the proposal can be implemented with existing JVM 
code, a method

similar to Throwable.fillinStackTrace() which merely returned the length 
that the stack

trace would 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.


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. Managing the content of the file 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.

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.

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 removed from A, and A is recompiled, 
META-INF/services/C will

contain B.
IF A and B are compiled together META-INF/services/C will contain A and B.

Assistance from Sun
--------------------
None.

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, and also it needs to be done in such a way as to 
manage 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 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. For further investigation.



More information about the challenge-discuss mailing list