8

We are using a setup with Spring Boot, Hibernate, Query DSL and Maven with Java 1.8

Recently, I've added Query DSL to the project with the configuration listed below. To make it work, I had to configure the Java Compiler in the eclipse project settings to allow Annotation Processing and also add the Query DSL .jar file to the eclipse Annotation Factory Path.

This setup worked as expected. It generated the custom Q classes and I could use them in my code. When now running the mvn clean install on the command line, every class in my code throws the error cannot find symbol, because the class is missing. Is there anything else I need to configure - similar to the .jar file in the eclipse settings - to make the build process work?

EDIT: This question is not a duplicate of this question because I did not ask why this error (cannot find a symbol) occurs but rather how to configure QueryDSL to also work on the command line.

EDIT2: I have now tried to integrate the build-helper-maven-plugin to use multiple source paths as an input. This did not help either. I also tried to generate the files into a src folder. It did not help either.

When I first compile the library in eclipse, the mvn compile goes through on the command line, but mvn clean compile still fails, because it just uses the compiled files of eclipse again. The apt-maven-plugin is executed, which can be seen just before the build process fails:

[INFO] --- apt-maven-plugin:1.1.3:process (default) @ project1 ---
[INFO]
[INFO] --- build-helper-maven-plugin:1.9.1:add-source (add-source) @ project1 ---
[INFO] Source directory: C:\Users\user1\git\project1\src\main\generated added.
[INFO]
[INFO] --- maven-processor-plugin:2.2.4:process (process) @ project1 ---
[ERROR] diagnostic: [...]

EDIT3: When I remove every import statement which is referring to the Q classes, the build process goes through (obviously). It is, however, remarkable, that the Q classes get compiled correctly in that case. They appear in the target folder as .class files as they should. Could it be, that the Q classes are compiled too late?


Here is an excerpt of the pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    [...]
    <prerequisites>
        <maven>3.0.0</maven>
    </prerequisites>

    <dependencies>
        [...]
        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-apt</artifactId>
            <version>4.1.3</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-jpa</artifactId>
            <version>4.1.3</version>
        </dependency>
    </dependencies>

    <build>
        <defaultGoal>spring-boot:run</defaultGoal>
        <plugins>
            [...]
            <plugin>
                <groupId>com.mysema.maven</groupId>
                <artifactId>apt-maven-plugin</artifactId>
                <version>1.1.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>target/generated-sources/java</outputDirectory>
                            <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        [...]
    </build>
</project>

This is the configuration of the eclipse project settings:

enter image description here

This is the error message which is displayed in the console:

[INFO] --- maven-processor-plugin:2.2.4:process (process) @ project1 ---
[ERROR] diagnostic: C:\Users\user1\git\project1\src\main\java\com\project1\repository\UserRepositoryImpl.java:3: error: cannot find symbol
import static com.project1.domain.QUser.user;
                                     ^
  symbol:   class QUser
  location: package com.project1.domain

[ERROR] diagnostic: C:\Users\user1\git\project1\src\main\java\com\project1\repository\UserRepositoryImpl.java:3: error: static import only from classes and interfaces
import static com.project.domain.QUser.user;
^
ssc-hrep3
  • 15,024
  • 7
  • 48
  • 87
  • 3
    Possible duplicate of [What does a "Cannot find symbol" compilation error mean?](https://stackoverflow.com/questions/25706216/what-does-a-cannot-find-symbol-compilation-error-mean) –  May 30 '18 at 15:24
  • As I've written above, it is perfectly clear why this error occurs. The generated class is not there, because it is not generated correctly while running `mvn compile` on the command line. It is then imported and obviously not found. The answer, however, should resolve this underlying problem and not go into details about this error. Therefore, not a duplicate @feelingunwelcome – ssc-hrep3 May 30 '18 at 16:15

6 Answers6

3

This is old question but this is how i find my solution, added classifier for jpa dependency:

    <!-- BEGIN: 'querydsl-jpa' -->
    <dependency>
        <groupId>com.mysema.querydsl</groupId>
        <artifactId>querydsl-jpa</artifactId>
        <version>${querydsl-jpa.version}</version>
        <classifier>apt</classifier>
    </dependency>
    <!-- END: 'querydsl-jpa' -->

My complete pom:

<!-- BEGIN: BUILD -->
<build>

    <!-- BEGIN: PLUGINS -->
    <plugins>

        <!-- BEGIN: apt-maven-plugin -->
        <plugin>
            <groupId>com.mysema.maven</groupId>
            <artifactId>apt-maven-plugin</artifactId>
            <version>${apt.version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>process</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>target/generated-sources/apt</outputDirectory>
                        <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <!-- END: apt-maven-plugin -->

    </plugins>
    <!-- END: PLUGINS -->

</build>
<!-- END: BUILD -->

<!-- BEGIN: DEPENDENCIES -->
<dependencies>

    <!-- *********************************************** -->
    <!-- BEGIN: 'QUERYDSL DEPENDENCIES'                  -->

    <!-- BEGIN: 'querydsl-apt' -->
    <dependency>
        <groupId>com.mysema.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <version>${querydsl-apt.version}</version>
    </dependency>
    <!-- END: 'querydsl-apt' -->

    <!-- BEGIN: 'querydsl-jpa' -->
    <dependency>
        <groupId>com.mysema.querydsl</groupId>
        <artifactId>querydsl-jpa</artifactId>
        <version>${querydsl-jpa.version}</version>
        <classifier>apt</classifier>
    </dependency>
    <!-- END: 'querydsl-jpa' -->

    <!-- *********************************************** -->
    <!-- END: 'QUERYDSL DEPENDENCIES'                    -->


</dependencies>
cmlonder
  • 2,370
  • 23
  • 35
3

For me, it didn't work because it conflicted with maven-compiler-plugin with already set annotation processor. Just deleted the use of apt-maven-plugin and added its annotation processor in maven-compiler-plugin.

    <build>
        <plugins>
<!--            related to issues:-->
<!--                - https://github.com/querydsl/querydsl/issues/2654 -->
<!--                - https://github.com/querydsl/querydsl/issues/2242 -->
<!--            Using apt-maven-plugin conflicts with other annotation processors (like mapStruct) -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                        <path>
                            <groupId>com.querydsl</groupId>
                            <artifactId>querydsl-apt</artifactId>
                            <version>5.0.0</version>
                            <classifier>jpa</classifier>
                        </path>
                        <path>
                            <groupId>jakarta.persistence</groupId>
                            <artifactId>jakarta.persistence-api</artifactId>
                            <version>2.2.3</version>
                        </path>
                        <path>
                            <groupId>javax.annotation</groupId>
                            <artifactId>javax.annotation-api</artifactId>
                            <version>1.3.2</version>
                        </path>
                        <!-- other annotation processors -->
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
<!--            <plugin>-->
<!--                <groupId>com.mysema.maven</groupId>-->
<!--                <artifactId>apt-maven-plugin</artifactId>-->
<!--                <version>1.1.3</version>-->
<!--                <executions>-->
<!--                    <execution>-->
<!--                        <goals>-->
<!--                            <goal>process</goal>-->
<!--                        </goals>-->
<!--                        <configuration>-->
<!--                            <outputDirectory>target/generated-sources</outputDirectory>-->
<!--                            <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>-->
<!--                        </configuration>-->
<!--                    </execution>-->
<!--                </executions>-->
<!--            </plugin>-->
        </plugins>
    </build>

But there is an issue with using querydsl annotation processor in maven-compiler-plugin. You have to add jakarta.persistence-api and javax.annotation-api.

1

I would rather use profile to generate these Qclasses only when db change occurs.

cons:

-your diff in pull requests is clean when you don't change db schema because for each generation these files tend to generate differently for some reason (atleast in my case).

-you can manage witch of tables present in your db will have Qclasses (sometimes it is a pain when you forget to regenerate them after changing db schema)

-well not that it is lots of time . but builds are faster if You don't change schema and profile is turned off.

Try something like this and turn on profile when You want to generate changed schema Qclasses :

<properties>
    <whitelisted.tables>
        user_accunt,
        other
    </whitelisted.tables>
</properties>
<profiles>
    <profile>
        <id>generate</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>com.querydsl</groupId>
                    <artifactId>querydsl-maven-plugin</artifactId>
                    <version>${querydsl.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>export</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <jdbcDriver>org.postgresql.Driver</jdbcDriver>
                        <jdbcUrl>jdbc:postgresql://localhost:port/dbname</jdbcUrl>
                        <packageName>your.package.name.for.q</packageName>
                        <jdbcUser>dbusername</jdbcUser>
                        <jdbcPassword>dbpassword</jdbcPassword>
                        <targetFolder>${project.basedir}/src/main/java/</targetFolder>
                        <spatial>true</spatial>
                        <tableNamePattern>${whitelisted.tables}</tableNamePattern>
                    </configuration>
                    <dependencies>
                        <dependency>
                            <groupId>org.postgresql</groupId>
                            <artifactId>postgresql</artifactId>
                            <version>42.1.1</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>
Szychan
  • 169
  • 1
  • 8
  • I would rather like to generate those files directly during the build. I have also several DTO Q classes which need to be generated, so it is not only required on a database change. But thanks anyway! – ssc-hrep3 Jun 08 '18 at 10:41
  • Is there a way to run a mvn script to just generate the Q classes e.g. into `src/main/generated` and then afterwards use this folder as a second source folder in a regular maven build? – ssc-hrep3 Jun 09 '18 at 07:59
  • provided MVN configuration allows You to use these classes in project. also You may always create different module to add dependency to another module/modules. I can imagine that is what You want to achieve. – Szychan Jun 11 '18 at 08:15
0

The generated-source directory are not automatically included in the jar.

You need to use the Maven build helper plugin to fix this issue, for example:

https://github.com/alexec/javahelp-skeleton/blob/master/pom.xml

  • Thanks, I've already tried that, without any success. The source is added (according to the maven logs) but the same error occurrs.. – ssc-hrep3 Jun 09 '18 at 07:58
0

You can try out few things:

1.try to put <clearOutputDir>false</clearOutputDir> in your configuration tag
2. Sometimes classes might not be getting generated before the compile phase. So try to put phase in your plugin

   <execution>
        <phase>generate-sources</phase>
        <goals>
            <goal>...</goal>
        </goals>
    </execution>


Vivek Shukla
  • 711
  • 9
  • 18
0

By convention Maven assumes all source code is in 'src/main/java', compiles this and put all *.class file in target.

So if you have a class 'Alien.java' in <project-root>/alice/in/wonderland, your won't be able to access it (in src/main/java) because maven puts everything from src/main/java in classpath for your compiler and hence compiler is unaware of any source code (*.java) anywhere else.

In your case you are generating your source code in directory target/generated-sources/java, so you will have to tell maven about it. As mentioned in some other answers you may use build-helper-plugin for this, let maven know that your source resides on target/generated-sources/java by

 <project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>target/generated-sources/java</source>
                <source>alice/in/wonderland</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Edit: You have mentioned wrong path in build-helper-plugin

I see although you are using build helper plugin but you are using wrong path

 --- build-helper-maven-plugin:1.9.1:add-source (add-source) @ project1 ---
[INFO] Source directory: C:\Users\user1\git\project1\src\main\generated added.

Instead of src\main\generated you should use <source>target/generated-sources/java</source>

old-monk
  • 799
  • 8
  • 20
  • I've played around with this plugin, but it doesn't seem to do anything at all. The output says, that the additional path was added, but it still fails to compile. – ssc-hrep3 Jun 08 '18 at 15:47
  • I've also tested multiple paths, therefore `src/main/generated` and `target/generated-sources/java` – ssc-hrep3 Jun 08 '18 at 15:48
  • @ssc-hrep3 can you give the complete stacktrace of maven? – old-monk Jun 08 '18 at 15:53