SUBMISSION : A second look on "named parameters"

Jean-Baptiste Bugeaud bugeaud at gmail.com
Sat Apr 18 15:15:42 PDT 2009


Hi everybody,

Here is an late submission, sorry I missed the initial deadline. If
you think (as I do) that this is a key small change for lots of
improvement, maybe there is still a very small gap to go for JDK7;-)

A proposition including the same goal was introduced in JDK6 JSR but
withdawn in final version. So legacy impact, issues ... should be
already well known by the JDK core team. This second look has tried to
solve all the problems.

Let's go ....

Author(s): Jean-Baptiste BUGEAUD, Paris, France

OVERVIEW :
  FEATURE SUMMARY : Introduce named parameter on methods into the language
  MAJOR ADVANTAGE : Integration with the legacy, fully backward
compatible. Clear paradigm separation.
  MAJOR BENEFIT : Consistent way of naming the parameter help to unify
existing APIs, remove boiler plate core thus simplify object
marshaling and reflection usage (WS, JMX, EJB ...).
  MAJOR DISADVANTAGE : Semantic of static keyword on parameter might
not be clear for beginers
  ALTERNATIVES : Usage of existing bytecode handling lib can expose
the parameter names already, but this leads to dependency [5][6] and
potential security issues. Usage of APT[7] to store parameter names
constraint to a prequirement : apply it to all the code you target.
This is unlikely to happen for JARS you have not created, thus
reducing the potential benefits.

EXAMPLE

SIMPLE EXAMPLE :

(1a) :

class OrderManager{
 public void order(String product, int amount){
  // do the login
 }
}

(1b)

class OrderManager{
 public void order(static String product, static int amount){
  // do the login
 }
}

(2a)
void displayOrderCriteria(){
 Method[] methods = OrderManager.class.getMedthods();
 for (Method m : methods){
  System.out.println("To call :"+m);
  for(String n : m.getParameterNames[]){
   System.out.println("\tYou must provide :"+n);
  }
 }
}

(2b)
void displayOrderCriteria(){
 Method[] methods = OrderManager.class.getMedthods();
 for (Method m : methods){
  System.out.println("To call :"+m);
  for(String n : m.getStaticParameterNames[]){
   System.out.println("\tYou must provide :"+n);
  }
 }
}

ADVANCED EXAMPLE :

(3.1)
package java.lang.annotation

@Documented
@Retention(value = RetentionPolicy.SOURCE)
@Target( { ElementType.METHOD, ElementType.ANNOTATION_TYPE })
 public @interface StaticParameterNames {
};

(3.2)

@Retention(value = RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD })
@Inside(WebService.class)
@ValidWebOperation
@StaticParameterNames
public @interface WebMethod {
 String operationName() default "";
 String action() default "";
};


(3.3)

@WebService
class LoginManager{
 @WebMethod public void doLogin(String user, char[] password){
  // simply log the user
 }
}

DETAILS

SPECIFICATION :

Historicaly, method's parameter names can be stored in the Java
bytecode using appropriate compiler switch [2]. Although, no standard
API is available to benefit from them they aready. But when compiler
optimisation is set or an obfuscater is enabled, then are no more
available. This is not reliable.

Such inconsistency, along with some other problems, have prevented the
inclusion for JDK6 of previous proposition [3][4].

This proposition of small language change, introduce named parameter
on methods into the language thru the add of a new language paradigm :
static named parameter. At source level, this new kind of parameter is
simply a regular parameter with the modifier static set on it.

As a summary, we will get two kind of parameters in the language :
 - regular named parameter (see method on (1a)) : the legacy, we "keep
the good-old way", parameter might be stored in bytecode depending on
compiler option, no change on language/semantic/compilation
 - static named parameter (see method on (1b)) : a regular named
parameter with a static modifier added, whatever happens (compiler
option, obfuscator, etc) parameter name will always be kept at
bytecode level.

At Java API level, on java.lang.reflec.Method, two new method will
help API implementer to leverage both kind of parameters.
 - String[] getParameterNames()
 - String[] getParameterStaticNames()

IDE would be most interrested into calling the first one. But API
implementer (such as JAXWS for instance) requiring a consistent
behavior could rely on the second. But they could downgrade on the
first one for legacy JAR if they wish so.

Introduction of an annotation StaticParameterNames could also be
leverage by API implementer to include automatic parameter name
storage. This one alone will ease lots of library code. For instance,
in JAXWS (see example 3.3), WebParam are now optional to get a web
service working : WebMethod would be enough as long as JAXWS
implementer apply StaticParameterNames on the WebMethod annotation
(see example 3.2).

COMPILATION :

Static named parameters are compiled the same way of regular named
ones but with addition of the static modifier set on the reference at
the bytecode level and the parameter name parameter kept in the table.
No compiler/optimizer/obfuscator should remove/change the parameter
names at bytecode level on a static named parameter.

Thus, at a higher level, although not taking part of the method
signature (and call resolution), the static named parameter could now
be seen as part of the method contract: changing a static named
parameter's name could have the same impact as renaming a method. This
is the developper resposability to analyze impact of such a change.

If a method is tagged with the annotation (or an inherited annotation)
StaticParameterNames, all its method parameter should be compiled as
if they were static named parameters.

TESTING :

Compile test classes (such as examples 1a & 1b) using compiler with
the feature enable with and without optimization enable (the one that
remove the parameter names on regular named parameters).

For each scenario (with & without optimization) :
Call the reflection API for listing regular named parameters, and
check according to the names that should be returned as per the test
class.
Call the reflection API for listing static named parameters, and check
according to the names that should be returned as per the test class.

LIBRARY SUPPORT :

Two methods must be added to java.lang.relfect.Method :

String[] getParameterNames()

List the parameter names as existing in the bytecode. No guaranty of
reliability is made : can be renamed, removed, added, ...
Array is of the same size of getParameterTypes(), for a given index,
if the corresponding name is not found a null value is returned.

String[] getParameterStaticNames()

List the static parameter names as existing in the bytecode. Those
named are reliable. Any change impact the contract.
Array is of the same size of getParameterTypes(), for a given index,
if the corresponding parameter is not tagged with static modifier, a
null value is returned.


StaticParameterNames (see example 3.1) annotation must be introduced
to indicate to the compiler all parameters of a tagged method are
meant to be static nammed parameters although not tagged with the
static modifier. This anotation can tag other annotation.


OTHER CHANGES:

 Any existing API willing to benefit from this feature, could inherit
from StaticParameterNames but this is out of scope of this proposal.

COMPATIBILITY

MIGRATION :
 Manual migration is done adding static modifier on parameters.
 Automatic migration could be done by APIs leader using the
StaticParameterNames annotation, thus all the existing code base would
be migrated at the next build automatically.


COMPATIBILITY :

 BREAKING CHANGES: no, this is the reason of using static modifier.
 EXISTING PROGRAMS: code using legacy class can benefit from the
getParameterNames(). But getParameterStaticNames() will always return
an array of null values.


REFERENCES

EXISTING BUGS

http://bugs.sun.com/view_bug.do?bug_id=6444738

URL FOR PROTOTYPE

None at this time. Early feasibility check in the native VM coden plus
pure Java code is feasible [5].


[1] http://paulhammant.com/blog/parameter-names-for-java6-question.html
[2] http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javac.html
[3] http://weblogs.java.net/blog/mreinhold/archive/2005/12/mustang_release.html
[4] http://blogs.sun.com/mr/entry/java_se_6_public_review
[5] http://paranamer.codehaus.org/
[6] http://www.jroller.com/eu/entry/using_asm_to_read_mathod
[7] http://weblogs.java.net/blog/emcmanus/archive/2006/06/using_annotatio.html



More information about the coin-dev mailing list