Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support serialization of any() paths in Querydsl JPA #1062

Closed
jotomo opened this issue Nov 28, 2014 · 9 comments
Closed

Support serialization of any() paths in Querydsl JPA #1062

jotomo opened this issue Nov 28, 2014 · 9 comments
Milestone

Comments

@jotomo
Copy link

@jotomo jotomo commented Nov 28, 2014

This is the same as #904, but for the JPA module. I can use any() in predicates in tests that run on the same JVM. But when running an integration tests, where I have a client that serializes a predicate containing any(), and a server which deserializes the predicate (on another JVM), then I'm getting this exception when attempting to execute the predicate (via Spring Data JPA):

Caused by: java.lang.IllegalArgumentException: Undeclared path 'standort'. Add this path as a source to the query to be able to reference it.
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:78)
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:30)
    at com.mysema.query.types.path.ListPath.accept(ListPath.java:77)
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:65)
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:30)
    at com.mysema.query.types.expr.SimpleOperation.accept(SimpleOperation.java:61)
    at com.mysema.query.types.ValidatingVisitor.visitJoins(ValidatingVisitor.java:123)
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:87)
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:30)
    at com.mysema.query.types.SubQueryExpressionImpl.accept(SubQueryExpressionImpl.java:57)
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:65)
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:30)
    at com.mysema.query.types.expr.BooleanOperation.accept(BooleanOperation.java:61)
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:65)
    at com.mysema.query.types.ValidatingVisitor.visit(ValidatingVisitor.java:30)
    at com.mysema.query.types.OperationImpl.accept(OperationImpl.java:91)
    at com.mysema.query.DefaultQueryMetadata.validate(DefaultQueryMetadata.java:351)
    at com.mysema.query.DefaultQueryMetadata.addWhere(DefaultQueryMetadata.java:193)
    at com.mysema.query.support.QueryMixin.where(QueryMixin.java:426)
    at com.mysema.query.support.QueryBase.where(QueryBase.java:127)
    at com.mysema.query.jpa.JPAQueryBase.where(JPAQueryBase.java:32)
    at org.springframework.data.jpa.repository.support.QueryDslJpaRepository.createQuery(QueryDslJpaRepository.java:139)
    at org.springframework.data.jpa.repository.support.QueryDslJpaRepository.findAll(QueryDslJpaRepository.java:115)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606

I reported another bug earlier, which also steemed from my setup of having a predicate serialized on one JVM and deserialized on another, which was caused by a bug in the caching code. In case it's releated it's #481.
P.S. The predicate is of the form QStandort.standort.detailsSet.any().detailField.isNotEmpty()

@timowest
Copy link
Member

@timowest timowest commented Nov 29, 2014

Which Querydsl version do you use?

@jotomo
Copy link
Author

@jotomo jotomo commented Nov 29, 2014

Sorry for forgetting such a basic detail ... I'm using 3.5.1. Tested with 3.5.0, 3.4.2 and 3.4.1 as well.

@timowest
Copy link
Member

@timowest timowest commented Nov 30, 2014

@jotomo I couldn't replicate it with serializing and deserializing a single predicate on one machine. Could you try to debug the comparison that leads to the exception?

@jotomo
Copy link
Author

@jotomo jotomo commented Dec 1, 2014

I toke the test from the referenced PR, adjusted it to my env and changed it to create a file with the serialized predicate on the first run. When running the test a second time the file is read and the predicate executed. This ensures serialization and deserialization happen on different JVMs.This is of course not a proper solution to be committed, but makes the issue reproducible (the test in the PR works fine here too).
My test then, looks like this:

    @Test
    public void Any_Serialized() throws Exception {
        Predicate where = QStandort.standort.abwasserbehandlungsanlages.any().herkunft.equalsIgnoreCase("TEST");

        Path path = Paths.get("d:/predicate.ser");

        if(Files.notExists(path)) {
            // serialize predicate on first run
            FileOutputStream fileOutputStream = new FileOutputStream(path.toFile());
            ObjectOutputStream out = new ObjectOutputStream(fileOutputStream);
            out.writeObject(where);
            out.close();

            assertThat(Lists.newArrayList(standortRepo.findAll(where)).size(), is(1));
        } else {
            // deserialize predicate on second run
            FileInputStream fileInputStream = new FileInputStream(path.toFile());
            ObjectInputStream in = new ObjectInputStream(fileInputStream);
            Predicate where2 = (Predicate) in.readObject();
            in.close();
            //Files.delete(path);

            assertThat(Lists.newArrayList(standortRepo.findAll(where2)).size(), is(1));
        }
    }

The relevant part being the file handling of course.
Let me know if this is useful or what else I can do to help to find the cause. I'll see if I can find anything by firing up the debugger in the above test.

@jotomo
Copy link
Author

@jotomo jotomo commented Dec 1, 2014

At the site of the exception:

exception-in-querydsl-validating-visitor

Inspecting the variables I can see that there's a hashcode mismatch, which is also shown in my test:

hashcode-mismatch-in-test

Thus, the contains check on the Set in ValidatingVisitor fails.

Edit: Actually, the predicates having different hashcodes might not be a problem, but expr.getRoot() (first image) evaluating to a different hashcode than the standort object in the known set is. I verified this is the case, but confused this in the second image.

@Shredder121
Copy link
Member

@Shredder121 Shredder121 commented Dec 1, 2014

which JVMs do you use? I also inspected some variables, but want to focus more on this issue.

@jotomo
Copy link
Author

@jotomo jotomo commented Dec 1, 2014

@Shredder121

java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

(JDK from Oracle)
On Win7, x64.

@timowest timowest added this to the 4.0.0 milestone Dec 7, 2014
@jotomo
Copy link
Author

@jotomo jotomo commented Dec 9, 2014

@timowest @Shredder121 I ran a local build in which I've applied the PR against the latest release and now all my tests are green too. Thanks a lot for fixing this issue so quickly, highly appreciated!

@timowest timowest modified the milestones: 3.6.1, 4.0.0 Dec 17, 2014
@timowest
Copy link
Member

@timowest timowest commented Jan 31, 2015

Released in 3.6.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

3 participants
You can’t perform that action at this time.