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
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • DGS GraphQL and Spring Boot
  • 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

  • Using Python Libraries in Java
  • Next Evolution in Integration: Architecting With Intent Using Model Context Protocol
  • Building Reliable LLM-Powered Microservices With Kubernetes on AWS
  • Software Delivery at Scale: Centralized Jenkins Pipeline for Optimal Efficiency
  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
8.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

  • DGS GraphQL and Spring Boot
  • 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
Oops! Something Went Wrong

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

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

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 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!