Announcement Announcement Module
Collapse
No announcement yet.
Repository extending spring data envers and querydsl Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Repository extending spring data envers and querydsl

    I'm playing with a branch of an existing web application that uses spring data repositories on spring data 1.1.0.RELEASE. The repo's extend QueryDslPredicateExecutor and JpaRepository to provide query methods to various services in a seperate layer.

    I'm trying to add to those repositories support for the spring data envers project and have an error at runtime when the repository is instantiated by an @Autowired call only when I extend the repo interface with both org.springframework.data.querydsl.QueryDslPredicat eExecutor and org.springframework.data.repository.history.Revisi onRepository. I reproduced the same issue using the Spring Data Envers project code from https://github.com/SpringSource/spring-data-envers.

    In order to reproduce:
    (Using Springsource Toolsuite)
    -Create new spring project.
    -Convert to maven project.
    -Delete the default pom.xml.
    -Import project from https://github.com/SpringSource/spring-data-envers.
    -Update project configuration with maven plug-in in STS.
    -Clean project.
    -Run as maven clean integration-test. Confirm the spring data envers project works.
    -Modify the pom.xml with
    Code:
    <plugin>
      <groupId>com.mysema.maven</groupId>
      <artifactId>maven-apt-plugin</artifactId>
      <version>1.0.3</version>
      <executions>
        <execution>
          <phase>generate-sources</phase>
          <goals><goal>process</goal></goals>
          <configuration>
            <outputDirectory>target/generated-sources/queries</outputDirectory>
            <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
          </configuration>
        </execution>
      </executions>
    </plugin>
    and
    Code:
    <dependency>
      <groupId>com.mysema.querydsl</groupId>
      <artifactId>querydsl-jpa</artifactId>
      <version>2.7.0</version>
    </dependency>
    		
    <dependency>
      <groupId>com.mysema.querydsl</groupId>
      <artifactId>querydsl-apt</artifactId>
      <version>2.7.0</version>
      <scope>provided</scope>
    </dependency>
    -Refactor (move) AbstractEntity.java, Country.java and License.java to the same package but under the src/main/java so the maven-apt-plugin will find the entites and create the QueryDSL Q classes.
    -Modify LicenseRepository to extend in addition QueryDslPredicateExecutor<License>.
    -Update project configuration with maven plug-in in STS.
    -Clean project.
    -Run as maven build clean integration-test.
    -This is where it fails the test (stack trace at the end of the post).

    In LicenseRepository.java if i comment out the extends RevisionRepository (and the lines where it's methods are called in the integration test); run the test again and it passes. If I reinstate extends RevisionRepository and commented out lines and remove the extends QueryDslPredicateExecutor it works. With both however it fails. While trying things I ended up getting the stack trace to change method from org.springframework.data.querydsl.QueryDslPredicat eExecutor.findAll() to the findOne() method by switching the order of the interfaces after extends but with the same fail result.

    Am I missing something about the repository interface structure or should it be able to implement both interfaces automatically at the same time (none of the methods are the same signature afaik)? If I'm being incredibly dim about this I apologise, but if it's a bug with data commons mixing up the methods or just spring data envers being a pretty raw project at the moment I'd like to know where to make a ticket.

    Stack trace (relevant parts):

    Code:
    ***snip***
    Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.data.envers.sample.LicenseRepository org.springframework.data.envers.repository.support.RepositoryIntegrationTest.licenseRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'licenseRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Could not create query metamodel for method public abstract java.lang.Iterable org.springframework.data.querydsl.QueryDslPredicateExecutor.findAll(com.mysema.query.types.Predicate,com.mysema.query.types.OrderSpecifier[])!
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506)
    ***snip***
    
    ***snip***
    Caused by: java.lang.IllegalArgumentException: Could not create query metamodel for method public abstract java.lang.Iterable org.springframework.data.querydsl.QueryDslPredicateExecutor.findAll(com.mysema.query.types.Predicate,com.mysema.query.types.OrderSpecifier[])!
    	at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:92)
    ***snip***
    
    ***snip***
    Caused by: java.lang.IllegalArgumentException: No property find found for type class org.springframework.data.envers.sample.License
    	at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:73)
    ***snip***

  • #2
    After some more digging it would seem the default factory that builds repository interfaces picked up from the package scan in <repositories base-package="foo.bar"> only handles querydsl or standard jpa repositories.

    Since spring data envers comes with it's own custom factory class, the best thing i can come up with to work around this problem is to declare all repositories manually as <repository id="repoName"> sub-elements of <repositories>. Since <repository> sub elements inherit factory-class from <repositories> you can set the envers factory on a repo by repo basis. But, I still have to declare a seperate repo interface for the envers extentions only.

    I think in order to get envers and querydsl interfaces from spring data to play together in one repo interface a custom factory that implements both and has some filtering on it's return like the JpaRepositoryFactory does in it's org.springframework.data.repository.support.Reposi toryFactorySupport.getRepositoryBaseClass() override. This still leaves the issue of filtering <repositories> as I beleive manual mode is triggered as soon as you use a <repository> sub element?

    Is this a modularity problem with the spring data commons layout - that these more specialized modules for data jpa clash in config and at runtime?

    Comment


    • #3
      For what it is worth - am experiencing the same problem. Would vote for a better solution....

      Comment


      • #4
        I ran into this as well. I opened an issue if you want to up vote it.

        https://jira.springsource.org/browse/DATAJPA-387

        Comment

        Working...
        X