Keresés tartalomra
Kategóriák
Címkék
- Java
- Spring
- Python
- IoC
- Android
- DI
- Dagger
- Thymeleaf
- Markdown
- JDK11
- AOP
- Aspect
- Captcha
- I18n
- JavaSpark
- Microframework
- Testing
- JUnit
- Security
- JWT
- REST
- Database
- JPA
- Gépház
- WebFlux
- ReactiveProgramming
- Microservices
- Continuous Integration
- CircleCI
- Deployment Pipeline
- Docker
- Mocking
- LogProcessing
- PlantUML
- UML
- Modellezés
- OAuth2
- Node.js
- DevOps
- Websocket
Egyperces: QueryDSL kódgenerálás Java 21 alatt
A QueryDSL-t egy korábbi cikkemben már említettem, de emlékeztetőül, ez egy JPA query library, ami teljesen támogatott a Spring Data JPA által (gyakorlatilag része annak), segítségével egészen rugalmasan lehet egyedi lekérdezéseket írni. Mivel a JPA réteg része, működőképes SQL és NoSQL adatbázismotorokkal egyaránt, én MongoDB fölött használom. A bevezetőben említett metaosztályokat fordítási időben generálja, Maven és Gradle támogatása is van (bár Gradle alatt nem annyira egyszerű beállítani mint Maven esetében), problémát egészen Java 17-tel bezárólag nem is tapasztaltam vele. Aztán elkezdtem dolgozni a Java 21-re migráláson.
És itt kezdődtek a bajok. Fontos megjegyezni, hogy a QueryDSL egy ideje már tetszhalott állapotban van: a Spring Boot 3.x által is csomagolt 5.1.0-s verzió idén januárban jelent meg, az előző, 5.0.0-s verzió még 2021-ben. Bár az előbbi viszonylag jó jel, valójában a QueryDSL még mindig Java 11-el van fordítva, ami bizony már egy 6 éves verziója a Java-nak. A kódgeneráláshoz saját APT csomagot ad a library, azon belül pedig a cél adatbázismotornak megfelelő annotation processorral tudjuk generálni a metaosztályokat (Q-classok, a nevük miatt: mind úgy vannak elnevezve, hogy Q<EntityClassNév>
). A hivatalos dokumentáció Maven integráláshoz az APT Maven Plugin legfrissebb verzióját ajánlja (com.mysema.maven:apt-maven-plugin:1.1.3
), mellyel csupán egy probléma van: 2014-ben adták ki - ismétlem, ez a legfrissebb verzió. Java 21 alatt ez a kombináció már pontosan elég arra, hogy ne tudjon elindulni a metaosztályok generálása, bár meglepő módon pont nem az APT Maven Plugin okozza a problémát, hanem maga a QueryDSL APT modulja, egyszerűen nem tud mit kezdeni a Java 21-es forrásokkal.
Szerencsére több megoldás is rendelkezésünkre áll. Az egyik, talán legkézenfekvőbb a QueryDSL forkja, melyet a Feign REST kliens implementációt is "elkövető" OpenFeign vett gondozásába, és a fork 6.x verziói már támogatják a Java 21 és afölötti verziók használatát is. A probléma ezzel, hogy a fork is az APT Maven Pluginra támaszkodik, ami bár működik, személy szerint nem szívesen bízok friss verziókra támaszkodó, aktívan fejlesztett és karbantartott szoftver projekteket 10+ éves librarykre. A dokumentáció szerint azonban (mármint a QueryDSL eredeti dokumentációja szerint), a kódgenerálás beköthető a Maven Compiler Plugin compile goaljába. Teljesen jól hangzik, elvileg működik is, kivéve, ha Lombok annotációk is jelen vannak. Erre a következő megoldásom született (amiért előre is elnézést kérek, nem a legszebb, de legalább működik):
- Először is maradtam a Spring Boot által hozott 5.1.0-s verziónál;
- Majd az APT Maven Plugintól végleg megváltam;
- Végüli a Maven Compiler Plugin alapú megoldásnál maradtam, de a compilation phaset két executionre bontva, amiben az első csak a metaosztályok generálásáért felel, míg a második a teljeskörű fordításért, beleértve például a Lombok annotációk kezelését is.
A tökéletes eredmény érdekében a QueryDSL APT libraryjét a Maven Compiler Plugin függéseként kell beállítanunk, majd létre kell hoznunk két executiont, mindkettőt a compile
goalra kötve, ám az elsőt a generate-sources
, míg a másodikat a compile
phaseben indítjuk. Az első executionben továbbá definiálni fogjuk a generáláshoz szükséges packageket mint annotation processor path-ok (ez a QueryDSL APT és a Spring Boot Starter Data MongoDB csomagok voltak ez esetemben, SQL adatbázisokhoz valószínűleg a Spring Boot Starter Data JPA kellene, de ezt nem mondom biztosra), majd kiválasztjuk az annotation processort magát (esetemben ez az org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
volt). Nagyon fontos továbbá, hogy a configuration szekció proc
kapcsolóját only
módra állítjuk, ezzel jelezve a compilernek hogy itt kizárólag annotáció feldolgozással (ez esetben effektíve kódgenerálással) akarunk foglalkozni, ne végezzen fordítást. A második execution configurationjében lényegében visszakapcsolunk mindent alapértelmezettre, tehát a proc
kapcsolót full
módra állítjuk, a parameters
kapcsolót true
-ra, illetve a generált források mappáját beállítjuk erre: target/generated-sources/annotations-default
. Ezután újra működni fog a QueryDSL Java 21 alatt, az erősen elavult APT plugin nélkül.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<!-- a QueryDSL APT plugint hozzáadjuk mint függés -->
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
</dependencies>
<executions>
<!-- első execution: csak annotáció feldolgozás, itt generáljuk a QueryDSL Q-classokat -->
<execution>
<id>run-annotation-processor</id>
<!-- forrás generálási fázishoz kötjük -->
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<!-- csak annotáció feldolgozás szeretnénk -->
<proc>only</proc>
<!-- itt mondjuk meg a Mavennek, hogy hol találja a szükséges annotation processort -->
<annotationProcessorPaths>
<path>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</path>
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</path>
</annotationProcessorPaths>
<annotationProcessors>
<processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
</annotationProcessors>
</configuration>
</execution>
<!-- második execution: teljes fordítás, immár a Q-clasokkal együtt -->
<execution>
<id>default-compile</id>
<!-- ahogy eredetileg is történne, ezt már a compile fázisban futtatjuk -->
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<!-- teljes annotáció feldolgozást vissza kell kapcsolnunk, pl a Lombok miatt -->
<proc>full</proc>
<parameters>true</parameters>
<generatedSourcesDirectory>target/generated-sources/annotations-default</generatedSourcesDirectory>
</configuration>
</execution>
</executions>
</plugin>
Komment írásához jelentkezz be
Bejelentkezés
Még senki nem szólt hozzá ehhez a bejegyzéshez.