Community
Participate
Working Groups
I ran into a problem with a new workspace, SQL stopped generating. I debugged and found that TemplateContext.primGetMethod was returning the wrong method. It should be returning SqlGetByKeyStatementTemplate.genStatementBody, but was returning SqlActionStatementTemplate.genStatementBody. I inspected templateClass.getMethods() and it was returning the super class methods before the class ie SqlActionStatementTemplate methods before SqlGetByKeyStatementTemplate. I looked at the workspace and saw it was using IBM v6 jre, my old workspace was using The Sun JRE. I switched to the SUN jre and the order was different, the super methods were after the class methods. In reading the Java docs and doing a google search I think we have a serious design flaw. The docs say "Returns an array containing Method objects reflecting all the public member methods of the class or interface represented by this Class object, including those declared by the class or interface and those inherited from superclasses and superinterfaces. Array classes return all the (public) member methods inherited from the Object class. The elements in the array returned are not sorted and are not in any particular order.". The last sentence is the flaw: methods are returned in no specific order and our code relies on finding the class method before the super method. From posts that I read in my google search (order returned by Java Class.getMethods) some people claim that if you recompile a class they have seen the order change.
The fix might be easy, change the method to use getDeclaredMethods and explicitly loop on the super types. Maybe: do{ for (Method m : templateClass.getDeclaredMethods()) { if(Modifier.isPublic(m.getModifiers())){ ......existing code starting after the for (Method m... } }while(method == null && (templateClass = templateClass.getSuperclass()) != null );
There's still a problem. The parameter-matching code doesn't take overloading into account. Say the class has two methods with the specified name. One takes an Object (I'll call this method A) and the other takes a String (method B). If the argument is a String, we should choose B, but if we happen to examine A first we'll choose it instead. A solution can be written based on code from RBD's JavaLib implementation, com.ibm.etools.egl.java\egljava\egl\java\JavaLib_Lib.java It has already been through the Java Runtime CQ. See the method called findMethod in JavaLib_Lib. egl.java.ArgInfo contains a lot of the useful code too. The JavaLib code needs to be updated because it was written before Java got autoboxing. ArgInfo has comments like "Primitives can't be converted to objects" and parts of its code are based on that assumption. For bonus points, make it work with a varargs parameter too.
*** Bug 358084 has been marked as a duplicate of this bug. ***
Tim and Paul (with some help from Joe) need to fix this.
fixed. We used Joe's suggestion.
Reopening to address Matt's question, for future.
current fix does not handle method overloading
setting this to 1.0, as it seems any fix in this area could be too risky for the impending .7 release. If anyone disagrees, please mention it here.
I agree that it should be deferred. Would be good to tackle this one early in the 1.0 cycle or we're likely to keep putting it off.
I found another case where this is causing problems. I'm using a development environment, with all plugins checked out and current. (In case you're reading this a while from now, we're just about to declare 0.8 M2.) I'm generating annotatedTest.egl from project org.eclipse.edt.tests.sql, from the kan-cvs-save server. Function insertRowWithExecuteStatement contains an execute statement. Its using clause includes variable row.nullableCol. As the name implies, it's nullable. We check for nullability in method genSetColumnValue of org.eclipse.edt.gen.java.templates.eglx.persistence\src\org\eclipse\edt\gen\java\templates\eglx\persistence\sql\SqlActionStatementTemplate.java, at line 366. Here's the code: protected void genSetColumnValue(SqlActionStatement stmt, Expression expr, String stmt_or_resultSet_var, int columnIndex, Context ctx, TabbedWriter out) { EGLClass type = (EGLClass)expr.getType().getClassifier(); Boolean isNullable = (Boolean)ctx.invoke("isNullable", stmt, ctx, expr); if(isNullable != null && isNullable){ When I run EDT in my IBM JRE, the isNullable variable is true. That's correct. But when I use my Sun JRE, isNullable is false. The IRs for the record and statement look the same in both cases. Here's the output of java -version from my Sun JRE: java version "1.6.0_30" Java(TM) SE Runtime Environment (build 1.6.0_30-b12) Java HotSpot(TM) Client VM (build 20.5-b03, mixed mode, sharing) Here's the output of java -version from my IBM JRE: java version "1.6.0" Java(TM) SE Runtime Environment (build pwi3260sr9fp1-20110208_03(SR9 FP1)) IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 Windows XP x86-32 jvmwi3260sr9-201102 03_74623 (JIT enabled, AOT enabled) J9VM - 20110203_074623 JIT - r9_20101028_17488ifx3 GC - 20101027_AA) JCL - 20110203_01
Oracle's "Java SE 7 and JDK 7 Compatibility" page at http://www.oracle.com/technetwork/java/javase/compatibility-417013.html mentions a change that may affect us if we switch from one JRE to another. Area: HotSpot Synopsis: Order of Methods returned by Class.get Methods can Vary Description: In JDK 7, build 129, the following reflective operations in java.lang.Class changed the fixed order in which they return the methods and constructors of a class: getMethods getDeclaredMethods getDeclaredConstructors This may cause issues for code that assumes (contrary to the specification) a particular order for methods or constructors. RFE: 7023180
lowering to normal severity, as the scope of the problem is limited.
I raised the severity because this is happening in at least SQL, IBMi, dedicated service invocation, and Tim is seeing this in a new generator that he is working on. I've seen 2 forum entries that I would attribute to this problem. It doesn't not happen consistently so it makes the product seem unstable. We need to address this in the next release.
fixed. see org.eclipse.edt.mof/src/org/eclipse/edt/mof/codegen/api/TemplateContext.java for the change. Look at the current class and determine if a method is parameter assignable from the arguments. If there is more than 1 method determine the most specific by comparing the methods on the current class to find the most specific. If no method is found look at the super class's methods.
verified