Replaces Neo JNDI lookups for ConnectivityConfiguration and DestinationConfiguration with SAP Cloud SDK DestinationAccessor in Java code and web.xml for Cloud Foundry migration.
npx claudepluginhub sap-samples/btp-neo-java-app-migration --plugin sap-btp-neo-migrationThis skill is limited to using the following tools:
Configure the Destination service for outbound HTTP connections.
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.
Configure the Destination service for outbound HTTP connections.
Replace Neo's ConnectivityConfiguration and DestinationConfiguration JNDI lookups with SAP Cloud SDK's DestinationAccessor API for managing outbound connections.
This skill applies if any of these patterns are found:
<resource-ref>
<res-ref-name>connectivityConfiguration</res-ref-name>
<res-type>com.sap.core.connectivity.api.configuration.ConnectivityConfiguration</res-type>
</resource-ref>
import com.sap.core.connectivity.api.configuration.ConnectivityConfiguration;
import com.sap.core.connectivity.api.configuration.DestinationConfiguration;
// JNDI lookup pattern
Context ctx = new InitialContext();
ConnectivityConfiguration config =
(ConnectivityConfiguration) ctx.lookup("java:comp/env/connectivityConfiguration");
DestinationConfiguration destConfig = config.getConfiguration("my-destination");
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 sdk-replacement skill
Remove these from web.xml:
<resource-ref>
<res-ref-name>connectivityConfiguration</res-ref-name>
<res-type>com.sap.core.connectivity.api.configuration.ConnectivityConfiguration</res-type>
</resource-ref>
Also remove AuthenticationHeaderProvider if present:
<resource-ref>
<res-ref-name>authenticationHeaderProvider</res-ref-name>
<res-type>com.sap.core.connectivity.api.authentication.AuthenticationHeaderProvider</res-type>
</resource-ref>
Note: The SAP Cloud SDK handles authentication automatically - no manual header management needed.
Before:
import javax.naming.Context;
import javax.naming.InitialContext;
import com.sap.core.connectivity.api.configuration.ConnectivityConfiguration;
import com.sap.core.connectivity.api.configuration.DestinationConfiguration;
After:
import com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor;
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;
import com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationNotFoundException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.HttpResponse;
import static com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor.getHttpClient;
Before (Neo):
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String destinationName = "my-destination";
try {
// JNDI lookup for connectivity configuration
Context ctx = new InitialContext();
ConnectivityConfiguration configuration =
(ConnectivityConfiguration) ctx.lookup("java:comp/env/connectivityConfiguration");
// Get destination configuration
DestinationConfiguration destConfiguration =
configuration.getConfiguration(destinationName);
if (destConfiguration == null) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Destination not found: " + destinationName);
return;
}
// Get URL from destination
String url = destConfiguration.getProperty("URL");
URL targetUrl = new URL(url);
// Get proxy settings
String proxyType = destConfiguration.getProperty("ProxyType");
Proxy proxy = getProxy(proxyType);
// Open connection with proxy
HttpURLConnection urlConnection = (HttpURLConnection) targetUrl.openConnection(proxy);
// Copy response
InputStream instream = urlConnection.getInputStream();
// ... handle response
} catch (NamingException e) {
throw new ServletException(e);
}
}
After (Cloud Foundry):
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String destinationName = "my-destination";
try {
// Get destination using SAP Cloud SDK
HttpDestination destination;
try {
destination = DestinationAccessor.getDestination(destinationName).asHttp();
} catch (DestinationNotFoundException e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Destination not found: " + destinationName);
return;
}
// Get HTTP client configured for the destination
// Automatically handles proxy, authentication, etc.
HttpClient httpClient = getHttpClient(destination);
// Make request
HttpGet httpGet = new HttpGet(destination.getUri());
HttpResponse destinationResponse = httpClient.execute(httpGet);
// Check status
int statusCode = destinationResponse.getStatusLine().getStatusCode();
if (statusCode != HttpServletResponse.SC_OK) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Destination returned: " + statusCode);
return;
}
// Write response
destinationResponse.getEntity().writeTo(response.getOutputStream());
} catch (Exception e) {
throw new ServletException("Connectivity failed: " + e.getMessage(), e);
}
}
If you need to access destination properties directly:
Before (Neo):
DestinationConfiguration destConfig = config.getConfiguration(destinationName);
String url = destConfig.getProperty("URL");
String user = destConfig.getProperty("User");
String proxyType = destConfig.getProperty("ProxyType");
After (Cloud Foundry):
import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
import com.sap.cloud.sdk.cloudplatform.connectivity.DestinationProperty;
Destination destination = DestinationAccessor.getDestination(destinationName);
// Get URI
URI uri = destination.asHttp().getUri();
// Get custom properties
Optional<String> customProperty = destination.get("customProperty");
// Check proxy type
ProxyType proxyType = destination.asHttp().getProxyType();
boolean isOnPremise = proxyType == ProxyType.ON_PREMISE;
Add destination service to mtad.yaml:
modules:
- name: ${app-name}
type: java.tomcat
path: target/${app-name}.war
parameters:
buildpack: sap_java_buildpack_jakarta
disk-quota: 512MB
memory: 512MB
properties:
ENABLE_SECURITY_JAVA_API_V2: true
SET_LOGGING_LEVEL: 'ROOT: INFO'
requires:
- name: ${app-name}-destination
resources:
- name: ${app-name}-destination
type: org.cloudfoundry.managed-service
parameters:
service: destination
service-plan: lite
Create destinations via BTP Cockpit or programmatically:
my-destinationhttps://api.example.com# Get access token
TOKEN=$(cf oauth-token | sed 's/bearer //')
# Create destination
curl -X POST \
"https://destination-configuration.cfapps.${region}.hana.ondemand.com/destination-configuration/v1/subaccountDestinations" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"Name": "my-destination",
"Type": "HTTP",
"URL": "https://api.example.com",
"ProxyType": "Internet",
"Authentication": "NoAuthentication"
}'
No new configuration files in the application. Destinations are managed in BTP Cockpit.
| Service | Plan | Purpose |
|---|---|---|
destination | lite | Destination configuration service |
mvn clean compile
Add a test endpoint:
@WebServlet("/test/destination")
public class DestinationTestServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String destName = req.getParameter("name");
try {
HttpDestination dest = DestinationAccessor.getDestination(destName).asHttp();
resp.getWriter().println("Destination found: " + dest.getUri());
} catch (DestinationNotFoundException e) {
resp.sendError(404, "Destination not found: " + destName);
}
}
}
mvn clean package
cf deploy . -f
# Test
curl "https://${app-url}/test/destination?name=my-destination"
Cause: Destination not created or name mismatch. Solution:
Cause: Authentication configuration issue. Solution: Check destination authentication settings and credentials.
Cause: Network or firewall issue. Solution:
// Get destination by name
Destination dest = DestinationAccessor.getDestination("name");
// Get as HTTP destination
HttpDestination httpDest = dest.asHttp();
// Try to get destination (returns Optional)
Option<Destination> maybeDest = DestinationAccessor.tryGetDestination("name");
// Get URI
URI uri = httpDest.getUri();
// Get proxy type
ProxyType proxyType = httpDest.getProxyType();
// Get headers
Collection<Header> headers = httpDest.getHeaders();
// Get HTTP client for destination
HttpClient client = HttpClientAccessor.getHttpClient(httpDest);
// Execute request
HttpResponse response = client.execute(new HttpGet(httpDest.getUri()));
After completing this skill, proceed to: