Replaces Neo Java Web API (neo-java-web-api, scp-neo deps in pom.xml; com.sap.cloud.* imports) with SAP Cloud SDK for Cloud Foundry compatibility. Invoke after jakarta-java25-migration.
npx claudepluginhub sap-samples/btp-neo-java-app-migration --plugin sap-btp-neo-migrationThis skill is limited to using the following tools:
Replace the Neo-specific Java Web API with SAP Cloud SDK for Cloud Foundry compatibility.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Processes PDFs: extracts text/tables/images, merges/splits/rotates pages, adds watermarks, creates/fills forms, encrypts/decrypts, OCRs scans. Activates on PDF mentions or output requests.
Share bugs, ideas, or general feedback.
Replace the Neo-specific Java Web API with SAP Cloud SDK for Cloud Foundry compatibility.
The Neo Java Web API (com.sap.cloud:neo-java-web-api) is not available in Cloud Foundry. This skill replaces it with SAP Cloud SDK dependencies that provide equivalent functionality for the CF environment.
This skill applies if any of these patterns are found:
<dependency>
<groupId>com.sap.cloud</groupId>
<artifactId>neo-java-web-api</artifactId>
</dependency>
<!-- OR -->
<dependency>
<groupId>com.sap.cloud.sdk.cloudplatform</groupId>
<artifactId>scp-neo</artifactId>
</dependency>
import com.sap.cloud.account.*;
import com.sap.core.connectivity.api.*;
import com.sap.security.um.user.*;
Working directory: This skill must run inside the
-cf-migrationcopy of your app, created byjakarta-java25-migrationorneo-to-cf-migration-orchestrator. If your current directory does not end in-cf-migration, switch to it before proceeding.
Before invoking this skill, ensure you have invoked:
Use the jakarta-java25-migration skill
Remove from pom.xml:
<!-- REMOVE this dependency -->
<dependency>
<groupId>com.sap.cloud</groupId>
<artifactId>neo-java-web-api</artifactId>
<version>${neo.version}</version>
<scope>provided</scope>
</dependency>
<!-- ALSO REMOVE if present -->
<dependency>
<groupId>com.sap.cloud.sdk.cloudplatform</groupId>
<artifactId>scp-neo</artifactId>
<version>${sdk.version}</version>
</dependency>
Add to <dependencyManagement> section:
<dependencyManagement>
<dependencies>
<!-- CF Tomcat BOM - provides servlet container and runtime -->
<dependency>
<groupId>com.sap.cloud.sjb.cf</groupId>
<artifactId>cf-tomcat-bom</artifactId>
<version>${cf-tomcat-bom-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SAP Cloud SDK BOM - provides SDK modules -->
<dependency>
<groupId>com.sap.cloud.sdk</groupId>
<artifactId>sdk-modules-bom</artifactId>
<version>${sdk-modules-bom-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Add to <properties> section:
<properties>
<!-- Latest stable versions as of 2025 -->
<cf-tomcat-bom-version>2.22.0</cf-tomcat-bom-version>
<sdk-modules-bom-version>5.14.0</sdk-modules-bom-version>
</properties>
Note: Check for latest versions at:
Add to <dependencies> section:
<dependencies>
<!-- SAP Cloud SDK for Cloud Foundry -->
<dependency>
<groupId>com.sap.cloud.sdk.cloudplatform</groupId>
<artifactId>scp-cf</artifactId>
</dependency>
<!-- SAP Cloud Security Java API (required for XSUAA integration) -->
<dependency>
<groupId>com.sap.cloud.security</groupId>
<artifactId>java-api</artifactId>
</dependency>
<!-- Servlet API (provided by buildpack) -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
</dependencies>
Note: The
jakarta.servlet-apidoes not need an explicit<scope>provided</scope>as this is inherited from the BOM.
Depending on what Neo APIs you were using, add these dependencies:
<!-- If using OpenCMIS (Document Management) -->
<dependency>
<groupId>org.apache.chemistry.opencmis</groupId>
<artifactId>chemistry-opencmis-client-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.chemistry.opencmis</groupId>
<artifactId>chemistry-opencmis-client-api</artifactId>
</dependency>
<!-- If using Mail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
</dependency>
<!-- If using JSP -->
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- If using EL -->
<dependency>
<groupId>jakarta.el</groupId>
<artifactId>jakarta.el-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- If using WebSocket -->
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
<scope>provided</scope>
</dependency>
In Neo, the platform-provided com.sap.ui5.resource.ResourceServlet served SAPUI5 libraries at /resources/*. This servlet class does not exist in Cloud Foundry. If HTML files reference SAPUI5 via a relative resources/sap-ui-core.js path, the page will load but render blank because the UI5 library returns 404.
# Check for ResourceServlet in web.xml
grep -r "ResourceServlet\|com.sap.ui5.resource" --include="*.xml" src/main/webapp/
# Check for relative SAPUI5 loading in HTML files
grep -r 'src="resources/sap-ui-core.js"' --include="*.html" src/main/webapp/
If either returns results, apply the fixes below.
Remove the servlet declaration and mapping:
<!-- REMOVE: Neo-specific SAPUI5 resource servlet -->
<servlet>
<servlet-name>ResourceServlet</servlet-name>
<servlet-class>com.sap.ui5.resource.ResourceServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ResourceServlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
Replace the relative path with the SAPUI5 CDN URL in all HTML files.
CRITICAL: The old CDN domain
sapui5.hana.ondemand.comno longer serves older SAPUI5 versions (pre-1.71) and may be fully retired. Always use the current CDN domainui5.sap.com.
Before:
<script id="sap-ui-bootstrap" type="text/javascript"
src="resources/sap-ui-core.js"
...></script>
After:
<script id="sap-ui-bootstrap" type="text/javascript"
src="https://ui5.sap.com/resources/sap-ui-core.js"
...></script>
Bulk fix (relative paths):
grep -rl 'src="resources/sap-ui-core.js"' --include="*.html" src/main/webapp/ | \
xargs sed -i 's|src="resources/sap-ui-core.js"|src="https://ui5.sap.com/resources/sap-ui-core.js"|g'
Bulk fix (old CDN domain):
grep -rl 'sapui5.hana.ondemand.com' --include="*.html" src/main/webapp/ | \
xargs sed -i 's|sapui5.hana.ondemand.com|ui5.sap.com|g'
Note: If the application requires a specific SAPUI5 version, pin it in the URL:
https://ui5.sap.com/1.120.0/resources/sap-ui-core.js. Older versions (pre-1.71) are no longer available on the CDN — if the app pins an old version, update to a supported LTS version (e.g., 1.108.x or 1.120.x).
The sap_bluecrystal theme was removed in SAPUI5 1.40+. If your application references it, it will fail to load the theme CSS, causing either a broken layout or a blank page.
Detect:
grep -r "sap_bluecrystal" --include="*.html" --include="*.json" src/main/webapp/
Fix: Replace with sap_fiori_3 (Quartz Light) or sap_horizon (latest):
# Update in HTML files
grep -rl "sap_bluecrystal" --include="*.html" src/main/webapp/ | \
xargs sed -i 's|sap_bluecrystal|sap_fiori_3|g'
# Update in manifest.json
grep -rl "sap_bluecrystal" --include="*.json" src/main/webapp/ | \
xargs sed -i 's|sap_bluecrystal|sap_fiori_3|g'
| Removed Theme | Replacement |
|---|---|
sap_bluecrystal | sap_fiori_3 or sap_horizon |
sap_belize | sap_fiori_3 or sap_horizon |
If the Neo web.xml had <servlet-mapping> entries (e.g., for CXF/JAX-RS servlets), ensure they are preserved in the CF web.xml. A common oversight is copying the <servlet> declaration without its <servlet-mapping>, which causes REST APIs to return 404.
Detect:
# Check if web.xml has servlet declarations without corresponding mappings
grep "<servlet-name>" src/main/webapp/WEB-INF/web.xml
For each <servlet-name>, verify a corresponding <servlet-mapping> exists. For JAX-RS applications using CXF:
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Note: If the JAX-RS Application class has
@ApplicationPath("/rest")and you are using TomEE, auto-discovery may work without an explicit mapping. However, ifCXFNonSpringJaxrsServletis explicitly declared in web.xml, the<servlet-mapping>is required — the explicit declaration overrides auto-discovery.
Warning (TomEE only): If the application uses TomEE (EJB support),
CXFNonSpringJaxrsServletmust be removed entirely fromweb.xml— not just have its mapping added. This servlet bypasses TomEE's CDI container, causing@Injectand@EJBfields in JAX-RS endpoints to remainnull(NullPointerExceptionat runtime). See the tomee-runtime skill, Step 6 for details.
Replace Neo-specific imports with SAP Cloud SDK equivalents:
| Neo Import | SAP Cloud SDK Import |
|---|---|
com.sap.core.connectivity.api.configuration.DestinationConfiguration | com.sap.cloud.sdk.cloudplatform.connectivity.Destination |
com.sap.core.connectivity.api.configuration.ConnectivityConfiguration | com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor |
com.sap.cloud.account.TenantContext | com.sap.cloud.sdk.cloudplatform.tenant.TenantAccessor |
com.sap.security.um.user.UserProvider | Via XSUAA token (see authentication skill) |
See assets/pom-cf-tomcat.xml for a complete template.
No new configuration files required for this skill alone. The MTA descriptor will be created after all skills are applied.
No CF services required for this skill alone. Services are defined by feature-specific skills.
mvn clean compile
mvn dependency:tree | grep -E "scp-cf|cf-tomcat-bom|sdk-modules-bom"
Expected output should show the new SDK dependencies.
grep -rh "com.sap.cloud.account\|com.sap.core.connectivity\|com.sap.security.um" src/main/java/
Should return results that need to be replaced with SDK equivalents.
Cause: BOM import not set up correctly.
Solution: Ensure <dependencyManagement> section includes both BOMs with <type>pom</type> and <scope>import</scope>.
Solution: Use mvn dependency:tree to identify conflicts, then add exclusions as needed.
Cause: Dependency scope issue.
Solution: Verify jakarta.servlet-api has <scope>provided</scope> (it's provided by the buildpack).
Cause: Three common causes, all resulting in the UI5 framework failing to load (the HTML page returns 200 but the <div> stays empty):
com.sap.ui5.resource.ResourceServlet served SAPUI5 at /resources/*. This servlet doesn't exist in CF. HTML files loading src="resources/sap-ui-core.js" get a 404.sapui5.hana.ondemand.com no longer serves older SAPUI5 versions — pinned versions like 1.38.x return 404.sap_bluecrystal theme was removed in SAPUI5 1.40+ — if referenced, the theme CSS fails to load.Diagnosis: Open browser developer tools (F12 → Network tab). Look for 404 responses on sap-ui-core.js or theme CSS files.
Solution: See Step 6 above. Update HTML files to use the current CDN domain ui5.sap.com, pin a supported SAPUI5 version (1.108.x or 1.120.x), replace sap_bluecrystal with sap_fiori_3, and remove the ResourceServlet declaration from web.xml.
Cause: The CXF/JAX-RS servlet was declared in web.xml but the <servlet-mapping> was missing. Without a mapping, the servlet is registered but unreachable.
Solution: See Step 7 above. Add a <servlet-mapping> for the servlet (e.g., <url-pattern>/rest/*</url-pattern>).
After completing this skill, proceed to applicable scenario skills: