DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • OpenAPI From Code With Spring and Java: A Recipe for Your CI
  • How to Build a New API Quickly Using Spring Boot and Maven
  • Configurable Feign Client Retry With Reusable Library and DRY
  • From J2EE to Jakarta EE

Trending

  • Edge Computing in Utility IoT: Two Architecture Patterns That Actually Work
  • Java Backend Development in the Era of Kubernetes and Docker
  • DuckDB for Python Developers
  • Working With Cowork: Don’t Be Confused
  1. DZone
  2. Coding
  3. Java
  4. Querydsl vs. JPA Criteria, Part 5: Maven Integration

Querydsl vs. JPA Criteria, Part 5: Maven Integration

The first part takes a look at the Maven setup of Querydsl framework with Java EE and Jakarta. The second part sheds light on Querydsl solution with Maven classifiers.

By 
Arnošt Havelka user avatar
Arnošt Havelka
DZone Core CORE ·
Nov. 03, 23 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
9.9K Views

Join the DZone community and get the full member experience.

Join For Free

As most technologies or dependencies evolve fast, it's sometimes hard to make the initial setup or upgrade smoothly. The goal of this article is to provide a summary of the Maven setup for the Querydsl framework, depending on the used technology. After that, let's see a short overview of the Querydsl solution.

In This Article, You Will Learn

  • How to setup Querydsl with Spring Boot 2.x (i.e Java EE) and Spring Boot 3.x (i.e. Jakarta EE)
  • What is a Maven classifier
  • How is the Maven classifier used in Querydsl build
  • Usage of Eclipse Transformer Plugin

Querydsl Setup

There are several possibilities to set up Querydsl framework in a Spring Boot application. The correct approach depends on the technologies used. 

Before we get into it, let's start with the recommended official setup.

Official Setup

Querydsl framework has a nice documentation site. The Maven integration is described in Chapter 2.1.1 where the recommended setup is based on the following:

  • querydsl-jpa and querydsl-apt dependencies and
  • usage of apt-maven-plugin plugin. 

The querydsl-apt dependency isn't mentioned on the official site, but such dependency is needed for the generation of metadata Q classes (see Metadata article). If we don't use querydsl-apt dependency then we get the error like this:

Plain Text
 
[INFO] --- apt:1.1.3:process (default) @ sat-jpa ---
error: Annotation processor 'com.querydsl.apt.jpa.JPAAnnotationProcessor' not found
1 error


The full working Maven setup based on the official recommendation is like this:

XML
 
<dependencies>
  ...
  <dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
  </dependency>
  ...
</dependencies>

<build>
  <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>
      <dependencies>
        <dependency>
          <groupId>com.querydsl</groupId>
          <artifactId>querydsl-apt</artifactId>
          <version>${querydsl.version}</version>
        </dependency>
      </dependencies>
    </plugin>
  </plugins>
</build>

</project>


This setup is working, and the Maven build is successful (see the log below). Unfortunately, several errors can be found there. In our case, the logs contain e.g. error: cannot find symbol import static com.github.aha.sat.jpa.city.City_.COUNTRY.

Plain Text
 
[INFO] ---------------------< com.github.aha.sat:sat-jpa >---------------------
[INFO] Building sat-jpa 0.5.2-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- clean:3.2.0:clean (default-clean) @ sat-jpa ---
[INFO] Deleting <local_path>\sat-jpa\target
[INFO] 
[INFO] --- apt:1.1.3:process (default) @ sat-jpa ---
<local_path>\sat-jpa\src\main\java\com\github\aha\sat\jpa\city\CityRepository.java:3: error: cannot find symbol
import static com.github.aha.sat.jpa.city.City_.COUNTRY;
                                         ^
  symbol:   class City_
  location: package com.github.aha.sat.jpa.city
<local_path>\sat-jpa\src\main\java\com\github\aha\sat\jpa\city\CityRepository.java:3: error: static import only from classes and interfaces
import static com.github.aha.sat.jpa.city.City_.COUNTRY;
^
<local_path>\sat-jpa\src\main\java\com\github\aha\sat\jpa\city\CityRepository.java:4: error: cannot find symbol
import static com.github.aha.sat.jpa.city.City_.NAME;
                                         ^
  symbol:   class City_
  location: package com.github.aha.sat.jpa.city
...
19 errors
[INFO] 
[INFO] --- resources:3.2.0:resources (default-resources) @ sat-jpa ---
...
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 51, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] 
[INFO] --- jar:3.2.2:jar (default-jar) @ sat-jpa ---
[INFO] Building jar: <local_path>\sat-jpa\target\sat-jpa.jar
[INFO] 
[INFO] --- spring-boot:2.7.5:repackage (repackage) @ sat-jpa ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  15.680 s
[INFO] Finished at: 2023-09-20T08:43:59+02:00
[INFO] ------------------------------------------------------------------------


Let's focus on how to fix this issue in the next parts.

Setup for Java EE With Spring Boot 2.x

Once I found this StackOverflow issue, I realized that the querydsl-apt plugin is no longer needed. The trick lies in using querydsl-apt a dependency with a jpa classifier instead of using the apt-maven-pluginplugin. 

Note: the querydsl-apt plugin seems to be deprecated since Querydsl 3 (see the following).

With that, the simplified Maven setup looks like this:

XML
 
<dependencies>
  ...
  <dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
  </dependency>
  <dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <version>${querydsl.version}</version>
    <classifier>jpa</classifier>
    <scope>provided</scope>
  </dependency>
  ...
</dependencies>


Note: Once we specify the classifier, we also need to specify a version of the dependency. Therefore, we cannot rely on the version defined in Spring Boot anymore.

The logs from the Maven build are clean now.

Plain Text
 
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------------< com.github.aha.sat:sat-jpa >---------------------
[INFO] Building sat-jpa 0.5.2-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- clean:3.2.0:clean (default-clean) @ sat-jpa ---
[INFO] Deleting <local_path>\sat-jpa\target
[INFO] 
[INFO] --- resources:3.2.0:resources (default-resources) @ sat-jpa ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] Copying 1 resource
[INFO] Copying 2 resources
...
[INFO] 
[INFO] --- jar:3.2.2:jar (default-jar) @ sat-jpa ---
[INFO] Building jar: <local_path>\sat-jpa\target\sat-jpa.jar
[INFO] 
[INFO] --- spring-boot:2.7.5:repackage (repackage) @ sat-jpa ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  15.148 s
[INFO] Finished at: 2023-09-20T08:56:42+02:00
[INFO] ------------------------------------------------------------------------


Setup for Jakarta With Spring Boot 3.x

As Spring Boot 3 relies on Jakarta instead of Java EE specification, we need to adjust our Maven setup a little bit. The change is described in Upgrade to Spring Boot 3.0. This article is based on this.

Basically, we just need to use jakarta classifier instead of jpa classifier.

XML
 
<dependencies>
  ...
  <dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
    <version>${querydsl.version}</version>
    <classifier>jakarta</classifier>
  </dependency>
  <dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <version>${querydsl.version}</version>
    <classifier>jakarta</classifier>
    <scope>provided</scope>
  </dependency>
  ...
</dependencies>


The maven build output is the same as in the Java EE setup.

Maven Classifiers

Let's shed light on the Querydsl solution once we understand Maven classifier usage.

Querydsl Solution

Querydsl generates metadata Q classes for every entity in order to be able to write queries easily. The querydsl-apt dependency achieves it with an instance of JPAAnnotationProcessor  (see e.g., Java Annotation Processing and Creating a Builder for more details on annotation processing). The exact implementation of the annotation processor depends on the technology used. The desired processor is defined in javax.annotation.processing.Processor file located in the used querydsl-apt dependency. The content of this file has to have the full classpath to the desired annotation processor, e.g. com.querydsl.apt.jpa.JPAAnnotationProcessor.

Let's go back to the classifiers for a while. Querydsl supports several classifiers (e.g., JPA, jdo, roo, etc.), and each of them needs a different treatment based on the used technology. Therefore, Querydsl needs to specify the supported annotations for each technology.

For JPA, Querydsl supports these classifiers:

  • jpa classifier for the old Java EE (with javax.persistence package) and
  • jakarta classifier for a new Jakarta EE (with jakarta.persistence package) as you already know.

Purpose of Maven Classifier

The purpose of the Maven classifier is explained on the official site as follows:

The classifier distinguishes artifacts that were built from the same POM but differ in content. It is some optional and arbitrary string that — if present — is appended to the artifact name just after the version number.

As a motivation for this element, consider for example a project that offers an artifact targeting Java 11 but at the same time also an artifact that still supports Java 1.8. The first artifact could be equipped with the classifier jdk11 and the second one with jdk8 such that clients can choose which one to use.

Please check, e.g., this guide for more information about the Maven classifier usage.

In our case, all the available classifiers for querydsl-apt dependency are depicted below. They can also be listed online here. Similarly, you can also see all the classifiers for querydsl-jpa dependency here.

List of all classifiers

When com.querydsl.apt.jpa.JPAAnnotationProcessor class is de-compiled from querydsl-apt-5.0.0-jpa.jar and querydsl-apt-5.0.0-jakarta.jar dependencies then we can see the only difference (see depicted below) is in the used imports (see lines 5-11). As a result, the JPAAnnotationProcessor is capable of handling different annotations in our classes (see lines 16-20).

querydsl-apt-5.0.0-jakarta.jar

Use of Maven Classifier

All Maven classifiers supported by Querydsl are defined in descriptors element specified in pom.xml file (see lines 11-20) as:

XML
 
<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <id>apt-jars</id>
      <goals>
        <goal>single</goal>    
      </goals>
      <phase>package</phase>
      <configuration>
        <descriptors>
          <descriptor>src/main/general.xml</descriptor>
          <descriptor>src/main/hibernate.xml</descriptor>
          <descriptor>src/main/jdo.xml</descriptor>
          <descriptor>src/main/jpa.xml</descriptor>
          <descriptor>src/main/jakarta.xml</descriptor>
          <descriptor>src/main/morphia.xml</descriptor>
          <descriptor>src/main/roo.xml</descriptor>
          <descriptor>src/main/onejar.xml</descriptor>
        </descriptors>
        <outputDirectory>${project.build.directory}</outputDirectory>
      </configuration>
    </execution>    
  </executions>        
</plugin>


This configuration is used in order to build multiple JARs defined by descriptors (see above). Each descriptor defines all the specifics for the technology. Usually, the XML descriptor just specifies the source folder (see line 11 in jpa.xml).

XML
 
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
  <id>jpa</id>
  <formats>
    <format>jar</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <fileSets>
    <fileSet>
      <directory>src/apt/jpa</directory>    
      <outputDirectory>/</outputDirectory>
    </fileSet>
    <fileSet>
      <directory>${project.build.outputDirectory}</directory>    
      <outputDirectory>/</outputDirectory>
    </fileSet>            
  </fileSets>  
</assembly>


However, the definition of Jakarta EE is a little bit more complicated. The key part in jakarta.xml is unpacking of JAR (see line 16) and using the jakarta classifier (see line 18) in order to activate the Eclipse Transformer Plugin.

XML
 
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
  <id>jakarta</id>
  <formats>
    <format>jar</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <moduleSets>
    <moduleSet>
      <useAllReactorProjects>true</useAllReactorProjects>
      <includes>
        <include>${project.groupId}:${project.artifactId}</include>
      </includes>
      <binaries>
        <unpack>true</unpack>
        <includeDependencies>false</includeDependencies>
        <attachmentClassifier>jakarta</attachmentClassifier>
        <outputDirectory>/</outputDirectory>
      </binaries>
    </moduleSet>
  </moduleSets>
  <fileSets>
    <fileSet>
      <directory>src/apt/jpa</directory>    
      <outputDirectory>/</outputDirectory>
    </fileSet>
  </fileSets>
</assembly>


Note: the value in the id element is used as the classifier, see here.

Eclipse Transformer Plugin

The last piece in the puzzle lies in the usage of the already-mentioned org.eclipse.transformer.maven plugin.

Eclipse Transformer provides tools and runtime components that transform Java binaries, such as individual class files and complete JARs and WARs, mapping changes to Java packages, type names, and related resource names.

The org.eclipse.transformer.maven plugin is defined on lines 171-187 in querydsl-apt dependency as:

XML
 
<plugin>
  <groupId>org.eclipse.transformer</groupId>
  <artifactId>org.eclipse.transformer.maven</artifactId>
  <version>0.2.0</version>
  <executions>
    <execution>
      <id>jakarta-ee</id>
      <goals>
        <goal>run</goal>
      </goals>
      <phase>package</phase>
      <configuration>
        <classifier>jakarta</classifier>
      </configuration>
    </execution>
  </executions>
</plugin>


Note: See this blog for more information about Eclipse Transformer plugin usage.

Conclusion

This article has covered Querydsl setups for Java EE and Jakarta EE. The rest explained the usage of the Maven classifier by Querydsl.

The used source code (even though it wasn't a lot here) is available here.

Disclaimer: The article is based on my investigation when I tried to figure out the solution. Please let me know of any inaccuracies or misleading information. 

Apache Maven Java EE Spring Boot

Opinions expressed by DZone contributors are their own.

Related

  • OpenAPI From Code With Spring and Java: A Recipe for Your CI
  • How to Build a New API Quickly Using Spring Boot and Maven
  • Configurable Feign Client Retry With Reusable Library and DRY
  • From J2EE to Jakarta EE

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook