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.

Informações da origem

Repositório
SAP-samples/btp-neo-java-app-migration
Última atividade na origem
7 de maio de 2026 às 07:30
Idioma detectado do SKILL.md
inglês
Estrelas
6
Forks
0

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
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:
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub