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

Comments

Projects
None yet
3 participants
@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

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Nov 29, 2014

Member

Which Querydsl version do you use?

Member

timowest commented Nov 29, 2014

Which Querydsl version do you use?

@jotomo

This comment has been minimized.

Show comment
Hide comment
@jotomo

jotomo 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.

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

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Nov 30, 2014

Member

@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?

Member

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

This comment has been minimized.

Show comment
Hide comment
@jotomo

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

This comment has been minimized.

Show comment
Hide comment
@jotomo

jotomo 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.

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

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Dec 1, 2014

Member

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

Member

Shredder121 commented Dec 1, 2014

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

@jotomo

This comment has been minimized.

Show comment
Hide comment
@jotomo

jotomo 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.

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

This comment has been minimized.

Show comment
Hide comment
@jotomo

jotomo 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!

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

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Jan 31, 2015

Member

Released in 3.6.1

Member

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