Jednou za čas dostanu uklízecí mánii. Tentokrát mě k tomu dokopal aplikáč, kde nefungovalo něco, co v pohodě běželo na servlet containeru. Odpustím si plivání síry, protože pořádek v tom úplně nebyl. Problém měl dvě části. Kdysi už jsem psal o tom, že věci jako servlet API do waru nepatří. To je sice poměrně jasné, ale i tak se člověk dokáže nachytat. Pak je tu trochu větší past a to, že Java EE (aka javax) je mrtvá, nově už jako Jakarta EE.

Úvod

Doporučuji vaší pozornosti článek Transition from Java EE to Jakarta EE, ale abych to trochu předžvýkal. Java EE jako například javax.servlet-api byla v Oracle repozitářích. Kód se přesunul do open source. Zůstal java package name (v prvních verzí, později se rovněž mění), ale změnil se maven group ID z javax.* na jakarta.*. To sice dává jasně najevo rozdíl, ale zároveň to umožňuje používat oba artefakty současně. Navíc, a to je horší, to umožňuje mít závislosti odlišných verzí. Používáte-li například Spring Boot BoM, tak ten definuje obě sady artefaktů, ale co se týče verzí, tak vám alespoň napovídá.

Následuje ukázka rozdílu v definici maven závislosti servlet-api.

Javax

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>${servlet-api.version}</version>
</dependency>

Jakarta

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>${jakarta-servlet.version}</version>
</dependency>

Cíl

Chceme se tedy zbavit všech závislostí javax.*. Včetně com.sun.mail a com.sun.xml.bind. K javax.cache jsem nenašel jakarta alternativu. Přibalíte (maven scope compile) jen ty závislosti, které jsou nutné. Podle toho, kam nasazujete. Třeba servlet-api nepatří ani na servlet container.

Pro nižší verze jakarta artefaktů nemusíte měnit java importy. Tedy že budete stále používat javax.servlet.http.HttpServletRequest a teprve později přejdete na jakarta.servlet.http.HttpServletRequest.

Bezpečnostní pojistky

Ani sebelepší code review nezaručí, že vám pořádek vydrží. Můžete si tam knihovny zavést i neúmyslně přes tranzitivní závislosti. Pojistkou může být šikovně nastavený maven enforcer plugin. Konkrétně konfigurace zakázaných závislostí.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>${maven-enforcer-plugin.version}</version>
    <executions>
        <execution>
            <id>enforce-banned-dependencies</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <bannedDependencies>
                        <excludes>
                            <!-- Force switching to Jakarta EE -->
                            <exclude>javax.*</exclude>
                            <!-- already on application server or servlet container -->
                            <exclude>jakarta.servlet:jakarta.servlet-api:*</exclude>
                            <exclude>jakarta.servlet.jsp:jakarta.servlet.jsp-api:*</exclude>
                            <!-- replaced by jakarta -->
                            <exclude>com.sun.mail</exclude>
                            <exclude>com.sun.xml.bind</exclude>
                        </excludes>
                        <includes>
                            <!-- Jakarta API are allowed to be provided -->
                            <include>jakarta.*:*:jar:*:provided</include>
                            <!-- Not yet migrated to Jakarta -->
                            <include>javax.cache:*</include>
                        </includes>
                    </bannedDependencies>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

Závěr

Java EE aka javax je mrtvá, ať žije Jakarta. Je nebezpečné mít obě závislosti současně, zejména s ohledem na možnou rozdílnost verzí. Ukázali jsme si, jak můžete nakonfigurovat maven plugin, který vám závislosti bude hlídat.

Související