Issue Details (XML | Word | Printable)

Key: JDO-194
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Michael Bouschen
Reporter: Michael Watzek
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
JDO

JPOX does not support implicit variables.

Created: 28/Oct/05 01:16 AM   Updated: 05/Apr/06 06:12 AM
Component/s: tck2
Affects Version/s: None
Fix Version/s: JDO 2 rc1

Time Tracking:
Not Specified

Resolution Date: 27/Dec/05 06:41 AM


 Description  « Hide
JPOX throws an exception executing queries having implicit parameters (see below). The bug may be reproduced executing test case org.apache.jdo.tck.query.jdoql.variables.VariablesAndFields.

Query: SELECT FROM org.apache.jdo.tck.pc.company.Employee WHERE team.contains(employee) & employee.firstname == 'emp1First'

org.jpox.store.exceptions.NoSuchPersistentFieldException: Field "employee" does not exist in org.apache.jdo.tck.pc.company.Person or is not persistent
at org.jpox.store.rdbms.table.ClassTable.getFieldMapping(ClassTable.java:1790)
at org.jpox.store.expression.TableExpression.newFieldExpression(TableExpression.java:183)
at org.jpox.store.query.JDOQLQuery$Compiler.compileIdentifier(JDOQLQuery.java:1534)
at org.jpox.store.query.JDOQLQuery$Compiler.compilePrimary(JDOQLQuery.java:1299)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpressionNotPlusMinus(JDOQLQuery.java:1245)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpression(JDOQLQuery.java:1226)
at org.jpox.store.query.JDOQLQuery$Compiler.compileMultiplicativeExpression(JDOQLQuery.java:1179)
at org.jpox.store.query.JDOQLQuery$Compiler.compileAdditiveExpression(JDOQLQuery.java:1156)
at org.jpox.store.query.JDOQLQuery$Compiler.compileRelationalExpression(JDOQLQuery.java:1125)
at org.jpox.store.query.JDOQLQuery$Compiler.compileEqualityExpression(JDOQLQuery.java:1102)
at org.jpox.store.query.JDOQLQuery$Compiler.compileAndExpression(JDOQLQuery.java:1090)
at org.jpox.store.query.JDOQLQuery$Compiler.compileExclusiveOrExpression(JDOQLQuery.java:1078)
at org.jpox.store.query.JDOQLQuery$Compiler.compileInclusiveOrExpression(JDOQLQuery.java:1066)
at org.jpox.store.query.JDOQLQuery$Compiler.compileConditionalAndExpression(JDOQLQuery.java:1054)
at org.jpox.store.query.JDOQLQuery$Compiler.compileConditionalOrExpression(JDOQLQuery.java:1036)
at org.jpox.store.query.JDOQLQuery$Compiler.compileExpression(JDOQLQuery.java:1013)
at org.jpox.store.query.JDOQLQuery$Compiler.compilePrimary(JDOQLQuery.java:1346)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpressionNotPlusMinus(JDOQLQuery.java:1245)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpression(JDOQLQuery.java:1226)
at org.jpox.store.query.JDOQLQuery$Compiler.compileMultiplicativeExpression(JDOQLQuery.java:1179)
at org.jpox.store.query.JDOQLQuery$Compiler.compileAdditiveExpression(JDOQLQuery.java:1156)
at org.jpox.store.query.JDOQLQuery$Compiler.compileRelationalExpression(JDOQLQuery.java:1125)
at org.jpox.store.query.JDOQLQuery$Compiler.compileEqualityExpression(JDOQLQuery.java:1102)
at org.jpox.store.query.JDOQLQuery$Compiler.compileAndExpression(JDOQLQuery.java:1090)
at org.jpox.store.query.JDOQLQuery$Compiler.compileExclusiveOrExpression(JDOQLQuery.java:1078)
at org.jpox.store.query.JDOQLQuery$Compiler.compileInclusiveOrExpression(JDOQLQuery.java:1066)
at org.jpox.store.query.JDOQLQuery$Compiler.compileConditionalAndExpression(JDOQLQuery.java:1054)
at org.jpox.store.query.JDOQLQuery$Compiler.compileConditionalOrExpression(JDOQLQuery.java:1036)
at org.jpox.store.query.JDOQLQuery$Compiler.compileExpression(JDOQLQuery.java:1013)
at org.jpox.store.query.JDOQLQuery$Compiler.compileQueryStatement(JDOQLQuery.java:891)
at org.jpox.store.query.JDOQLQuery.compile(JDOQLQuery.java:569)
at org.jpox.store.query.JDOQLQuery.performExecute(JDOQLQuery.java:639)
at org.jpox.store.query.Query.executeWithMap(Query.java:907)
at org.jpox.store.query.Query.executeWithArray(Query.java:887)
at org.jpox.store.query.Query.execute(Query.java:819)
at org.apache.jdo.tck.query.QueryTest.execute(QueryTest.java:706)
at org.apache.jdo.tck.query.QueryTest.executeAPIQuery(QueryTest.java:625)
at org.apache.jdo.tck.query.QueryTest.executeAPIQuery(QueryTest.java:601)
at org.apache.jdo.tck.query.jdoql.variables.VariablesAndFields.testPositive(VariablesAndFields.java:148)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at org.apache.jdo.tck.JDO_Test.runBare(JDO_Test.java:204)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.textui.TestRunner.doRun(TestRunner.java:116)
at junit.textui.TestRunner.doRun(TestRunner.java:109)
at org.apache.jdo.tck.util.BatchTestRunner.start(BatchTestRunner.java:120)
at org.apache.jdo.tck.util.BatchTestRunner.main(BatchTestRunner.java:95)


 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Andy Jefferson added a comment - 06/Nov/05 06:59 AM
JPOX CVS does now implement implicit variables 9nightly builds dated 06/11/2005 or later), and the test would pass except for the fact that it has some errors.

query.jdoql.variables.VariablesAndFields
* several of the queries use & when they should use &&
* several of the queries use = when they should use ==

Craig Russell added a comment - 06/Nov/05 10:16 AM
In Java, there is a difference between & and &&, but in JDOQL there is not. So the use of & is equivalent to &&.

None of the queries should use = since it is illegal in JDOQL.

Andy Jefferson added a comment - 25/Nov/05 05:34 PM
This test passes and has for a week at least

Michael Watzek added a comment - 09/Dec/05 10:59 PM
The test cases MixedVariables and VariablesAndFields fail throwing NoClassDefFoundError. Both test cases use implicit vairables.

14:22:31,328 (main) DEBUG [org.apache.jdo.tck] - Executing API query: SELECT FROM org.apache.jdo.tck.pc.company.Employee WHERE team.contains(employee) & employee.firstname == 'emp1First'
14:22:31,343 (main) INFO [org.apache.jdo.tck] - Exception during setUp or runtest:
java.lang.NoClassDefFoundError: org/apache/jdo/tck/pc/company/employee (wrong name: org/apache/jdo/tck/pc/company/Employee)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:539)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:251)
at java.net.URLClassLoader.access$100(URLClassLoader.java:55)
at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
at org.jpox.JDOClassLoaderResolver.classOrNull(JDOClassLoaderResolver.java:449)
at org.jpox.JDOClassLoaderResolver.classForName(JDOClassLoaderResolver.java:140)
at org.jpox.util.Imports.resolveClassDeclaration(Imports.java:152)
at org.jpox.store.query.Query.resolveClassDeclaration(Query.java:844)
at org.jpox.store.query.JDOQLQuery$Compiler.compileIdentifier(JDOQLQuery.java:1993)
at org.jpox.store.query.JDOQLQuery$Compiler.compilePrimary(JDOQLQuery.java:1650)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpressionNotPlusMinus(JDOQLQuery.java:1598)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpression(JDOQLQuery.java:1579)
at org.jpox.store.query.JDOQLQuery$Compiler.compileMultiplicativeExpression(JDOQLQuery.java:1532)
at org.jpox.store.query.JDOQLQuery$Compiler.compileAdditiveExpression(JDOQLQuery.java:1509)
at org.jpox.store.query.JDOQLQuery$Compiler.compileRelationalExpression(JDOQLQuery.java:1469)
at org.jpox.store.query.JDOQLQuery$Compiler.compileEqualityExpression(JDOQLQuery.java:1446)
at org.jpox.store.query.JDOQLQuery$Compiler.compileAndExpression(JDOQLQuery.java:1434)
at org.jpox.store.query.JDOQLQuery$Compiler.compileExclusiveOrExpression(JDOQLQuery.java:1422)
at org.jpox.store.query.JDOQLQuery$Compiler.compileInclusiveOrExpression(JDOQLQuery.java:1410)
at org.jpox.store.query.JDOQLQuery$Compiler.compileConditionalAndExpression(JDOQLQuery.java:1398)
at org.jpox.store.query.JDOQLQuery$Compiler.compileConditionalOrExpression(JDOQLQuery.java:1380)
at org.jpox.store.query.JDOQLQuery$Compiler.compileExpression(JDOQLQuery.java:1357)
at org.jpox.store.query.JDOQLQuery$Compiler.compilePrimary(JDOQLQuery.java:1699)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpressionNotPlusMinus(JDOQLQuery.java:1598)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpression(JDOQLQuery.java:1579)
at org.jpox.store.query.JDOQLQuery$Compiler.compileMultiplicativeExpression(JDOQLQuery.java:1532)
at org.jpox.store.query.JDOQLQuery$Compiler.compileAdditiveExpression(JDOQLQuery.java:1509)
at org.jpox.store.query.JDOQLQuery$Compiler.compileRelationalExpression(JDOQLQuery.java:1469)
at org.jpox.store.query.JDOQLQuery$Compiler.compileEqualityExpression(JDOQLQuery.java:1446)
at org.jpox.store.query.JDOQLQuery$Compiler.compileAndExpression(JDOQLQuery.java:1434)
at org.jpox.store.query.JDOQLQuery$Compiler.compileExclusiveOrExpression(JDOQLQuery.java:1422)
at org.jpox.store.query.JDOQLQuery$Compiler.compileInclusiveOrExpression(JDOQLQuery.java:1410)
at org.jpox.store.query.JDOQLQuery$Compiler.compileConditionalAndExpression(JDOQLQuery.java:1398)
at org.jpox.store.query.JDOQLQuery$Compiler.compileConditionalOrExpression(JDOQLQuery.java:1380)
at org.jpox.store.query.JDOQLQuery$Compiler.compileExpression(JDOQLQuery.java:1357)
at org.jpox.store.query.JDOQLQuery$Compiler.compileExpressionFromString(JDOQLQuery.java:1287)
at org.jpox.store.query.JDOQLQuery$Compiler.compileFilter(JDOQLQuery.java:1118)
at org.jpox.store.query.JDOQLQuery$Compiler.performCompile(JDOQLQuery.java:920)
at org.jpox.store.query.JDOQLQuery$Compiler.executionCompile(JDOQLQuery.java:905)
at org.jpox.store.query.JDOQLQuery.performExecute(JDOQLQuery.java:622)
at org.jpox.store.query.Query.executeWithMap(Query.java:966)
at org.jpox.store.query.Query.executeWithArray(Query.java:939)
at org.jpox.store.query.Query.execute(Query.java:862)
at org.apache.jdo.tck.query.QueryTest.execute(QueryTest.java:1151)
at org.apache.jdo.tck.query.QueryTest.execute(QueryTest.java:1029)
at org.apache.jdo.tck.query.QueryTest.executeAPIQuery(QueryTest.java:966)
at org.apache.jdo.tck.query.QueryTest.executeAPIQuery(QueryTest.java:946)
at org.apache.jdo.tck.query.jdoql.variables.VariablesAndFields.testPositive(VariablesAndFields.java:152)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at org.apache.jdo.tck.JDO_Test.runBare(JDO_Test.java:204)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.textui.TestRunner.doRun(TestRunner.java:116)
at junit.textui.TestRunner.doRun(TestRunner.java:109)
at org.apache.jdo.tck.util.BatchTestRunner.start(BatchTestRunner.java:120)
at org.apache.jdo.tck.util.BatchTestRunner.main(BatchTestRunner.java:95)

Andy Jefferson added a comment - 13/Dec/05 06:48 PM
And this is using what version of Subversion code exactly ? I'm using latest SVN and these tests still pass as mentioned previously.

Michael Bouschen added a comment - 21/Dec/05 01:53 AM
Yesterday (Dec 19) I updated my workspace and ran all the tests.
I see the same errors (NoClassDefFoundError) as Michael Watzek described above.

Andy Jefferson added a comment - 21/Dec/05 02:03 AM
And I have a clean checkout of about 30 mins ago and still get no errors whatsoever on those tests. Perhaps something in your setup ? I use Linux and Maven 1.0.2. You use Windows don't you Michael ? The issue is more than likely some windows case-sensitivity or file separator issue.

Michael Bouschen added a comment - 21/Dec/05 03:57 AM
Interesting! Yes, I'm using Windows. I think it has to do with queries using a variable with the same name as a class (modulo case). The above JDOQL query
  SELECT FROM org.apache.jdo.tck.pc.company.Employee WHERE team.contains(employee) & employee.firstname == 'emp1First'
defines an implicit variable called employee where Employee is the base name of the candidate class. It does not matter whether the variable is defined implicitly or explicitly. The problem disappears if I change the variable name to e.g. 'emp'.

The method names in the stack trace suggest that JPOX tries to resolve the identifier 'employee' as class name. Is that the case. Which occurrence of 'employee' is causing the problem, the contains argument or the left hand side of the equals comparison?

Andy Jefferson added a comment - 21/Dec/05 05:11 AM
JPOX would have to check for whether something is a class or not before falling back to "implicit variable". As for which variable "employee" is the issue I've no idea ... but then I don't see the issue so can't debug it. The stack trace line numbers provided by Michael above don't correspond to what I have in JPOX CVS either. Provide a valid stack trace using the most recent JPOX build, and just the part like the following

at org.jpox.util.Imports.resolveClassDeclaration(Imports.java:152)
at org.jpox.store.query.Query.resolveClassDeclaration(Query.java:844)
at org.jpox.store.query.JDOQLQuery$Compiler.compileIdentifier(JDOQLQuery.java:1993)
at org.jpox.store.query.JDOQLQuery$Compiler.compilePrimary(JDOQLQuery.java:1650)

Without valid line numbers I can't do a thing.

Michael Bouschen added a comment - 21/Dec/05 08:06 AM
This is a part of the stack trace from todays run using the JPOX build available today:
        ...
at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
at org.jpox.JDOClassLoaderResolver.classOrNull(JDOClassLoaderResolver.java:449)
at org.jpox.JDOClassLoaderResolver.classForName(JDOClassLoaderResolver.java:140)
at org.jpox.util.Imports.resolveClassDeclaration(Imports.java:152)
at org.jpox.store.query.Query.resolveClassDeclaration(Query.java:844)
at org.jpox.store.query.JDOQLQuery$Compiler.compileIdentifier(JDOQLQuery.java:2019)
at org.jpox.store.query.JDOQLQuery$Compiler.compilePrimary(JDOQLQuery.java:1676)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpressionNotPlusMinus(JDOQLQuery.java:1624)
at org.jpox.store.query.JDOQLQuery$Compiler.compileUnaryExpression(JDOQLQuery.java:1605)
        ...
Please let me know in case you need more.

Andy Jefferson added a comment - 21/Dec/05 06:34 PM
Thanks for the stack trace Michael. Seems that some Windows JREs sometimes throw a NoClassDefFoundError and Unix JREs dont - nice consistent platform-independent approach. JPOX CVS (builds from 22/12/2005 onwards) now checks for this and acts accordingly. Give it a try since I can't :-)

Michael Bouschen added a comment - 24/Dec/05 06:22 AM
Sorry Andy, this seems to be a JRE problem when running on Windows. I tried, but the problem remains:
at java.lang.Class.forName(Class.java:141)
at org.jpox.JDOClassLoaderResolver.classForName(JDOClassLoaderResolver.java:164)
at org.jpox.util.Imports.resolveClassDeclaration(Imports.java:152)
at org.jpox.store.query.Query.resolveClassDeclaration(Query.java:844)
at org.jpox.store.query.JDOQLQuery$Compiler.compileIdentifier(JDOQLQuery.java:2082)

I did a simple test case. A Class.forName("foo.bar") when there is a class foo.Bar results in the same exception when running on Windows.
I propose I change the test case and rename the variable from employee to emp to avoid the Windows issue. I assigned the issue to me already.

Craig Russell added a comment - 27/Dec/05 06:11 AM
We are going to file a bug on the JRE saying that behavior for classes that don't exist is inconsistent based on the platform and the name. Specifically, it seems that Windows platforms get confused trying to resolve class names that differ in capitalization from real class names.

There are two action items to take away.

1. JDO implementations should behave defensively and treat both NoClassDefFoundError and ClassNotFoundException as "class does not exist". There is no reason to expect that Sun will timely fix this defect in the relevant Java platforms that JDO implementations support.

2. TCK test cases should be changed to avoid using variable names that conflict modulo capitalization with class names.

Michael Bouschen added a comment - 27/Dec/05 06:41 AM
I changed the variable names in test classes MixedVariables and VariablesAndFields to avoid a conflict modulo capitalization with class names.

I found and fixed the same issue in the following test classes:
- org.apache.jdo.tck.query.delete.DeleteQueryElements
- org.apache.jdo.tck.query.api.SingleStringQuery
- org.apache.jdo.tck.query.api.ChangeQuery
- org.apache.jdo.tck.query.jdoql.keywords.SingleString
- org.apache.jdo.tck.query.result.NPEInResultExpr
- org.apache.jdo.tck.query.result.VariableInResult
- org.apache.jdo.tck.query.result.ResultExpressions.java
- org.apache.jdo.tck.query.result.DistinctCandidateInstances

Andy Jefferson added a comment - 04/Jan/06 04:27 AM
> JDO implementations should behave defensively and treat both NoClassDefFoundError and ClassNotFoundException as "class does not exist".

FWIW. That is what JPOX builds have been doing since about 4 days ago.

Martin Zaun added a comment - 04/Feb/06 01:28 AM
> JDO implementations should behave defensively and treat both NoClassDefFoundError and ClassNotFoundException as "class does not exist".

In fact, this does not only include NoClassDefFoundErrors but LinkageErrors in general, see below.

>We are going to file a bug on the JRE saying that behavior for classes that don't exist is inconsistent based on the platform and the name. Specifically, it seems that Windows platforms get confused trying to resolve class names that differ in capitalization from real class names.

The JRE's behaviour doesn't strike me as inconsistent with the Java specs after consulting the Java Language Specification (3rd edition)
    http://java.sun.com/docs/books/jls/index.html
and, more detailed, the revised chapter 5 "Loading, Linking and Initializing" of the the Java VM Specification (2nd edition + latest amendments):
    http://java.sun.com/docs/books/vmspec/2nd-edition/ConstantPool.pdf

In a nutshell:
1) A ClassNotFoundException is thrown when no binary representation of a class could be found at all; a LinkageError, including NoClassDefFoundError, is thrown when some representation was found but it's "content" turns out not to be a feasible or the required class.

2) ClassLoader.loadClass() is a place where LinkageErrors may occur. (There are rules about when classloaders, which may employ an eager or lazy loading strategy, may throw such errors).

3) The process of finding of a binary representation of a class is specified as platform-dependent -- even for the bootstrap classloader. Note that user-defined classloaders have all freedom anyway (for instance, loading classes over the net).

So, a classloader may, by its rules, report to have located a binary representation for a class name, which then turns out not to be the required class, thus, resulting in a LinkageError.

The VM spec is explicit on this:

5.3.1 Loading Using the Bootstrap Class Loader
The following steps are used to load and thereby create the nonarray class or interface C denoted by N using the bootstrap class loader.
...
1. The Java virtual machine searches for a purported representation of C in a platform- dependent manner. Note that there is no guarantee that a purported representation found is valid or is a representation of C.

   Typically, a class or interface will be represented using a file in a hierarchical file system. The name of the class or interface will usually be encoded in the pathname of the file.

   This phase of loading must detect the following error:
   * If no purported representation of C is found, loading throws an instance of NoClassDefFoundError or an instance of one of its subclasses.