Skip to main content

dependency-compatibility

Invoke this skill to resolve third-party library compatibility issues during Neo to CF migration. Detects libraries that break on Java 25, Jakarta EE 10, or HANA Cloud — including schema migration tools (Liquibase, Flyway), DI frameworks (Guice, CDI), and other known problematic dependencies. Run after jakarta-java25-migration and sdk-replacement.

Informations de source

Dépôt
SAP-samples/btp-neo-java-app-migration
Dernière activité de la source
7 mai 2026 à 07:30
Langue détectée de SKILL.md
anglais
Étoiles
6
Forks
0

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
dependency-compatibility
description
Invoke this skill to resolve third-party library compatibility issues during Neo to CF migration. Detects libraries that break on Java 25, Jakarta EE 10, or HANA Cloud — including schema migration tools (Liquibase, Flyway), DI frameworks (Guice, CDI), and other known problematic dependencies. Run after jakarta-java25-migration and sdk-replacement.
disable-model-invocation
false
allowed-tools
Read, Edit, Write, Bash, Grep, Glob
# Third-Party Dependency Compatibility Resolve third-party library compatibility issues that arise during the Neo to Cloud Foundry migration. ## Purpose When migrating from Neo (Java 8, Java EE) to CF (Java 25, Jakarta EE 10, HANA Cloud), many third-party libraries break due to: - **Java 25 module system** — removed `javax.xml.bind`, `javax.xml.ws`, and other `javax.*` modules from the JDK - **javax → jakarta namespace** — libraries compiled against `javax.servlet`, `javax.ws.rs`, etc. won't link against Jakarta EE 10 - **Database changes** — schema migration tools may not recognize HANA Cloud - **DI framework conflicts** — listener ordering, JNDI assumptions, and initialization sequences break when the platform changes This skill scans the project's dependencies, identifies known compatibility issues, and applies targeted fixes. > **Note:** The `jakarta-java25-migration` skill handles the core javax→jakarta migration and Java 25 language upgrade. This skill handles **third-party library-specific** issues that the core migration doesn't cover. ## Detection This skill applies if any of these patterns are found: ### In pom.xml ```xml <!-- Schema migration tools --> <artifactId>liquibase-core</artifactId> <artifactId>flyway-core</artifactId> <!-- DI frameworks --> <artifactId>guice</artifactId> <artifactId>guice-servlet</artifactId> <artifactId>weld-servlet-core</artifactId> <!-- Known problematic libraries --> <artifactId>poi-ooxml</artifactId> <artifactId>itextpdf</artifactId> <artifactId>ehcache</artifactId> <artifactId>hazelcast</artifactId> <artifactId>quartz</artifactId> <artifactId>retrofit</artifactId> ``` ### In Java source files ```java // DI framework imports import com.google.inject.*; import com.google.inject.servlet.GuiceServletContextListener; // Liquibase programmatic usage import liquibase.Liquibase; import liquibase.integration.servlet.LiquibaseServletListener; // CDI annotations import javax.enterprise.context.*; import jakarta.enterprise.context.*; ``` ### In web.xml ```xml <!-- Liquibase listener --> <listener-class>liquibase.integration.servlet.LiquibaseServletListener</listener-class> <!-- Guice filter/listener --> <listener-class>com.google.inject.servlet.GuiceServletContextListener</listener-class> <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> ``` ## Prerequisites Before invoking this skill, ensure you have invoked: 1. **jakarta-java25-migration** - `Use the jakarta-java25-migration skill` - Java 25 and Jakarta EE 10 migration must be done first - REQUIRED before this skill 2. **sdk-replacement** - `Use the sdk-replacement skill` - SAP Cloud SDK setup must be done first - REQUIRED before this skill ## Transformation Steps ### Step 1: Schema Migration Tools (Conditional) > **This step is conditional.** Only apply if schema migration tools are detected. #### Detect ```bash # Liquibase find . -name "pom.xml" -not -path "*/target/*" -exec grep -l "liquibase" {} \; # Flyway find . -name "pom.xml" -not -path "*/target/*" -exec grep -l "flyway" {} \; ``` If either returns output, apply the relevant fix below. #### 1a: Liquibase — Upgrade to 4.x for Java 25 + HANA Cloud Liquibase 3.x has **two critical issues** on CF: 1. **JAXB dependency** — Liquibase 3.x internally uses `javax.xml.bind` for parsing XML changelogs. Java 25 removed `javax.xml.bind` from the JDK, causing: ``` NoClassDefFoundError: javax/xml/bind/annotation/XmlElement ``` 2. **Unknown database: HDB** — Liquibase 3.x doesn't recognize HANA Cloud's database identifier. It falls back to `UnsupportedDatabase`, which can fail on schema-specific operations. **Fix:** Upgrade Liquibase to 4.x and add the HANA extension. > **Note:** Check [Maven Central](https://mvnrepository.com/artifact/org.liquibase/liquibase-core) for the latest 4.x version at the time of migration. **Before:** ```xml <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>3.8.2</version> <!-- or any 3.x --> </dependency> <!-- Old HANA community extension (may be present or commented out) --> <dependency> <groupId>com.github.lbitonti</groupId> <artifactId>liquibase-hana</artifactId> <version>3.0</version> </dependency> ``` **After:** ```xml <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>4.30.0</version> </dependency> <!-- Official HANA extension for Liquibase 4.x --> <dependency> <groupId>org.liquibase.ext</groupId> <artifactId>liquibase-hanadb</artifactId> <version>4.30.0</version> </dependency> <!-- SLF4J bridge for Liquibase logging --> <dependency> <groupId>com.mattbertolini</groupId> <artifactId>liquibase-slf4j</artifactId> <version>5.1.0</version> </dependency> ``` > **Important:** Remove the old `com.github.lbitonti:liquibase-hana` dependency if present (even if commented out). It is incompatible with Liquibase 4.x. See the [Liquibase HANA Extension](https://github.com/liquibase/liquibase-hanadb) for details. #### 1b: Flyway — Upgrade for Jakarta EE 10 + HANA Cloud Flyway 9.x+ supports Jakarta EE and HANA Cloud natively. > **Note:** Flyway 10.x requires Java 17+. Check [Flyway docs](https://documentation.red-gate.com/fd/release-notes-for-flyway-engine-179732572.html) for the latest version. ```bash # Check current Flyway version find . -name "pom.xml" -not -path "*/target/*" -exec grep -A1 "flyway" {} \; ``` If Flyway version is < 9.0, upgrade: ```xml <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> <version>10.20.1</version> </dependency> <!-- For HANA support --> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-database-saphana</artifactId> <version>10.20.1</version> </dependency> ``` ### Step 2: DI Framework Integration (Conditional) > **This step is conditional.** Only apply if a DI framework is detected. #### Detect ```bash # Google Guice grep -r "com.google.inject\|GuiceServletContextListener\|GuiceFilter" --include="*.java" . find . -name "pom.xml" -not -path "*/target/*" -exec grep -l "guice" {} \; # CDI (Weld) grep -r "javax.enterprise.context\|jakarta.enterprise.context\|@RequestScoped\|@ApplicationScoped" --include="*.java" . find . -name "pom.xml" -not -path "*/target/*" -exec grep -l "weld" {} \; # HK2 find . -name "pom.xml" -not -path "*/target/*" -exec grep -l "hk2" {} \; ``` If any commands return output, check for the common issues below. #### 2a: Listener Ordering with Schema Migration Tools If the application uses **both** a DI framework **and** a schema migration tool (Liquibase, Flyway), listener ordering in `web.xml` becomes critical. **Problem:** Schema migration tools like Liquibase's `LiquibaseServletListener` perform their own JNDI lookup for the `DataSource`. This doesn't work when: - The `DataSource` is provided by a DI framework that must initialize first - The DI container manages database connections **The required initialization order in `web.xml` is:** ``` 1. DI Framework Listener → Initializes DI container, creates DataSource 2. Schema Migration Listener → Gets DataSource from DI, runs migrations 3. Application Listener → Application starts with migrated schema ``` **Solution:** Replace Liquibase's built-in `LiquibaseServletListener` (or Flyway's equivalent) with a custom `ServletContextListener` that retrieves the `DataSource` from your DI container. **web.xml listener ordering:** ```xml <!-- Order matters! DI must initialize before schema migration --> <listener> <!-- 1. DI framework initializes first --> <listener-class>com.example.app.GuiceContextListener</listener-class> </listener> <listener> <!-- 2. Schema migration runs after DI provides the DataSource --> <listener-class>com.example.app.CFLiquibaseRunner</listener-class> </listener> <listener> <!-- 3. Application initializes after schema is ready --> <listener-class>com.example.app.AppInitializer</listener-class> </listener> ``` **Custom migration runner template (adapt to your DI framework):** ```java import jakarta.servlet.ServletContextEvent; import jakarta.servlet.ServletContextListener; import javax.sql.DataSource; import liquibase.Liquibase; import liquibase.database.Database; import liquibase.database.DatabaseFactory; import liquibase.database.jvm.JdbcConnection; import liquibase.resource.ClassLoaderResourceAccessor; import java.sql.Connection; /** * Custom Liquibase runner that retrieves the DataSource from the DI container * instead of performing a direct JNDI lookup. * * ADAPT: Replace getDataSourceFromDI() with your DI framework's lookup method. */ public class CFLiquibaseRunner implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { try { // ADAPT: Get DataSource from your DI framework // For Guice: Injector injector = (Injector) sce.getServletContext().getAttribute(Injector.class.getName()); // DataSource ds = injector.getInstance(DataSource.class); // For CDI: DataSource ds = CDI.current().select(DataSource.class).get(); DataSource dataSource = getDataSourceFromDI(sce); try (Connection conn = dataSource.getConnection()) { Database database = DatabaseFactory.getInstance() .findCorrectDatabaseImplementation(new JdbcConnection(conn)); try (Liquibase liquibase = new Liquibase( "db/changelog/db.changelog-master.xml", new ClassLoaderResourceAccessor(), database)) { liquibase.update(""); } } } catch (Exception e) { throw new RuntimeException("Liquibase migration failed", e); } } private DataSource getDataSourceFromDI(ServletContextEvent sce) { // TODO: Implement based on your DI framework throw new UnsupportedOperationException("Adapt this method to your DI framework"); } @Override public void contextDestroyed(ServletContextEvent sce) { // no-op } } ``` > **Note:** This is a template — you must adapt `getDataSourceFromDI()` to your specific DI framework. The key principle is: let the DI container manage the DataSource, and have the migration runner retrieve it from the container rather than doing its own JNDI lookup. #### 2b: Jersey + CDI (Weld) on Tomcat — Missing Bean Discovery When using **Jersey** with **CDI (Weld)** on **Tomcat** (not TomEE), the `jersey-cdi2-se` module bootstraps Weld in SE (standalone) mode. Weld SE scans for `META-INF/beans.xml` inside classpath entries to discover bean archives. However, a WAR's standard CDI descriptor at `WEB-INF/beans.xml` is **not** recognized by Weld SE — only by Weld Servlet. **Symptom:** All `@Inject` points fail at deployment with: ``` WELD-001408: Unsatisfied dependencies for type UserDAO with qualifiers @Default WELD-001408: Unsatisfied dependencies for type Notifier with qualifiers @Default ... ``` The errors appear for **every** injected bean even though `WEB-INF/beans.xml` exists with `bean-discovery-mode="all"`. **Detection:** ```bash # Check if using jersey-cdi2-se with Weld on Tomcat grep -l "jersey-cdi2-se" pom.xml grep -l "weld-servlet" pom.xml grep -l "cf-tomcat-bom" pom.xml # Check if META-INF/beans.xml exists in resources ls src/main/resources/META-INF/beans.xml 2>/dev/null ``` If all three dependencies are present AND `src/main/resources/META-INF/beans.xml` does NOT exist, apply this fix. **Fix:** Add a `beans.xml` to `src/main/resources/META-INF/` so it is packaged as `WEB-INF/classes/META-INF/beans.xml` in the WAR. This makes Weld SE treat the classes directory as a bean archive: ```bash mkdir -p src/main/resources/META-INF ``` Create `src/main/resources/META-INF/beans.xml`: ```xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd" bean-discovery-mode="all" version="4.0"> </beans> ``` > **Note:** Keep the existing `WEB-INF/beans.xml` as well — it is still needed for Weld Servlet mode. The WAR should contain BOTH `WEB-INF/beans.xml` and `WEB-INF/classes/META-INF/beans.xml`. This issue does NOT affect TomEE-based applications because TomEE provides its own CDI container (OpenWebBeans) and does not use `jersey-cdi2-se`. #### 2c: Jersey + CDI (Weld) on Tomcat — Ambiguous HttpServletRequest After fixing the bean discovery issue (Step 2b), a second deployment error can occur: `WELD-001409: Ambiguous dependencies` for `HttpServletRequest`. With `bean-discovery-mode="all"`, Weld SE discovers multiple providers for `HttpServletRequest` — typically two Jersey `SupplierBeanBridge` instances and one Weld built-in bean. **Symptom:** ``` WELD-001409: Ambiguous dependencies for type HttpServletRequest with qualifiers @Default at injection point [BackedAnnotatedField] @Inject private com.example.filter.MyFilter.request Possible dependencies:
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub