{"id":20484561,"url":"https://github.com/sap-samples/btp-neo-java-app-migration","last_synced_at":"2025-04-13T14:52:14.983Z","repository":{"id":235199718,"uuid":"787800862","full_name":"SAP-samples/btp-neo-java-app-migration","owner":"SAP-samples","description":"Code sample and documentation for migrating SAP BTP Java applications from NEO to Cloud Foundry, showcasing step-by-step processes and best practices.","archived":false,"fork":false,"pushed_at":"2024-07-23T07:46:37.000Z","size":4863,"stargazers_count":3,"open_issues_count":3,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-07-23T09:40:13.877Z","etag":null,"topics":["btp-cloud-foundry","btp-neo","connectivity","destinations","document-serivce","hana-cloud","xsuaa"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SAP-samples.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-17T07:56:50.000Z","updated_at":"2024-07-23T07:46:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"e682d0ac-6e55-4f4c-9666-97cec58cacd0","html_url":"https://github.com/SAP-samples/btp-neo-java-app-migration","commit_stats":null,"previous_names":["sap-samples/btp-java-migration-procedure-united"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SAP-samples%2Fbtp-neo-java-app-migration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SAP-samples%2Fbtp-neo-java-app-migration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SAP-samples%2Fbtp-neo-java-app-migration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SAP-samples%2Fbtp-neo-java-app-migration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SAP-samples","download_url":"https://codeload.github.com/SAP-samples/btp-neo-java-app-migration/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224809250,"owners_count":17373589,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["btp-cloud-foundry","btp-neo","connectivity","destinations","document-serivce","hana-cloud","xsuaa"],"created_at":"2024-11-15T16:23:59.024Z","updated_at":"2025-04-13T14:52:14.973Z","avatar_url":"https://github.com/SAP-samples.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![REUSE status](https://api.reuse.software/badge/github.com/SAP-samples/btp-neo-java-app-migration)](https://api.reuse.software/info/github.com/SAP-samples/btp-neo-java-app-migration)\n\n\n\n## Java Migration Guide Neo to CF\n\n### Contents\n1. [Description](#description)\n2. [Requirements](#requirements)\n3. [Scenario](#scenario)\n4. [Project Structure](#project-structure)\n5. [SAP BTP Neo Deployment](#sap-btp-neo-deployment)\n6. [Migration](#migration)\n7. [Step 1. Neo Java Web API to SAP Cloud SDK](#step-1-neo-java-web-api-to-sap-cloud-sdk)\n8. [Step 2. Approuter](#step-2-approuter)\n9. [Step 3. Authentication and authorization](#step-3-authentication-and-authorization)\n10. [Step 4. Destinations](#step-4-destinations)\n11. [Step 5. Connectivity](#step-5-connectivity)\n12. [Step 6. Document Management Service (ECM)](#step-6-document-management-service)\n13. [Step 7. Database](#step-7-database)\n14. [Step 8. Setup destination from application1 to applicaion2](#step-8-setup-destination-from-application1-to-application2)\n14. [Step 9. SAP BTP CF Deployment](#step-9-sap-btp-cf-deployment)\n15. [Final Configuration](#final-configuration)\n\n### Description\nThis is a simple example of a Java project that can be used as a supporting resource for understanding Java applications' migration from SAP BTP Neo to SAP BTP Cloud Foundry.\n\n### Requirements\nYou have to install the following tools to be able to perform the steps described in this document:\n1. SAP JVM 8: [installation](https://help.sap.com/docs/btp/sap-btp-neo-environment/optional-install-sap-jvm)\n2. Maven: [installation](https://maven.apache.org/install.html)\n3. CF CLI: [installation](https://docs.cloudfoundry.org/cf-cli/install-go-cli.html)\n4. MultiApps CloudFoundry CLI Plugin: [installation](https://developers.sap.com/tutorials/cp-cf-install-cliplugin-mta.html)\n5. Install [Cloud MTA Build Tool(MBT)](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-developer-guide-for-cloud-foundry-multitarget-applications-sap-business-app-studio/cloud-mta-build-tool-mbt)\n6. IDE of your choice (for example, IntelliJ IDEA, Eclipse)\n7. SAP BTP Neo subaccount (with created SAP Hana database)\n8. SAP BTP Cloud Foundry subaccount (with created SAP Hana database)\n9. (Optional) Local tomcat 8.5.X to run OnPremise application: [installation](https://tomcat.apache.org/download-80.cgi)\n10. (Optional) Sap Cloud Connector: [installation](https://tools.hana.ondemand.com/#cloud)\n11. Node.js and npm. Please refer to the official [documentation](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) to check the installation process.\n\n### Scenario\n![scenario-diagram](./images/scenario.png \"Scenario diagram\")\n\nThe first app manages Personnel entities in the HANA database. The second app stores files in the document service and provides a REST API for managing files and a user interface.\u003cbr\u003e\n\nThe first app has a UI that creates a person with a first name, second name, and a photo. To store the photo, the first app uses a REST API of the second app to store the person's photo as a document. For that purpose, there must be \"trust\" between the two apps.\u003cbr\u003e\n\nEach app should be able to work alone - i.e. even if the document storage app is not there, the person app should be able to store a person without a photo, and the document app should be able to work alone.\u003cbr\u003e\n\n### Project Structure\n**scenario/**\u003cbr\u003e\n|--**on-premise-demo** - sources of OnPremise demo application\u003cbr\u003e\n|--**neo/**\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**application1/** - sources of Java app 1 for SAP BTP Neo\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- ...\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**application2/** - sources of Java app 2 for SAP BTP Neo\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- ...\u003cbr\u003e\n|--**cf/**\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**cf-application1/** - sources of migrated Java app 1 for SAP BTP CloudFoundry\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**approuter/** - sources of approuter application\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**xs-app.json** - approuter configuration\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**mta.yaml** - deployment descriptor\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**xs-security.json** - security descriptor\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- ...\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**cf-application2/** - sources of migrated Java app 2 for SAP BTP CloudFoundry\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**approuter/** - sources of approuter application\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**xs-app.json** - approuter configuration\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**mta.yaml** - deployment descriptor\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|--**xs-security.json** - security descriptor\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- ...\u003cbr\u003e\n\n## SAP BTP Neo Deployment\n\n### Option 1. Via SAP BTP Cockpit\n\nTo build and deploy this scenario in SAP BTP Neo, you need to do following:\n\n1. Clone/download this repository.\u003cbr\u003e\n2. Go to the `scenario/neo` directory.\u003cbr\u003e\n3. Go to `application1` and execute the `mvn clean package` command from the terminal. Repeat the steps for `application2`.\n\n4. Go to the SAP BTP Neo subaccount -\u003e Java Applications. Choose `Deploy Application` and provide the location of the `*.war` file for each application.\n\n![neo-deployment](./images/neo-deployment.png \"SAP BTP Neo deployment\")\n\n5. Choose `Deploy`.\n\n\u003e Note: please do not start the applications yet.\n\n### Option 2. Via Neo CLI\n\n1. Clone/download this repository.\u003cbr\u003e\n2. Go to the `scenario/neo` directory.\u003cbr\u003e\n3. Go to `application1` and execute the `mvn clean package` command from terminal. Repeat the steps for `application2`.\n\n\u003e Note: Install Neo CLI if not installed yet. [Installation](https://help.sap.com/docs/btp/sap-btp-neo-environment/install-sap-btp-sdk-for-neo-environment?locale=en-US)\n\n4. Execute the following command for `application1` and `application2`:\u003cbr\u003e\n```shell\nneo.sh deploy --account \u003csubaccount technical name\u003e --application \u003capplication name\u003e --source \u003cpath to war file\u003e --user \u003cuser name or email\u003e --host \u003chost\u003e\n```\n\n\u003e Note: Neo CLI provides `neo.sh` and `neo.bat` for UNIX systems and Windows respectively. You can find them in `\u003cNeo CLI directory\u003e/tools`.\u003cbr\u003e\n\u003e\n\u003e Note: See [here](https://help.sap.com/docs/btp/sap-btp-neo-environment/regions-and-hosts-available-for-neo-environment) for the host for the subaccount\u003cbr\u003e\n\u003e\n\u003e Note: Get the subaccount technical name from the SAP BTP Neo subaccount overview page:\u003cbr\u003e\n\u003e ![subaccount-technical-name](./images/subaccount-technical-name.png \"Subaccount technical name\")\n\n\nUseful links:\n- [Using Neo CLI](https://help.sap.com/docs/btp/sap-btp-neo-environment/using-console-client)\n\n#### SAP BTP Neo applications configuration\n\nGo the SAP Hana Workbench and create a new user for the data source binding:\n1. Go to `SAP HANA/SAP ASE`, choose `Databases \u0026 Schemas` and click on the database you have:\u003cbr\u003e![hana-workbench-1](./images/hana-workbench-1.png)\u003cbr\u003e\n2. Click `SAP HANA Web-Based Development Workbench`:\u003cbr\u003e![hana-workbench-2](./images/hana-workbench-2.png)\u003cbr\u003e\n3. Click on the `Catalog` tile.\n4. Open a new SQL console and create a new user by executing the following SQL statement:\n```sql\nCREATE USER \u003cusername\u003e PASSWORD \u003cpassword\u003e NO FORCE_FIRST_PASSWORD_CHANGE;\n```\nExample:\u003cbr\u003e![create-database-user](./images/create-database-user.png \"Create database user\")\n\n5. Go to the deployed **application1**.\n\n6. Open the `Configuration` tab -\u003e `Data Source Bindings` and provide the required details:\n   - Data Source field: `jdbc/application1`\n   - DB/Schema ID\n   - Database User and password (the newly created user credentials).\n\n7. Choose `Create`.\n\n![create-datasource-2](./images/create-datasource-2.png \"Create datasource binding\")\n\n8. Go to the deployed **application2** and start it.\n\n9. Go back to the deployed **application1** and open the `Configuration` tab -\u003e `Destinations`.\n\n10. Click `New Destination` and provide the required details:\n- Name: application2-destination\n- Type: HTTP\n- URL: Enter the url of the started **application2**\n- Proxy Type: Internet\n- Authentication: AppToAppSSO\n\n![create-destination-neo](./images/create-destination-neo.png \"Create destination to application2\")\n\n11. Start **application1**.\n\n\n\n#### SAP BTP Neo UI Deployment\n\nYou can use a sample SAPUI5 application to trigger Java endpoints in a user-friendly environment.\nFollow the steps below to deploy the SAPUI5 application to the SAP BTP Neo cockpit and connect it to the Java application.\n1. Choose HTML5 Applications in the left navigation panel.\n   ![NEO_UI_DEPLOY_1](./images/NEO_UI_DEPLOY_1.png \"HTML5 Applications\")\n\n2. Choose \"Import from file\" to create an application and provide the required details:\n- Download the [zip](./scenario/neo/employeelistui/dist.zip) file to your local machine and provide a path to the archive in the \"Zip File\" field.\n- Application name\n- Application version\n\n![NEO_UI_DEPLOY_2](./images/NEO_UI_DEPLOY_2.png \"Create new HTML5 Application\")\n\n3. Select a new application in the list and open its details page.\n\n![NEO_UI_DEPLOY_3](./images/NEO_UI_DEPLOY_3.png \"App Details\")\n\n4. Choose \"Versioning\" -\u003e \"Versions\" to activate a new version.\n\n![NEO_UI_DEPLOY_4](./images/NEO_UI_DEPLOY_4.png \"Activate a new version page\")\n\n5. Choose \"Activate version\" and confirm the activation in a popup.\n\n![NEO_UI_DEPLOY_5](./images/NEO_UI_DEPLOY_5.png \"Activate a new version\")\n\n6. Go back to the app overview page. Verify that the application is started and copy the application link.\n\n![NEO_UI_DEPLOY_6](./images/NEO_UI_DEPLOY_6.png \"Application link\")\n\n7. Go to Connectivity/Destinations and create a new destination to connect the SAPUI5 application to the Java application.\n   - Name: javamagement\n   - Type: HTTP\n   - URL: Enter the url of the started **application1**\n   - ProxyType: Internet\n   - Authentication: AppToAppSSO\n\n![NEO_UI_DEPLOY_7](./images/NEO_UI_DEPLOY_7.png \"Create a destination\")\n\n8. Open the SAPUI5 application using a link taken from the application overview page (see step 6).\n\n## Migration\n\nThis is a guide on how to migrate scenario applications from SAP BTP Neo to SAP BTP Cloud Foundry. You can find already migrated applications in the `scenario/cf/` directory.\n\nTo try this migration yourself, copy the content in the `scenario/neo/` directory to another directory of your choice (e.g. `migration/`) and follow the next steps.\n\n### Step 1. Neo Java Web API to SAP Cloud SDK\nThe Neo Java Web API dependency is not provided in Cloud Foundry. Comment out the following lines in `migration/application1/pom.xml` and `migration/application2/pom.xml`:\u003cbr\u003e\n:x:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.sap.cloud\u003c/groupId\u003e\n    \u003cartifactId\u003eneo-java-web-api\u003c/artifactId\u003e\n    \u003cversion\u003e${neo-java-web-api-version}\u003c/version\u003e\n    \u003cscope\u003eprovided\u003c/scope\u003e\n\u003c/dependency\u003e\n```\nYou can use the SAP Cloud SDK to interact with services:\u003cbr\u003e\n\n:white_check_mark:\n```xml\n\u003cdependencyManagement\u003e\n  \u003cdependencies\u003e\n   \u003cdependency\u003e\n      \u003cgroupId\u003ecom.sap.cloud.sjb.cf\u003c/groupId\u003e\n      \u003cartifactId\u003ecf-tomcat-bom\u003c/artifactId\u003e\n      \u003cversion\u003e${cf-tomcat-bom-version}\u003c/version\u003e\n      \u003ctype\u003epom\u003c/type\u003e\n      \u003cscope\u003eimport\u003c/scope\u003e\n   \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.sap.cloud.sdk\u003c/groupId\u003e\n        \u003cartifactId\u003esdk-modules-bom\u003c/artifactId\u003e\n        \u003cversion\u003e${sdk-modules-bom-version}\u003c/version\u003e\n        \u003ctype\u003epom\u003c/type\u003e\n        \u003cscope\u003eimport\u003c/scope\u003e\n    \u003c/dependency\u003e\n  \u003c/dependencies\u003e\n\u003c/dependencyManagement\u003e\n\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.sap.cloud.sdk.cloudplatform\u003c/groupId\u003e\n        \u003cartifactId\u003escp-cf\u003c/artifactId\u003e\n    \u003c/dependency\u003e\n    ...\n\u003c/dependencies\u003e\n```\n```\n\u003cproperties\u003e\n...\n  \u003ccf-tomcat-bom-version\u003eAdd version here\u003c/cf-tomcat-bom-version\u003e\n  \u003csdk-modules-bom-version\u003eAdd version hеrе\u003c/sdk-modules-bom-version\u003e\n...\n\u003c/properties\u003e\n```\n\u003e Note: sdk-modules-bom - Bill of Materials (BOM) of the SAP Cloud SDK modules. For versions see [here](https://mvnrepository.com/artifact/com.sap.cloud.sdk/sdk-modules-bom). Note that v4.*.* and below are compatible with java 8.\u003cbr\u003e\n\u003e Note: cf-tomcat-bom - Versions control of CF Tomcat BOM. For version see [here](https://mvnrepository.com/artifact/com.sap.cloud.sjb.cf/cf-tomcat-bom). Note that v1.*.* is compatible with java 8.\u003cbr\u003e\n\n\nAs the Neo Java Web API is not provided in the SAP BTP Cloud Foundry environment, you need to **comment out** all Neo-related `\u003cresource-ref\u003e` from `migration/application1` and `migration/application2`.\nThey are located in `application1/src/webapp/WEB-INF/web.xml` and `application2/src/webapp/WEB-INF/web.xml`. The following are available:\u003cbr\u003e\n:x:\n```xml\n\u003cresource-ref\u003e\n    \u003cres-ref-name\u003ejdbc/application1\u003c/res-ref-name\u003e\n    \u003cres-type\u003ejavax.sql.DataSource\u003c/res-type\u003e\n\u003c/resource-ref\u003e\n\n\u003cresource-ref\u003e\n    \u003cres-ref-name\u003econnectivityConfiguration\u003c/res-ref-name\u003e\n    \u003cres-type\u003ecom.sap.core.connectivity.api.configuration.ConnectivityConfiguration\u003c/res-type\u003e\n\u003c/resource-ref\u003e\n\n\u003cresource-ref\u003e\n    \u003cres-ref-name\u003eauthenticationHeaderProvider\u003c/res-ref-name\u003e\n    \u003cres-type\u003ecom.sap.core.connectivity.api.authentication.AuthenticationHeaderProvider\u003c/res-type\u003e\n\u003c/resource-ref\u003e\n```\n\nUseful links:\n- SAP Cloud SDK for Java - [documentation](https://sap.github.io/cloud-sdk/docs/java/overview-cloud-sdk-for-java)\n- Bill Of Materials - [documentation](https://help.sap.com/docs/btp/sap-business-technology-platform/bill-of-materials-bom)\n\n### Step 2. Approuter\nIf your application interacts with the user (e.g. use template engines or serves static files like *.html), you need to use approuter which will act as a gateway which will trigger authentication.\u003cbr\u003e\n\nStart by creating a new directory with the name `approuter` in the `migration/application1` and `migration/application2` directories. Create `package.json` and `xs-app.json` files inside the `approuter` directory. \u003cbr\u003e\n\n`package.json`:\n```json\n{\n  \"name\": \"approuter\",\n  \"dependencies\": {\n    \"@sap/approuter\": \"^16.0.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node node_modules/@sap/approuter/approuter.js\"\n  }\n}\n```\n\u003e Note: The version of the approuter can change. Please take this into account during actual migration. See  [NPM](https://www.npmjs.com/package/@sap/approuter).\n\n\n\n`xs-app.json` for application1:\n```json\n{\n  \"authenticationMethod\": \"route\",\n  \"routes\": [\n    {\n      \"source\": \"^(/.*)\",\n      \"target\": \"$1\",\n      \"destination\": \"cf-app1-destination\",\n      \"authenticationType\": \"xsuaa\",\n      \"csrfProtection\": false\n    }\n  ]\n}\n```\n\n`xs-app.json` for application2:\n```json\n{\n  \"authenticationMethod\": \"route\",\n  \"routes\": [\n    {\n      \"source\": \"^(/.*)\",\n      \"target\": \"$1\",\n      \"destination\": \"cf-app2-destination\",\n      \"authenticationType\": \"xsuaa\",\n      \"csrfProtection\": false\n    }\n  ]\n}\n```\n\n\u003e Note: Put your name of destination which will be used to proxy requests from approuter to the backend application. You can create this destination in SAP BTP Cockpit or create it with the deployment descriptor. The creation of a destination with the deployment descriptor is described in one of next steps.\u003cbr\u003e\n\u003e See: [Application Router Configuration Syntax](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-developer-guide-for-cloud-foundry-multitarget-applications-sap-web-ide-full-stack/application-router-configuration-syntax)\n\n### Step 3. Authentication and authorization\nSAP BTP Cloud Foundry uses the XSUAA service instance for authentication and authorization.\u003cbr\u003e\nTo use it, you need to create a service instance and a service binding to your application.\u003cbr\u003e\n\nThe creation of XSUAA service instance/service binding is done automatically by the `cf deploy` command with Deployment Artifact (Section [Step 7. Deployment](#step-7-deployment)).\u003cbr\u003e\nWe need to create the `xs-security.json` file which is also known as Security Descriptor - configuration file for specifying scopes, role-templates, role-collection etc.\n\n:white_check_mark:\u003cbr\u003e\n`migration/application1/xs-security.json`:\n```json\n{\n   \"xsappname\": \"cf-application1\",\n   \"tenant-mode\": \"dedicated\",\n   \"scopes\": [\n      {\n         \"name\": \"$XSAPPNAME.Everyone\",\n         \"description\": \"Everyone\"\n      },\n      {\n         \"name\": \"uaa.user\",\n         \"description\": \"UAA\"\n      }\n   ],\n   \"role-templates\": [\n      {\n         \"name\": \"Everyone\",\n         \"scope-references\": [\n            \"$XSAPPNAME.Everyone\",\n            \"uaa.user\"\n         ]\n      }\n   ],\n   \"role-collections\": [\n      {\n         \"name\": \"Everyone_RC\",\n         \"role-template-references\": [\n            \"$XSAPPNAME.Everyone\"\n         ]\n      }\n   ]\n}\n```\n\n:white_check_mark:\u003cbr\u003e\n`migration/application2/xs-security.json`:\n```json\n{\n   \"xsappname\": \"cf-application2\",\n   \"tenant-mode\": \"dedicated\",\n   \"scopes\": [\n      {\n         \"name\": \"$XSAPPNAME.Everyone\",\n         \"description\": \"Everyone\"\n      }\n   ],\n   \"role-templates\": [\n      {\n         \"name\": \"Everyone\",\n         \"scope-references\": [\n            \"$XSAPPNAME.Everyone\"\n         ]\n      }\n   ],\n   \"role-collections\": [\n      {\n         \"name\": \"Everyone_RC_app2\",\n         \"role-template-references\": [\n            \"$XSAPPNAME.Everyone\"\n         ]\n      }\n   ]\n}\n```\n\n\nIn the `src/main/webapp/WEB-INF/web.xml` of the `migration/application1` and `migration/application2` java application, you need to change `\u003cauth-method\u003e` to XSUAA:\u003cbr\u003e\n:white_check_mark:\n```xml\n\u003clogin-config\u003e\n    \u003cauth-method\u003eXSUAA\u003c/auth-method\u003e\n\u003c/login-config\u003e\n```\n\n\u003e Note: In SAP BTP Neo all authenticated users implicitly have the `Everyone` role, but that is not the case for SAP BTP Cloud Foundry.\n\nIn SAP BTP Neo applications, the `UserManagementAccessor` API was used to retrieve information about the current user. \u003cbr\u003e\nIn SAP BTP Cloud Foundry, we will use [cloud-security-services-integration-library](https://github.com/SAP/cloud-security-services-integration-library/tree/main-2.x).\nTo do that, we need to add the following dependency to pom.xml (both for `migration/application1` and `migration/application2`):\u003cbr\u003e\n\n:white_check_mark:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.sap.cloud.security\u003c/groupId\u003e\n    \u003cartifactId\u003ejava-api\u003c/artifactId\u003e\n\u003c/dependency\u003e\n```\n\nThis is how the code that is responsible for user data retrieval needs to be modified: \u003cbr\u003e\n**`migration/application1/src/java/servlet/UserInfoServlet`**:\u003cbr\u003e\n\n\u003e Note: Below the comparison block you can copy the already refacoted code from the toggle button:\n\n```diff\npackage com.example.application1.servlet;\n\nimport com.example.application1.dto.UserDto;\nimport com.fasterxml.jackson.databind.ObjectMapper;\n-import com.sap.security.um.service.UserManagementAccessor;\n-import com.sap.security.um.user.User;\n-import com.sap.security.um.user.UserProvider;\n-import org.slf4j.Logger;\n-import org.slf4j.LoggerFactory;\n+import com.sap.cloud.security.token.SecurityContext;\n+import com.sap.cloud.security.token.Token;\n+import com.sap.cloud.security.token.TokenClaims;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n+import java.io.IOException;\n\npublic class UserInfoServlet extends HttpServlet {\n\n-  private final static Logger LOGGER = LoggerFactory.getLogger(UserInfoServlet.class);\n\n  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {\n-    if (request.getUserPrincipal() == null) {\n-      throw new ServletException(\"User principal is null\");\n-   }\n+   Token token = SecurityContext.getAccessToken();\n\n+    if (token == null) {\n+      throw new ServletException(\"Access token is null\");\n+    }\n\n-    try {\n-      // UserProvider provides access to the user storage\n-      UserProvider users = UserManagementAccessor.getUserProvider();\n-\n-      // Read the currently logged-in user from the user storage\n-      User user = users.getUser(request.getUserPrincipal().getName());\n-\n-      String username = user.getAttribute(\"firstname\") + \" \" + user.getAttribute(\"lastname\");\n\n+     String userНame = token.getClaimAsString(TokenClaims.GIVEN_NAME);\n+    String email = token.getClaimAsString(TokenClaims.EMAIL);   \n-      String email = user.getAttribute(\"email\");\n\n      UserDto userDto = new UserDto(userНame, email);\n      String userDtoJson = new ObjectMapper().writeValueAsString(userDto);\n      response.getWriter().print(userDtoJson);\n-    } catch (Exception e) {\n-      LOGGER.error(\"Exception occurred: \" + e.getMessage(), e);\n-\n-      throw new ServletException(e);\n-    }\n}\n\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eClick here to copy the full refactored code for UserInfoServlet\u003c/summary\u003e\n\n```java\npackage com.example.application1.servlet;\n\nimport com.example.application1.dto.UserDto;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.sap.cloud.security.token.SecurityContext;\nimport com.sap.cloud.security.token.Token;\nimport com.sap.cloud.security.token.TokenClaims;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\npublic class UserInfoServlet extends HttpServlet {\n\n  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {\n    Token token = SecurityContext.getAccessToken();\n\n    if (token == null) {\n      throw new ServletException(\"Access token is null\");\n    }\n\n    String userName = token.getClaimAsString(TokenClaims.GIVEN_NAME);\n    String email = token.getClaimAsString(TokenClaims.EMAIL);\n\n    UserDto userDto = new UserDto(userName, email);\n\n    String userDtoJson = new ObjectMapper().writeValueAsString(userDto);\n\n    // Print the username and email\n    response.getWriter().print(userDtoJson);\n  }\n\n}\n```\n\u003c/details\u003e\n\nYou can copy the following classes which have been refactored as shown above:\n\n\u003cdetails\u003e\n\u003csummary\u003eHomeServlet class in migration/application2\u003c/summary\u003e\nThe path of the old Neo code: scenario/neo/application2/src/java\n\n```java\npackage com.example.application2;\n\nimport com.sap.cloud.security.token.SecurityContext;\nimport com.sap.cloud.security.token.Token;\nimport com.sap.cloud.security.token.TokenClaims;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\npublic class HomeServlet extends HttpServlet {\n\n  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {\n    Token token = SecurityContext.getAccessToken();\n\n    if (token == null) {\n      request.setAttribute(\"message\", \"Access token is null\");\n      request.getRequestDispatcher(\"/error.jsp\").forward(request, response);\n      return;\n    }\n\n    String userName = token.getClaimAsString(TokenClaims.USER_NAME);\n    String email = token.getClaimAsString(TokenClaims.EMAIL);\n\n    // Print the username and email\n    request.setAttribute(\"username\", userName);\n    request.setAttribute(\"email\", email);\n\n    request.getRequestDispatcher(\"/home.jsp\").forward(request, response);\n  }\n\n}\n```\n\u003c/details\u003e\n\n\n\nUseful links:\n- Application Security Descriptor Configuration Syntax - [documentation](https://help.sap.com/docs/btp/sap-business-technology-platform/application-security-descriptor-configuration-syntax)\n- SAP BTP Neo Get User Attributes - [documentation](https://help.sap.com/docs/btp/sap-btp-neo-environment/user-attributes)\n\n### Step 4. Destinations\nSAP BTP Neo application used ConnectivityConfiguration and AuthenticationHeaderProvider APIs. They should be **already commented out** from `migration/application1/src/main/webapp/WEB-INF/web.xml` and `migration/application2/src/main/webapp/WEB-INF/web.xml` as shown in [Step 1](#step-1-neo-java-web-api-to-sap-cloud-sdk).\u003cbr\u003e\n\nSAP BTP Neo and CF Code difference for destination usage in `application1`. For SAP BTP Cloud Foundry, the SAP Cloud SDK provides an API to consume destinations created in the SAP BTP Cockpit.\u003cbr\u003e\n\n\u003e Note: Below the comparison block you can copy the already refacoted code from the toggle button\n```diff\npackage com.example.application1.servlet;\n\nimport com.example.application1.dao.PersonDAO;\nimport com.example.application1.model.Person;\nimport com.fasterxml.jackson.databind.ObjectMapper;\n-import com.sap.core.connectivity.api.authentication.AuthenticationHeader;\n-import com.sap.core.connectivity.api.authentication.AuthenticationHeaderProvider;\n-import com.sap.core.connectivity.api.configuration.ConnectivityConfiguration;\n-import com.sap.core.connectivity.api.configuration.DestinationConfiguration;\n+import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;\n+import com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationNotFoundException;\nimport org.apache.http.HttpEntity;\n+import org.apache.http.client.HttpClient;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.entity.mime.MultipartEntityBuilder;\nimport org.apache.http.impl.client.BasicResponseHandler;\n-import org.apache.http.impl.client.CloseableHttpClient;\n-import org.apache.http.impl.client.HttpClients;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n-import javax.naming.InitialContext;\n-import javax.naming.NamingException;\nimport javax.servlet.ServletException;\nimport javax.servlet.annotation.MultipartConfig;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.Part;\nimport java.io.IOException;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.List;\n\n+import static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor.getDestination;\n+import static com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor.getHttpClient;\n\n@MultipartConfig\npublic class ManagementPageServlet extends HttpServlet {\n\n  private final static Logger LOGGER = LoggerFactory.getLogger(ManagementPageServlet.class);\n\n  private final static String DESTINATION_NAME = \"application2-destination\";\n\n-  private ConnectivityConfiguration connectivityConfiguration;\n-  private AuthenticationHeaderProvider authenticationHeaderProvider;\n-\n-  @Override\n-  public void init() throws ServletException {\n-    try {\n-      InitialContext ctx = new InitialContext();\n-\n-      connectivityConfiguration = (ConnectivityConfiguration) ctx.lookup(\"java:comp/env/connectivityConfiguration\");\n-      authenticationHeaderProvider = (AuthenticationHeaderProvider) ctx.lookup(\"java:comp/env/authenticationHeaderProvider\");\n-    } catch (NamingException e) {\n-      throw new ServletException(\"Can't lookup resources\", e);\n-    }\n-  }\n-\n  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {\n    PersonDAO personDAO = new PersonDAO();\n    List\u003cPerson\u003e personnel = personDAO.findAll();\n\n    String personnelJson = new ObjectMapper().writeValueAsString(personnel);\n    response.getWriter().print(personnelJson);\n  }\n\n  @Override\n  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n    String action = request.getParameter(\"action\");\n\n    if (\"delete\".equals(action)) {\n      doDelete(request, response);\n      return;\n    }\n    String fname = request.getParameter(\"fname\");\n    String lname = request.getParameter(\"lname\");\n\n    Person person = new Person();\n    person.setFirstName(fname);\n    person.setLastName(lname);\n\n    Part file = request.getPart(\"file\");\n\n    if (file.getSize() \u003e 0) {\n-      DestinationConfiguration destinationConfiguration = connectivityConfiguration.getConfiguration(DESTINATION_NAME);\n-      if (destinationConfiguration == null) {\n+        HttpDestination httpDestination;\n+      try {\n+        httpDestination = getDestination(DESTINATION_NAME).asHttp();\n+      } catch (DestinationNotFoundException e) {\n        String message = \"Destination to application2 not found.\";\n        LOGGER.error(message);\n\n        throw new ServletException(message);\n      }\n\n-      String requestUrl = destinationConfiguration.getProperty(\"URL\") + \"/api/documents\";\n+     String requestUrl = httpDestination.getUri() + \"/api/documents\";\n      AuthenticationHeader appToAppSSOHeader = authenticationHeaderProvider.getApptoAppSSOHeader(requestUrl, destinationConfiguration);\n\n-      try (CloseableHttpClient httpClient = HttpClients.createDefault()) {\n+     try {\n+       HttpClient httpClient = getHttpClient(httpDestination);\n        URIBuilder builder = new URIBuilder(requestUrl);\n        builder.setParameter(\"caller\", \"external\");\n        builder.setParameter(\"fileName\", file.getSubmittedFileName());\n        URI uri = builder.build();\n\n        HttpPost httpPost = new HttpPost(uri);\n-        httpPost.addHeader(appToAppSSOHeader.getName(), appToAppSSOHeader.getValue());\n\n        HttpEntity httpEntity = MultipartEntityBuilder.create().addBinaryBody(\"file\", file.getInputStream()).build();\n\n        httpPost.setEntity(httpEntity);\n\n        String documentId = httpClient.execute(httpPost, new BasicResponseHandler()).replaceAll(\"^\\\"|\\\\n$\", \"\");\n        person.setImageId(documentId);\n      } catch (IOException e) {\n        LOGGER.error(\"Can't establish connection with Document Storage application: \" + e.getMessage(), e);\n      } catch (URISyntaxException e) {\n        LOGGER.error(\"Exception occurred: \" + e.getMessage(), e);\n\n        throw new ServletException(e);\n      }\n    }\n\n    PersonDAO personDAO = new PersonDAO();\n    personDAO.save(person);\n  }\n\n  @Override\n-  protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException {\n+  protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n    String personId = request.getParameter(\"personId\");\n    long id = Long.parseLong(personId);\n    PersonDAO personDAO = new PersonDAO();\n\n    Person person = personDAO.findById(id);\n    String imageId = person.getImageId();\n\n    if (imageId != null) {\n-      DestinationConfiguration destinationConfiguration = connectivityConfiguration.getConfiguration(DESTINATION_NAME);\n-      if (destinationConfiguration == null) {\n+     HttpDestination httpDestination;\n+     try {\n+       httpDestination = getDestination(DESTINATION_NAME).asHttp();\n+     } catch (DestinationNotFoundException e) {\n        String message = \"Destination to application2 not found.\";\n        LOGGER.error(message);\n\n        throw new ServletException(message);\n      }\n\n-     String requestUrl = destinationConfiguration.getProperty(\"URL\") + \"/api/documents\";\n+     String requestUrl = httpDestination.getUri() + \"/api/documents\";\n-     AuthenticationHeader appToAppSSOHeader = authenticationHeaderProvider.getApptoAppSSOHeader(requestUrl, destinationConfiguration);\n\n-     try (CloseableHttpClient httpClient = HttpClients.createDefault())\n+     try\n      {\n+       HttpClient httpClient = getHttpClient(httpDestination);\n        URIBuilder builder = new URIBuilder(requestUrl);\n        builder.setParameter(\"action\", \"delete\");\n        builder.setParameter(\"caller\", \"external\");\n        builder.setParameter(\"documentId\", imageId);\n        URI uri = builder.build();\n\n        HttpPost httpPost = new HttpPost(uri);\n-       httpPost.addHeader(appToAppSSOHeader.getName(), appToAppSSOHeader.getValue());\n\n-       httpClient.execute(httpPost, new BasicResponseHandler());\n+       httpClient.execute(httpPost);\n      } catch (IOException e) {\n        LOGGER.error(\"Can't establish connection with Document Storage application: \" + e.getMessage(), e);\n      } catch (URISyntaxException e) {\n        LOGGER.error(\"Exception occurred: \" + e.getMessage(), e);\n\n        throw new ServletException(e);\n      }\n    }\n\n    personDAO.delete(id);\n  }\n}\n```\n\u003cdetails\u003e\n\u003csummary\u003eManagementPageServlet refactored code\u003c/summary\u003e\n\n```java\npackage com.example.application1.servlet;\n\nimport com.example.application1.dao.PersonDAO;\nimport com.example.application1.model.Person;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;\nimport com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationNotFoundException;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.apache.http.entity.mime.MultipartEntityBuilder;\nimport org.apache.http.impl.client.BasicResponseHandler;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.annotation.MultipartConfig;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.Part;\nimport java.io.IOException;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.List;\n\nimport static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor.getDestination;\nimport static com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor.getHttpClient;\n\n@MultipartConfig\npublic class ManagementPageServlet extends HttpServlet {\n\n  private final static Logger LOGGER = LoggerFactory.getLogger(ManagementPageServlet.class);\n\n  private final static String DESTINATION_NAME = \"application2-destination\";\n\n  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {\n    PersonDAO personDAO = new PersonDAO();\n    List\u003cPerson\u003e personnel = personDAO.findAll();\n\n    String personnelJson = new ObjectMapper().writeValueAsString(personnel);\n    response.getWriter().print(personnelJson);\n\n  }\n\n  @Override\n  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n    String action = request.getParameter(\"action\");\n\n    if (\"delete\".equals(action)) {\n      doDelete(request, response);\n      return;\n    }\n    String fname = request.getParameter(\"fname\");\n    String lname = request.getParameter(\"lname\");\n\n    Person person = new Person();\n    person.setFirstName(fname);\n    person.setLastName(lname);\n\n    Part file = request.getPart(\"file\");\n\n    if (file.getSize() \u003e 0) {\n      HttpDestination httpDestination;\n      try {\n        httpDestination = getDestination(DESTINATION_NAME).asHttp();\n      } catch (DestinationNotFoundException e) {\n        String message = \"Destination to application2 not found.\";\n        LOGGER.error(message);\n\n        throw new ServletException(message);\n      }\n\n\n      String requestUrl = httpDestination.getUri() + \"/api/documents\";\n\n      try {\n        HttpClient httpClient = getHttpClient(httpDestination);\n\n        URIBuilder builder = new URIBuilder(requestUrl);\n        builder.setParameter(\"caller\", \"external\");\n        builder.setParameter(\"fileName\", file.getSubmittedFileName());\n        URI uri = builder.build();\n\n        HttpPost httpPost = new HttpPost(uri);\n\n        HttpEntity httpEntity = MultipartEntityBuilder.create().addBinaryBody(\"file\", file.getInputStream()).build();\n\n        httpPost.setEntity(httpEntity);\n\n        String documentId = httpClient.execute(httpPost, new BasicResponseHandler()).replaceAll(\"^\\\"|\\\\n$\", \"\");\n        person.setImageId(documentId);\n      } catch (IOException e) {\n        LOGGER.error(\"Can't establish connection with Document Storage application: \" + e.getMessage(), e);\n      } catch (URISyntaxException e) {\n        LOGGER.error(\"Exception occurred: \" + e.getMessage(), e);\n\n        throw new ServletException(e);\n      }\n    }\n\n    PersonDAO personDAO = new PersonDAO();\n    personDAO.save(person);\n  }\n\n  @Override\n  protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n    String personId = request.getParameter(\"personId\");\n    long id = Long.parseLong(personId);\n    PersonDAO personDAO = new PersonDAO();\n\n    Person person = personDAO.findById(id);\n    String imageId = person.getImageId();\n\n    if (imageId != null) {\n      HttpDestination httpDestination;\n      try {\n        httpDestination = getDestination(DESTINATION_NAME).asHttp();\n      } catch (DestinationNotFoundException e) {\n        String message = \"Destination to application2 not found.\";\n        LOGGER.error(message);\n\n        throw new ServletException(message);\n      }\n\n      String requestUrl = httpDestination.getUri() + \"/api/documents\";\n\n      try {\n        HttpClient httpClient = getHttpClient(httpDestination);\n\n        URIBuilder builder = new URIBuilder(requestUrl);\n        builder.setParameter(\"action\", \"delete\");\n        builder.setParameter(\"caller\", \"external\");\n        builder.setParameter(\"documentId\", imageId);\n        URI uri = builder.build();\n\n        HttpPost httpPost = new HttpPost(uri);\n\n        httpClient.execute(httpPost);\n      } catch (IOException e) {\n        LOGGER.error(\"Can't establish connection with Document Storage application: \" + e.getMessage(), e);\n      } catch (URISyntaxException e) {\n        LOGGER.error(\"Exception occurred: \" + e.getMessage(), e);\n\n        throw new ServletException(e);\n      }\n    }\n\n    personDAO.delete(id);\n  }\n}\n```\n\u003c/details\u003e\n\nCopy the classes that have been refactored as shown below:\n\n\u003cdetails\u003e\n\u003csummary\u003eImageServlet class refactored code\u003c/summary\u003e\n\n```java\npackage com.example.application1.servlet;\n\nimport com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;\nimport com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationNotFoundException;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.utils.URIBuilder;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.ServletOutputStream;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.BufferedInputStream;\nimport java.io.BufferedOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.net.URISyntaxException;\n\nimport static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor.getDestination;\nimport static com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor.getHttpClient;\n\npublic class ImageServlet extends HttpServlet {\n\n  private final static Logger LOGGER = LoggerFactory.getLogger(ImageServlet.class);\n\n  private final static String DESTINATION_NAME = \"application2-destination\";\n\n  @Override\n  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n\n    String documentId = request.getParameter(\"documentId\");\n\n    HttpDestination httpDestination;\n    try {\n      httpDestination = getDestination(DESTINATION_NAME).asHttp();\n    } catch (DestinationNotFoundException e) {\n      String message = \"Destination to application2 not found.\";\n      LOGGER.error(message);\n\n      throw new ServletException(message);\n    }\n\n    String requestUrl = httpDestination.getUri() + \"/api/documents\";\n\n    try {\n      HttpClient httpClient = getHttpClient(httpDestination);\n\n      URIBuilder builder = new URIBuilder(requestUrl);\n      builder.setParameter(\"documentId\", documentId);\n\n      HttpGet httpGet = new HttpGet(builder.build());\n      HttpResponse httpResponse = httpClient.execute(httpGet);\n\n      InputStream inputStream = httpResponse.getEntity().getContent();\n      ServletOutputStream outputStream = response.getOutputStream();\n\n      copyContent(inputStream, outputStream);\n    } catch (URISyntaxException e) {\n      throw new ServletException(e);\n    }\n\n  }\n\n  private void copyContent(InputStream is, OutputStream os) throws ServletException {\n    try (BufferedInputStream bis = new BufferedInputStream(is); BufferedOutputStream bos = new BufferedOutputStream(os)) {\n      byte[] buffer = new byte[1024];\n      int count;\n      while ((count = bis.read(buffer)) \u003e= 0) {\n        bos.write(buffer, 0, count);\n      }\n    } catch (IOException e) {\n      throw new ServletException(\"Can't copy stream\", e);\n    }\n  }\n}\n```\n\u003c/details\u003e\n\n\u003e Note: Simple and efficient example on how to migrate destinations from SAP BTP Neo to SAP BTP Cloud Foundry:\n\u003e - [SAP BTP Neo Destinations Migration Sample](https://github.com/SAP-samples/btp-destination-service-samples)\n\n### Step 5. Connectivity\n\nFor SAP BTP Cloud Foundry, we can use the SAP Cloud SDK to establish a connection to an OnPremise system with SAP Cloud Connector. The SAP Cloud SDK provides an API to consume destinations created in the SAP BTP Cockpit.\u003cbr\u003e\n\nThe SAP BTP Neo application uses ConnectivityConfiguration and AuthenticationHeaderProvider APIs. They should be **already commented out** from `migration/application2/src/main/webapp/WEB-INF/web.xml` as shown in [Step 1](#step-1-neo-java-web-api-to-sap-cloud-sdk).\u003cbr\u003e\n\n#### Refactor SAP BTP Neo Code for connectivity usage\n\nThis is how we can refactor SAP BTP Neo Code for connectivity usage.\u003cbr\u003e\n\n\u003e Note: Below the comparison block you can copy the already refactored code from the toggle button\n\n```diff\npublic class OnPremiseServlet extends HttpServlet {\n\n  private final static Logger LOGGER = LoggerFactory.getLogger(OnPremiseServlet.class);\n\n  private final static String DESTINATION_NAME = \"on-premise-dest\";\n\n-  @Resource\n-  private TenantContext tenantContext;\n-\n-  private ConnectivityConfiguration connectivityConfiguration;\n-\n-  @Override\n-  public void init() {\n-    try {\n-      InitialContext ctx = new InitialContext();\n-\n-      connectivityConfiguration = (ConnectivityConfiguration) ctx.lookup(\"java:comp/env/connectivityConfiguration\");\n-    } catch (NamingException e) {\n-      throw new RuntimeException(\"Can't lookup resources\", e);\n-    }\n-  }\n\n  @Override\n  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n    String message;\n    try {\n-      DestinationConfiguration destinationConfiguration = connectivityConfiguration.getConfiguration(DESTINATION_NAME);\n+     HttpDestination httpDestination = getDestination(DESTINATION_NAME).asHttp();\n-     String requestUrl = destinationConfiguration.getProperty(\"URL\") + \"/hello-servlet\";\n+     String requestUrl = httpDestination.getUri() + \"/hello-servlet\";\n\n-      String proxyHost = System.getenv(\"HC_OP_HTTP_PROXY_HOST\");\n-      int proxyPort = Integer.parseInt(System.getenv(\"HC_OP_HTTP_PROXY_PORT\"));\n-\n-      Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));\n-\n-      URL url = new URL(requestUrl);\n-      HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(proxy);\n-      urlConnection.setRequestProperty(\"SAP-Connectivity-ConsumerAccount\", tenantContext.getTenant().getAccount().getName());\n-\n-      try (InputStream inputStream = urlConnection.getInputStream()) {\n-        message = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines().collect(Collectors.joining(\"\\n\"));\n-      }\n+     HttpClient httpClient = getHttpClient(httpDestination);\n+     HttpGet httpGet = new HttpGet(requestUrl);\n+     message = httpClient.execute(httpGet, new BasicResponseHandler());\n    } catch (Exception e) {\n      LOGGER.error(\"Can't establish connection to OnPremise system\", e);\n\n      message = \"Can't establish connection to OnPremise system: \" + e.getMessage();\n    }\n\n    request.setAttribute(\"message\", message);\n    request.getRequestDispatcher(\"/on-premise.jsp\").forward(request, response);\n  }\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eOnPremiseServlet refactored code\u003c/summary\u003e\n\n```java\npackage com.example.application2;\n\nimport com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.impl.client.BasicResponseHandler;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\nimport static com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor.getDestination;\nimport static com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor.getHttpClient;\n\npublic class OnPremiseServlet extends HttpServlet {\n\n  private final static Logger LOGGER = LoggerFactory.getLogger(OnPremiseServlet.class);\n\n  private final static String DESTINATION_NAME = \"on-premise-dest\";\n\n  @Override\n  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n    String message;\n    try {\n      HttpDestination httpDestination = getDestination(DESTINATION_NAME).asHttp();\n      String requestUrl = httpDestination.getUri() + \"/hello-servlet\";\n\n      HttpClient httpClient = getHttpClient(httpDestination);\n      HttpGet httpGet = new HttpGet(requestUrl);\n\n      message = httpClient.execute(httpGet, new BasicResponseHandler());\n    } catch (Exception e) {\n      LOGGER.error(\"Can't establish connection to OnPremise system\", e);\n\n      message = \"Can't establish connection to OnPremise system: \" + e.getMessage();\n    }\n\n    request.setAttribute(\"message\", message);\n\n    request.getRequestDispatcher(\"/on-premise.jsp\").forward(request, response);\n  }\n}\n```\n\u003c/details\u003e\n\nSAP Cloud SDK connectivity [documentation](https://sap.github.io/cloud-sdk/docs/java/features/connectivity/on-premise)\u003cbr\u003e\n\n#### Run OnPremise demo application\n\n##### SAP Cloud Connector setup:\n\n- Download the appropriate version of SAP Cloud connector for your machine from the [SAP Development Tools](https://tools.hana.ondemand.com/#cloud) -\u003e Cloud page.\n- Extract the downloaded zip and run the `./go.sh` script.\n- There would be a link in the console after you start the SCC from which you can access it from the browser.\n- The default credentials are:\n   - `Administrator` for the username\n   - `manage` for the password\n- After you login make sure to connect the SAP Cloud Connector to your SAP BTP subaccount.\n   - `Add subaccount -\u003e Configure manually -\u003e Enter subaccount data -\u003e Finish`\n- In the 'Cloud to On-premise' tab create a virtual mapping to your local application and create a `resource` with path `'/'` and select `Path And All Sub-Paths`\n  ![sap-cloud-connector](./images/set_up_scc.png \"SAP Cloud Connector setup\")\u003cbr\u003e\n\n##### Run on-premise-demo app:\n\n- Option 1. Import it into your IDE and run with tomcat here.\n- Option 2. Deploy right into tomcat by copying the `*.war` file into the `webapps` directory.\n\u003e Note: For option 2 to start the on-premise-app simply run the following command from the tomcat folder: `./bin/startup.sh`\n- Option 3. Use docker to build and run the application in a container.\n\nBuild the application with maven:\n```\nmvn clean package\n```\nCreate the following `Dockerfile` in the scenario/on-premise-demo folder:\n```Dockerfile\nFROM tomcat:9.0.89-jdk8\nCOPY target/*.war $CATALINA_HOME/webapps/\nEXPOSE 8080\nCMD [\"catalina.sh\",\"run\"]\n```\nBuild the docker image with the following command:\n```\ndocker build -t tomcat-docker .\n```\nRun the docker image with the following command:\n```\ndocker run -p 8080:8080 tomcat-docker\n```\n\n\u003e Note: You can add the `-d` flag to run the docker image in detached mode\n\nYou can checkout the on-premise app on the following URL: `http://localhost:8080/on-premise-demo-1.0-SNAPSHOT/hello-servlet`\n\n**BTP Cockpit -\u003e Cloud Foundry -\u003e Connectivity -\u003e Destination**\n\n![on-premise-dest](./images/on-premise-dest.png \"on-premise-dest destination\")\u003cbr\u003e\n\n### Step 6. Document Management Service\n\n**Comment out** the following lines from `migration/application2/src/main/webapp/WEB-INF/web.xml`:\u003cbr\u003e\n:x:\n```xml\n\u003cresource-ref\u003e\n    \u003cres-ref-name\u003eEcmService\u003c/res-ref-name\u003e\n    \u003cres-type\u003ecom.sap.ecm.api.EcmService\u003c/res-type\u003e\n\u003c/resource-ref\u003e\n```\n\nFor SAP BTP Cloud Foundry, we need to add the following dependencies to `migration/application2/pom.xml`.\u003cbr\u003e\n:white_check_mark:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.apache.chemistry.opencmis\u003c/groupId\u003e\n    \u003cartifactId\u003echemistry-opencmis-client-impl\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.apache.chemistry.opencmis\u003c/groupId\u003e\n    \u003cartifactId\u003echemistry-opencmis-client-api\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nFor SAP BTP Cloud Foundry, the main difference is in **retrieval of opencmis session.**\u003cbr\u003e\nSAP BTP Neo opencmis session retrieval:\u003cbr\u003e\n\n\u003e Note: Below the comparison block you can copy the already refacoted code from the toggle button\n\n```diff\npackage com.example.application2.ecm;\n\n+import com.fasterxml.jackson.core.JsonProcessingException;\n+import com.fasterxml.jackson.core.type.TypeReference;\n+import com.fasterxml.jackson.databind.JsonNode;\n+import com.fasterxml.jackson.databind.ObjectMapper;\n+import com.fasterxml.jackson.databind.node.ObjectNode;\n-import com.sap.ecm.api.EcmService;\n-import com.sap.ecm.api.RepositoryOptions;\nimport org.apache.chemistry.opencmis.client.api.Session;\n-import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;\n+import org.apache.chemistry.opencmis.client.api.SessionFactory;\n+import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl;\n+import org.apache.chemistry.opencmis.commons.SessionParameter;\n+import org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException;\n+import org.apache.http.HttpHeaders;\n+import org.apache.http.HttpResponse;\n+import org.apache.http.client.methods.HttpGet;\n+import org.apache.http.client.methods.HttpPost;\n+import org.apache.http.entity.StringEntity;\n+import org.apache.http.impl.client.CloseableHttpClient;\n+import org.apache.http.impl.client.HttpClientBuilder;\n\n+import java.io.BufferedReader;\n+import java.io.IOException;\n+import java.io.InputStreamReader;\n+import java.nio.charset.StandardCharsets;\n+import java.util.Base64;\n+import java.util.HashMap;\n+import java.util.Map;\n+import java.util.Optional;\n\n-import javax.naming.InitialContext;\n-import javax.naming.NamingException;\n\npublic class EcmManager {\n- private final static String UNIQUE_NAME = \"test_repository\";\n- private final static String SECRET_KEY = \"test_repository_secret_key\";\n\n+ // CMIS Session parameter values\n+ private final static String BROWSER = \"browser\";\n+ private final static String TRUE = \"true\";\n+ private final static String FALSE = \"false\";\n+ private final static String LANGUAGE_EN = \"en\";\n+ private final static String CONNECTION_TIMEOUT = Integer.toString(30_000);\n+ private final static String READ_TIMEOUT = Integer.toString(600_000);\n\n+ // VCAP Services environment nodes\n+ private final static String VCAP_SERVICES = \"VCAP_SERVICES\";\n+ private final static String SDM = \"sdm\";\n+ private final static String CREDENTIALS = \"credentials\";\n+ private final static String ENDPOINTS = \"endpoints\";\n+ private final static String ECM_SERVICE = \"ecmservice\";\n+ private final static String URL = \"url\";\n+ private final static String UAA = \"uaa\";\n+ private final static String ACCESS_TOKEN = \"access_token\";\n+ private final static String TOKEN_ENDPOINT = \"/oauth/token\";\n+ private final static String CLIENT_ID = \"clientid\";\n+ private final static String CLIENT_SECRET = \"clientsecret\";\n+ private final static String AUTHORIZATION = \"Authorization\";\n+ private final static String CONTENT_TYPE = \"Content-Type\";\n+ private final static String GRANT_TYPE = \"client_credentials\";\n\n+ // repository infos properties\n+ private final static String REPOSITORIES_ENDPOINT = \"rest/v2/repositories/\";\n+ private final static String REPO_AND_CONNECTION_INFOS = \"repoAndConnectionInfos\";\n+ private final static String REPOSITORY = \"repository\";\n+ private final static String ID = \"id\";\n\n  private static EcmManager instance;\n- private final EcmService ecmService;\n+ private volatile Session openCmisSession;\n\n  private EcmManager() {\n-   try {\n-     InitialContext ctx = new InitialContext();\n-     String lookupName = \"java:comp/env/EcmService\";\n-     ecmService = (EcmService) ctx.lookup(lookupName);\n-   } catch (NamingException e) {\n-     throw new RuntimeException(\"Can't lookup EcmService\");\n-   }\n  }\n\n  public static synchronized EcmManager getInstance() {\n    if (instance == null) {\n      instance = new EcmManager();\n    }\n\n    return instance;\n  }\n\n\n  public Session getSession() {\n-   Session session;\n-   try {\n-     // connect to repository\n-     session = ecmService.connect(UNIQUE_NAME, SECRET_KEY);\n-   } catch (CmisObjectNotFoundException e) {\n-     // repository does not exist, so try to create it\n-     createRepository();\n-     session = ecmService.connect(UNIQUE_NAME, SECRET_KEY);\n-    }\n-    return session;\n-  }\n+   if (openCmisSession == null) {\n+     synchronized (EcmManager.class) {\n+       if (openCmisSession == null) {\n+         openCmisSession = createCMISSession();\n+       }\n+     }\n+   } else {\n+     // stub to avoid CmisUnauthorizedException (session expires because of cookies)\n+     synchronized (EcmManager.class) {\n+       try {\n+         openCmisSession.getRootFolder();\n+       } catch (CmisUnauthorizedException e) {\n+         openCmisSession = createCMISSession();\n+       }\n+     }\n+   }\n+   return openCmisSession;\n+ }\n\n\n+  private Session createCMISSession() {\n+    SessionFactory sessionFactory = SessionFactoryImpl.newInstance();\n+    Map\u003cString, String\u003e parameterMap = new HashMap\u003c\u003e();\n+\n+    parameterMap.put(SessionParameter.BINDING_TYPE, BROWSER);\n+    parameterMap.put(SessionParameter.BROWSER_URL, getEcmServiceUrl() + BROWSER);\n+    parameterMap.put(SessionParameter.OAUTH_ACCESS_TOKEN, getAuthorizationToken());\n+\n+    parameterMap.put(SessionParameter.REPOSITORY_ID, getRepositoryId());\n+\n+    parameterMap.put(SessionParameter.AUTH_HTTP_BASIC, FALSE);\n+    parameterMap.put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, FALSE);\n+    parameterMap.put(SessionParameter.AUTH_OAUTH_BEARER, TRUE);\n+    parameterMap.put(SessionParameter.COMPRESSION, TRUE);\n+    parameterMap.put(SessionParameter.CLIENT_COMPRESSION, FALSE);\n+    parameterMap.put(SessionParameter.COOKIES, TRUE);\n+    parameterMap.put(SessionParameter.LOCALE_ISO639_LANGUAGE, LANGUAGE_EN);\n+    parameterMap.put(SessionParameter.CONNECT_TIMEOUT, CONNECTION_TIMEOUT);\n+    parameterMap.put(SessionParameter.READ_TIMEOUT, READ_TIMEOUT);\n+\n+    return sessionFactory.createSession(parameterMap);\n+  }\n\n+  private String getEcmServiceUrl() {\n+    Optional\u003cString\u003e ecmServiceUrl;\n+\n+    try {\n+      ObjectMapper mapper = new ObjectMapper();\n+      JsonNode vcap = mapper.readTree(System.getenv(VCAP_SERVICES));\n+      JsonNode credentials = vcap.get(SDM).get(0).get(CREDENTIALS);\n+      ecmServiceUrl = Optional.of(credentials.get(ENDPOINTS).get(ECM_SERVICE).get(URL).asText());\n+    } catch (JsonProcessingException e) {\n+      throw new RuntimeException(\"Can't retrieve ecm url from VCAP environment variables\", e);\n+    }\n+\n+    return ecmServiceUrl.get();\n+  }\n\n+  private String getAuthorizationToken() throws UnsupportedOperationException {\n+    Optional\u003cString\u003e tokenContent;\n+    Map\u003cString, String\u003e map = getSDMCredentials();\n+    final String tokenURL = map.get(URL) + TOKEN_ENDPOINT;\n+\n+    String base64Credentials = Base64.getEncoder().encodeToString((map.get(CLIENT_ID) + \":\" + map.get(CLIENT_SECRET)).getBytes());\n+\n+    try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {\n+      HttpPost httpPost = new HttpPost(tokenURL);\n+      httpPost.addHeader(AUTHORIZATION, \"Basic \" + base64Credentials);\n+      httpPost.addHeader(CONTENT_TYPE, \"application/x-www-form-urlencoded\");\n+\n+      StringEntity input = new StringEntity(\"grant_type=\" + GRANT_TYPE);\n+      httpPost.setEntity(input);\n+\n+      HttpResponse response = httpClient.execute(httpPost);\n+      BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));\n+      tokenContent = Optional.of(br.readLine());\n+\n+      ObjectMapper mapper = new ObjectMapper();\n+      TypeReference\u003cMap\u003cString, String\u003e\u003e typeRef = new TypeReference\u003cMap\u003cString, String\u003e\u003e() {};\n+      HashMap\u003cString, String\u003e hashMap = (HashMap\u003cString, String\u003e) mapper.readValue(tokenContent.get(), typeRef);\n+      return hashMap.get(ACCESS_TOKEN);\n+    } catch (IOException e) {\n+      throw new RuntimeException(\"Can't get authorization token\");\n+    }\n+  }\n\n+  private Map\u003cString, String\u003e getSDMCredentials() {\n+    try {\n+      Map\u003cString, String\u003e map = new HashMap\u003c\u003e();\n+\n+      ObjectMapper mapper = new ObjectMapper();\n+      JsonNode vcap = mapper.readTree(System.getenv(VCAP_SERVICES));\n+      JsonNode credentials = vcap.get(SDM).get(0).get(CREDENTIALS);\n+\n+      map.put(CLIENT_ID, credentials.get(UAA).get(CLIENT_ID).asText());\n+      map.put(CLIENT_SECRET, credentials.get(UAA).get(CLIENT_SECRET).asText());\n+      map.put(URL, credentials.get(UAA).get(URL).asText());\n+\n+      return map;\n+    } catch (IOException e) {\n+      throw new RuntimeException(\"Can't retrieve VCAP_SERVICES SDM credentials\");\n+    }\n+  }\n\n-  private void createRepository() {\n-    RepositoryOptions options = new RepositoryOptions();\n-    options.setUniqueName(EcmManager.UNIQUE_NAME);\n-    options.setRepositoryKey(EcmManager.SECRET_KEY);\n-    options.setVisibility(RepositoryOptions.Visibility.PROTECTED);\n-    ecmService.createRepository(options);\n-  }\n\n+ private String getRepositoryId() {\n+     Optional\u003cString\u003e repositoryId;\n+     Optional\u003cString\u003e repositoryInfo;\n+ \n+     try {\n+       repositoryInfo = getRepositoryInfos();\n+ \n+       // if repository info is not empty, fetch the repository id\n+       if (!repositoryInfo.get().equals(\"{}\")) {\n+         repositoryId = parseRepositoryInfosAndGetID();\n+       } else {\n+         // creating a new repository when there is none found\n+         repositoryId = createNewRepository();\n+       }\n+     } catch (IOException e) {\n+       throw new RuntimeException(\"Can't retrieve repository id\");\n+     }\n+ \n+     return repositoryId.get();\n+   }\n+ \n+   private Optional\u003cString\u003e parseRepositoryInfosAndGetID() throws IOException {\n+     Optional\u003cString\u003e repositoryInfo = getRepositoryInfos();\n+     ObjectMapper mapper = new ObjectMapper();\n+ \n+     if (repositoryInfo.isPresent()) {\n+       JsonNode vcap = mapper.readTree(repositoryInfo.get());\n+       JsonNode repoAndConnectionInfos = vcap.get(REPO_AND_CONNECTION_INFOS);\n+ \n+       return Optional.of(repoAndConnectionInfos.get(REPOSITORY).get(ID).asText());\n+     } else {\n+       throw new RuntimeException(\"Can't parse repositories information\");\n+     }\n+   }\n+ \n+   private Optional\u003cString\u003e getRepositoryInfos() throws IOException {\n+     String accessToken = getAuthorizationToken();\n+ \n+     final String repoURL = getEcmServiceUrl() + REPOSITORIES_ENDPOINT;\n+ \n+     try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {\n+       HttpGet httpGet = new HttpGet(repoURL);\n+ \n+       httpGet.setHeader(HttpHeaders.CONTENT_TYPE, \"application/json\");\n+       httpGet.setHeader(HttpHeaders.AUTHORIZATION, \"Bearer \" + accessToken);\n+ \n+       HttpResponse response = httpClient.execute(httpGet);\n+       BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));\n+ \n+       return Optional.of(br.readLine());\n+     }\n+   }\n+ \n+   private Optional\u003cString\u003e createNewRepository() throws IOException {\n+     Optional\u003cString\u003e id;\n+ \n+     final String repoURL = getEcmServiceUrl() + REPOSITORIES_ENDPOINT;\n+     try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {\n+       HttpPost request = new HttpPost(repoURL);\n+ \n+       request.setHeader(HttpHeaders.CONTENT_TYPE, \"application/json\");\n+       request.setHeader(HttpHeaders.AUTHORIZATION, \"Bearer \" + getAuthorizationToken());\n+ \n+       // Setting payload for the new repository\n+       StringEntity payload = new StringEntity(setRepositoryPayload());\n+       request.setEntity(payload);\n+ \n+       // An error is thrown if no entitlement is configured for document management\n+       // service, repository option\n+       HttpResponse response = httpClient.execute(request);\n+       if (response.getStatusLine().getStatusCode() == 500) {\n+         throw new RuntimeException(\"No entitlement is configured for \" + \"Document Management Service, Repository Option. Entitlements is required to create a repository.\");\n+       }\n+ \n+       BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));\n+       Optional\u003cString\u003e responseBody = Optional.of(br.readLine());\n+ \n+       ObjectMapper mapper = new ObjectMapper();\n+       JsonNode jsonNode = mapper.readTree(responseBody.get());\n+       id = Optional.of(jsonNode.get(\"id\").asText());\n+ \n+       return id;\n+     }\n+   }\n+ \n+   private String setRepositoryPayload() {\n+ \n+     // creating payload for new repository\n+     ObjectMapper mapper = new ObjectMapper();\n+     ObjectNode rootNode = mapper.createObjectNode();\n+ \n+     ObjectNode leafNode = mapper.createObjectNode();\n+     leafNode.put(\"displayName\", \"JDBC-DocumentMGMT Repository\");\n+     leafNode.put(\"description\", \"JDBC-DocumentMGMT document store\");\n+     leafNode.put(\"repositoryType\", \"internal\");\n+     leafNode.put(\"isVirusScanEnabled\", \"true\");\n+     leafNode.put(\"skipVirusScanForLargeFile\", \"false\");\n+     leafNode.put(\"hashAlgorithms\", \"SHA-256\");\n+ \n+     rootNode.set(\"repository\", leafNode);\n+     return rootNode.toString();\n+   }\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eEcmManager refactored code\u003c/summary\u003e\n\n```java\npackage com.example.application2.ecm;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\nimport org.apache.chemistry.opencmis.client.api.Session;\nimport org.apache.chemistry.opencmis.client.api.SessionFactory;\nimport org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl;\nimport org.apache.chemistry.opencmis.commons.SessionParameter;\nimport org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException;\nimport org.apache.http.HttpHeaders;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.entity.StringEntity;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClientBuilder;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic class EcmManager {\n\n  // CMIS Session parameter values\n  private final static String BROWSER = \"browser\";\n  private final static String TRUE = \"true\";\n  private final static String FALSE = \"false\";\n  private final static String LANGUAGE_EN = \"en\";\n  private final static String CONNECTION_TIMEOUT = Integer.toString(30_000);\n  private final static String READ_TIMEOUT = Integer.toString(600_000);\n\n  // VCAP Services environment nodes\n  private final static String VCAP_SERVICES = \"VCAP_SERVICES\";\n  private final static String SDM = \"sdm\";\n  private final static String CREDENTIALS = \"credentials\";\n  private final static String ENDPOINTS = \"endpoints\";\n  private final static String ECM_SERVICE = \"ecmservice\";\n  private final static String URL = \"url\";\n  private final static String UAA = \"uaa\";\n  private final static String ACCESS_TOKEN = \"access_token\";\n  private final static String TOKEN_ENDPOINT = \"/oauth/token\";\n  private final static String CLIENT_ID = \"clientid\";\n  private final static String CLIENT_SECRET = \"clientsecret\";\n  private final static String AUTHORIZATION = \"Authorization\";\n  private final static String CONTENT_TYPE = \"Content-Type\";\n  private final static String GRANT_TYPE = \"client_credentials\";\n\n  // repository infos properties\n  private final static String REPOSITORIES_ENDPOINT = \"rest/v2/repositories/\";\n  private final static String REPO_AND_CONNECTION_INFOS = \"repoAndConnectionInfos\";\n  private final static String REPOSITORY = \"repository\";\n  private final static String ID = \"id\";\n\n\n  private static EcmManager instance;\n  private volatile Session openCmisSession;\n\n  private EcmManager() {}\n\n  public static synchronized EcmManager getInstance() {\n    if (instance == null) {\n      instance = new EcmManager();\n    }\n\n    return instance;\n  }\n\n\n  public Session getSession() {\n    if (openCmisSession == null) {\n      synchronized (EcmManager.class) {\n        if (openCmisSession == null) {\n          openCmisSession = createCMISSession();\n        }\n      }\n    } else {\n      // stub to avoid CmisUnauthorizedException (session expires because of cookies)\n      synchronized (EcmManager.class) {\n        try {\n          openCmisSession.getRootFolder();\n        } catch (CmisUnauthorizedException e) {\n          openCmisSession = createCMISSession();\n        }\n      }\n    }\n\n    return openCmisSession;\n  }\n\n\n  private Session createCMISSession() {\n    SessionFactory sessionFactory = SessionFactoryImpl.newInstance();\n    Map\u003cString, String\u003e parameterMap = new HashMap\u003c\u003e();\n\n    parameterMap.put(SessionParameter.BINDING_TYPE, BROWSER);\n    parameterMap.put(SessionParameter.BROWSER_URL, getEcmServiceUrl() + BROWSER);\n    parameterMap.put(SessionParameter.OAUTH_ACCESS_TOKEN, getAuthorizationToken());\n\n    parameterMap.put(SessionParameter.REPOSITORY_ID, getRepositoryId());\n\n    parameterMap.put(SessionParameter.AUTH_HTTP_BASIC, FALSE);\n    parameterMap.put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, FALSE);\n    parameterMap.put(SessionParameter.AUTH_OAUTH_BEARER, TRUE);\n    parameterMap.put(SessionParameter.COMPRESSION, TRUE);\n    parameterMap.put(SessionParameter.CLIENT_COMPRESSION, FALSE);\n    parameterMap.put(SessionParameter.COOKIES, TRUE);\n    parameterMap.put(SessionParameter.LOCALE_ISO639_LANGUAGE, LANGUAGE_EN);\n    parameterMap.put(SessionParameter.CONNECT_TIMEOUT, CONNECTION_TIMEOUT);\n    parameterMap.put(SessionParameter.READ_TIMEOUT, READ_TIMEOUT);\n\n    return sessionFactory.createSession(parameterMap);\n  }\n\n  private String getEcmServiceUrl() {\n    Optional\u003cString\u003e ecmServiceUrl;\n\n    try {\n      ObjectMapper mapper = new ObjectMapper();\n      JsonNode vcap = mapper.readTree(System.getenv(VCAP_SERVICES));\n      JsonNode credentials = vcap.get(SDM).get(0).get(CREDENTIALS);\n      ecmServiceUrl = Optional.of(credentials.get(ENDPOINTS).get(ECM_SERVICE).get(URL).asText());\n    } catch (JsonProcessingException e) {\n      throw new RuntimeException(\"Can't retrieve ecm url from VCAP environment variables\", e);\n    }\n\n    return ecmServiceUrl.get();\n  }\n\n  private String getAuthorizationToken() throws UnsupportedOperationException {\n    Optional\u003cString\u003e tokenContent;\n    Map\u003cString, String\u003e map = getSDMCredentials();\n    final String tokenURL = map.get(URL) + TOKEN_ENDPOINT;\n\n    String base64Credentials = Base64.getEncoder().encodeToString((map.get(CLIENT_ID) + \":\" + map.get(CLIENT_SECRET)).getBytes());\n\n    try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {\n      HttpPost httpPost = new HttpPost(tokenURL);\n      httpPost.addHeader(AUTHORIZATION, \"Basic \" + base64Credentials);\n      httpPost.addHeader(CONTENT_TYPE, \"application/x-www-form-urlencoded\");\n\n      StringEntity input = new StringEntity(\"grant_type=\" + GRANT_TYPE);\n      httpPost.setEntity(input);\n\n      HttpResponse response = httpClient.execute(httpPost);\n      BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));\n      tokenContent = Optional.of(br.readLine());\n\n      ObjectMapper mapper = new ObjectMapper();\n      TypeReference\u003cMap\u003cString, String\u003e\u003e typeRef = new TypeReference\u003cMap\u003cString, String\u003e\u003e() {};\n      HashMap\u003cString, String\u003e hashMap = (HashMap\u003cString, String\u003e) mapper.readValue(tokenContent.get(), typeRef);\n      return hashMap.get(ACCESS_TOKEN);\n    } catch (IOException e) {\n      throw new RuntimeException(\"Can't get authorization token\");\n    }\n  }\n\n  private Map\u003cString, String\u003e getSDMCredentials() {\n    try {\n      Map\u003cString, String\u003e map = new HashMap\u003c\u003e();\n\n      ObjectMapper mapper = new ObjectMapper();\n      JsonNode vcap = mapper.readTree(System.getenv(VCAP_SERVICES));\n      JsonNode credentials = vcap.get(SDM).get(0).get(CREDENTIALS);\n\n      map.put(CLIENT_ID, credentials.get(UAA).get(CLIENT_ID).asText());\n      map.put(CLIENT_SECRET, credentials.get(UAA).get(CLIENT_SECRET).asText());\n      map.put(URL, credentials.get(UAA).get(URL).asText());\n\n      return map;\n    } catch (IOException e) {\n      throw new RuntimeException(\"Can't retrieve VCAP_SERVICES SDM credentials\");\n    }\n  }\n\n  private String getRepositoryId() {\n    Optional\u003cString\u003e repositoryId;\n    Optional\u003cString\u003e repositoryInfo;\n\n    try {\n      repositoryInfo = getRepositoryInfos();\n\n      // if repository info is not empty, fetch the repository id\n      if (!repositoryInfo.get().equals(\"{}\")) {\n        repositoryId = parseRepositoryInfosAndGetID();\n      } else {\n        // creating a new repository when there is none found\n        repositoryId = createNewRepository();\n      }\n    } catch (IOException e) {\n      throw new RuntimeException(\"Can't retrieve repository id\");\n    }\n\n    return repositoryId.get();\n  }\n\n\n\n  private Optional\u003cString\u003e parseRepositoryInfosAndGetID() throws IOException {\n    Optional\u003cString\u003e repositoryInfo = getRepositoryInfos();\n    ObjectMapper mapper = new ObjectMapper();\n\n    if (repositoryInfo.isPresent()) {\n      JsonNode vcap = mapper.readTree(repositoryInfo.get());\n      JsonNode repoAndConnectionInfos = vcap.get(REPO_AND_CONNECTION_INFOS);\n\n      return Optional.of(repoAndConnectionInfos.get(REPOSITORY).get(ID).asText());\n    } else {\n      throw new RuntimeException(\"Can't parse repositories information\");\n    }\n  }\n\n  private Optional\u003cString\u003e getRepositoryInfos() throws IOException {\n    String accessToken = getAuthorizationToken();\n\n    final String repoURL = getEcmServiceUrl() + REPOSITORIES_ENDPOINT;\n\n    try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {\n      HttpGet httpGet = new HttpGet(repoURL);\n\n      httpGet.setHeader(HttpHeaders.CONTENT_TYPE, \"application/json\");\n      httpGet.setHeader(HttpHeaders.AUTHORIZATION, \"Bearer \" + accessToken);\n\n      HttpResponse response = httpClient.execute(httpGet);\n      BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));\n\n      return Optional.of(br.readLine());\n    }\n  }\n\n  private Optional\u003cString\u003e createNewRepository() throws IOException {\n    Optional\u003cString\u003e id;\n\n    final String repoURL = getEcmServiceUrl() + REPOSITORIES_ENDPOINT;\n    try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {\n      HttpPost request = new HttpPost(repoURL);\n\n      request.setHeader(HttpHeaders.CONTENT_TYPE, \"application/json\");\n      request.setHeader(HttpHeaders.AUTHORIZATION, \"Bearer \" + getAuthorizationToken());\n\n      // Setting payload for the new repository\n      StringEntity payload = new StringEntity(setRepositoryPayload());\n      request.setEntity(payload);\n\n      // An error is thrown if no entitlement is configured for document management\n      // service, repository option\n      HttpResponse response = httpClient.execute(request);\n      if (response.getStatusLine().getStatusCode() == 500) {\n        throw new RuntimeException(\"No entitlement is configured for \" + \"Document Management Service, Repository Option. Entitlements is required to create a repository.\");\n      }\n\n      BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));\n      Optional\u003cString\u003e responseBody = Optional.of(br.readLine());\n\n      ObjectMapper mapper = new ObjectMapper();\n      JsonNode jsonNode = mapper.readTree(responseBody.get());\n      id = Optional.of(jsonNode.get(\"id\").asText());\n\n      return id;\n    }\n  }\n\n  private String setRepositoryPayload() {\n\n    // creating payload for new repository\n    ObjectMapper mapper = new ObjectMapper();\n    ObjectNode rootNode = mapper.createObjectNode();\n\n    ObjectNode leafNode = mapper.createObjectNode();\n    leafNode.put(\"displayName\", \"JDBC-DocumentMGMT Repository\");\n    leafNode.put(\"description\", \"JDBC-DocumentMGMT document store\");\n    leafNode.put(\"repositoryType\", \"internal\");\n    leafNode.put(\"isVirusScanEnabled\", \"true\");\n    leafNode.put(\"skipVirusScanForLargeFile\", \"false\");\n    leafNode.put(\"hashAlgorithms\", \"SHA-256\");\n\n    rootNode.set(\"repository\", leafNode);\n    return rootNode.toString();\n  }\n\n}\n```\n\u003c/details\u003e\n\n\u003e Note: That is just an **example** of opencmis session retrieval.\n\nUseful links:\n- [Migrating Application to SAP Document Management Service from Neo Environment](https://help.sap.com/docs/document-management-service/sap-document-management-service/migrating-application-to-sap-document-management-service-from-neo-environment)\n\n### Step 7. Database\n**Comment out** the following lines from `migration/application1/webapp/WEB-INF/web.xml`:\u003cbr\u003e\n:x:\n```xml\n\u003cresource-ref\u003e\n    \u003cres-ref-name\u003ejdbc/application1\u003c/res-ref-name\u003e\n    \u003cres-type\u003ejavax.sql.DataSource\u003c/res-type\u003e\n\u003c/resource-ref\u003e\n```\n\nCreate a Hana Cloud service instance and service binding, choose type `schema` or specify it as a resource in `mta.yaml`.\u003cbr\u003e\nCreate the following file structure: `webapp/META-INF/sap_java_buildpack/config/resource_configuration.yml` and put the following content:\u003cbr\u003e\n:white_check_mark:\n```yaml\n---\ntomcat/webapps/ROOT/META-INF/context.xml:\n  service_name_for_DefaultDB: cf-app1-hana\n```\n\u003e Note: Provide your name of the service instance here.\n\nUnder `migration/application1/webapp/META-INF` create a `context.xml` file:\u003cbr\u003e\n:white_check_mark:\n```xml\n\u003c?xml version='1.0' encoding='utf-8'?\u003e\n\n\u003cContext\u003e\n    \u003cResource name=\"jdbc/application1\"\n              auth=\"Container\"\n              type=\"javax.sql.DataSource\"\n              factory=\"com.sap.xs.jdbc.datasource.tomcat.TomcatDataSourceFactory\"\n              service=\"${service_name_for_DefaultDB}\"/\u003e\n\u003c/Context\u003e\n```\n\u003e Note:\n\u003e Choose a name for the resource e.g. jdbc/DefaultDB as it is on SAP BTP Neo by default. It is jdbc/application1 in this scenario.\n\nIn [Step 9](#step-9-sap-btp-cf-deployment) you will have to add the following line to the application module's properties(`migration/application1/mta.yaml`). This is how the name of the service instance is passed to the application.\u003cbr\u003e\n:white_check_mark:\n```yaml\nJBP_CONFIG_RESOURCE_CONFIGURATION: [ \"tomcat/webapps/ROOT/META-INF/context.xml\": { \"service_name_for_DefaultDB\": \"cf-app1-hana\" } ]\n```\n\u003e Note: Place the name of the hana service instance here.\n\nSee: [Configure a Database Connection for the Tomcat Application Container](https://help.sap.com/docs/btp/sap-business-technology-platform/configure-database-connection-for-tomcat-application-container?locale=en-USstate%3DPRODUCTION)\n\n### Step 8. Setup destination from application1 to application2\n\nIn SAP BTP Neo, the destination from `application1` to `application2` was created with `Authentication: AppToAppSSO`.\u003cbr\u003e\n\nSAP BTP Cloud Foundry does not have such a destination's Authentication Type. Instead, we will use `Authentication: OAuth2UserTokenExchange`.\u003cbr\u003e\n\n![create-destination-cf](./images/create-destination-cf.png \"application2-destination\")\n\nProperties:\n- Name: application2-destination\n- Type: HTTP\n- URL: url of the deployed `migration/application2` (cf-application2 application in SAP BTP CloudFoundry Cockpit)\n- Proxy Type: Internet\n- Authentication: OAuth2UserTokenExchange\n- Client ID: clientid of the deployed `migration/application2` (cf-application2 application)\n- Client Secret: clientsecret of the deployed `migration/application2` (cf-application2 application)\n- Token Service URL: url of the deployed `migration/application2` (cf-application2 application) + `/oauth/token`\n\nClient ID, Client Secret and Token Service URL can be taken from `cf-app2-xsuaa` service binding. Find it in the Cockpit and click `View Credentials`:\n![cf-app2-xsuaa](./images/cf-app2-xsuaa.png \"cf-app2-xsuaa View Credentials\")\n\n\u003e Important! The Token Service URL is created by adding the XSUAA url and \"/oauth/token\" part.\u003cbr\u003e\n\u003e Important! E.g. XSUAA url = https://${some_domain}.hana.ondemand.com\u003cbr\u003e\n\u003e Important! E.g. Token Service URL = https://${some_domain}.hana.ondemand.com/oauth/token\n\nUseful links:\n- [OAuth User Token Exchange Authentication](https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/oauth-user-token-exchange-authentication)\n\n### Step 9. SAP BTP CF Deployment\n\n#### With mta.yaml\n\nFor SAP BTP Cloud Foundry, we can use a **deployment descriptor** to deploy an application.\nCreate a `mta.yaml` file in the project's root directory. It should be two different `mta.yaml` files: one for `application1` and one for `application2`.\u003cbr\u003e\n`migration/application1/mta.yaml` example:\n```yaml\n_schema-version: \"3.2\"\nversion: 0.0.1\nID: cf-application1\nmodules:\n  - name: cf-application1\n    type: java\n    path: ./\n    parameters:\n      disk-quota: 512MB\n      memory: 512MB\n    build-parameters:\n      buildpack: sap_java_buildpack\n      build-result: \"target/application1-1.0-SNAPSHOT.war\"\n    properties:\n      ENABLE_SECURITY_JAVA_API_V2: true\n      JBP_CONFIG_RESOURCE_CONFIGURATION: [ \"tomcat/webapps/ROOT/META-INF/context.xml\": { \"service_name_for_DefaultDB\": \"cf-app1-hana\" } ]\n      SET_LOGGING_LEVEL: 'ROOT: INFO'\n    requires:\n      - name: cf-app1-destination\n      - name: cf-app1-xsuaa\n      - name: cf-app1-hana\n    provides:\n      - name: cf-app1-java-app\n        properties:\n          java_app_url: '${default-url}'\n\n  - name: cf-application1-approuter\n    type: approuter.nodejs\n    path: approuter\n    parameters:\n      disk-quota: 256M\n      memory: 256M\n    properties:\n      XS_APP_LOG_LEVEL: debug\n    requires:\n      - name: cf-app1-xsuaa\n      - name: cf-app1-java-app\n        group: destinations\n        properties:\n          name: cf-app1-destination\n          url: '~{java_app_url}'\n          forwardAuthToken: true\n\nresources:\n  - name: cf-app1-destination\n    type: org.cloudfoundry.managed-service\n    parameters:\n      service: destination\n      service-plan: lite\n  - name: cf-app1-xsuaa\n    type: org.cloudfoundry.managed-service\n    parameters:\n      service: xsuaa\n      service-plan: application\n      path: ./xs-security.json\n  - name: cf-app1-hana\n    type: com.sap.xs.hana-schema\n```\n\n\u003cdetails\u003e\n\u003csummary\u003emta.yaml for migration/application2/mta.yaml\u003c/summary\u003e\n\n```yaml\n_schema-version: \"3.2\"\nversion: 0.0.1\nID: cf-application2\nmodules:\n  - name: cf-application2\n    type: java\n    path: ./\n    parameters:\n      disk-quota: 512MB\n      memory: 512MB\n    build-parameters:\n      buildpack: sap_java_buildpack\n      build-result: \"target/application2-1.0-SNAPSHOT.war\"\n    properties:\n      ENABLE_SECURITY_JAVA_API_V2: true\n      SET_LOGGING_LEVEL: 'ROOT: INFO'\n    requires:\n      - name: cf-app2-xsuaa\n      - name: cf-app2-sdm\n      - name: cf-app2-destination\n      - name: cf-app2-connectivity\n    provides:\n      - name: cf-app2-java-app\n        properties:\n          java_app_url: '${default-url}'\n\n  - name: cf-application2-approuter\n    type: approuter.nodejs\n    path: approuter\n    parameters:\n      disk-quota: 256M\n      memory: 256M\n    properties:\n      XS_APP_LOG_LEVEL: debug\n    requires:\n      - name: cf-app2-xsuaa\n      - name: cf-app2-java-app\n        group: destinations\n        properties:\n          name: cf-app2-destination\n          url: '~{java_app_url}'\n          forwardAuthToken: true\n\nresources:\n  - name: cf-app2-destination\n    type: org.cloudfoundry.managed-service\n    parameters:\n      service: destination\n      service-plan: lite\n  - name: cf-app2-connectivity\n    type: org.cloudfoundry.managed-service\n    parameters:\n      service: connectivity\n      service-plan: lite\n  - name: cf-app2-xsuaa\n    type: org.cloudfoundry.managed-service\n    parameters:\n      service: xsuaa\n      service-plan: application\n      path: ./xs-security.json\n  - name: cf-app2-sdm\n    type: org.cloudfoundry.managed-service\n    parameters:\n      service: sdm\n      service-plan: standard\n```\n\u003c/details\u003e\n\nThe `modules` section describes applications that will be deployed and the `resources` section describes service instances that will be created.\u003cbr\u003e\nEach application in the `modules` section has the following details:\n- name - name of the application to be deployed\n- type - type of the application (nodejs, java etc.)\n- path - **relative** path (relative to mta.yaml) to directory which contains the application files\n- properties - user-defined environment variables\n- requires - specifying resources' name will create a service binding to the deployed application\u003cbr\u003e\n\n#### Build and deploy\n\n1. Follow the next steps both for `migration/application1` and `migration/application2` directories. You can do it for `application1` first and for `application2` afterwards.\n2. Run `mvn clean package` to build the `*.war` file.\n3. Run `cf login --sso` and login to your subaccount and space.\n4. Run `mbt build` to generate the `mta_archives/\u003cname_of_mtar_file\u003e.mtar` file that will be used for deployment.\n5. Run `cf deploy mta_archives/\u003cname_of_mtar_file\u003e.mtar`.\n6. Wait for the deployment and start of the application.\n7. Make sure you assign yourself the `Everyone_RC` and `Everyone_RC_app2`  roles from the SAP BTP Cockpit in order to view the applications.\n\nUseful links:\n- [Multitarget Applications in the Cloud Foundry environment](https://help.sap.com/docs/btp/sap-business-technology-platform/multitarget-applications-in-cloud-foundry-environment)\u003cbr\u003e\n- [MTA Deployment Descriptor Syntax](https://help.sap.com/docs/SAP_HANA_PLATFORM/4505d0bdaf4948449b7f7379d24d0f0d/4050fee4c469498ebc31b10f2ae15ff2.html)\u003cbr\u003e\n\n#### Build and deploy SAPUI5 application\n1. Copy `scenario/cf/employeelistui` to the `migration` folder.\n1. Go to the `migration/employeelistui` directory.\n2. Run `cf login --sso` and login to your subaccount and space.\n3. Make sure [MTA Deployment Descriptor Syntax](./scenario/cf/employeelistui/mta.yaml) has a correct pattern to the cf-application1 app url in resources sections -\u003e javamigrationsample-destination-service-\u003ejavamagement destination.\n\n![CF_UI_DEPLOYMENT](./images/CF_UI_DEPLOYMENT.png \"SAPUI5 CF mta.yaml\")\n\n4. Run `mbt build` to generate the `mta_archives/\u003cname_of_mtar_file\u003e.mtar` file that will be used for deployment.\n5. Run the `cf deploy mta_archives/\u003cname_of_mtar_file\u003e.mtar`.\n6. Open the **HTML5 Applications** menu item in SAP BTP CF cockpit and search for javamigrationsample to open the application.\n\n\u003e Note: You have to subscribe to `SAP Build Workzone standard or advanced service` in order to see the SAP UI5 Application.\n\n\n![CF_UI_DEPLOYMENT_2](./images/CF_UI_DEPLOYMENT_2.png \"Open SAPUI5 CF app\")\n\n### Test the different scenarios\n\nYou should be able to test the different scenarios using the HTML5 UI. Open the HTML5 Applications menu item in SAP BTP CF cockpit and search for `javamigrationsample` to open the application. By using the UI you can test the different scenarios all in one by uploading a file, viewing the uploaded file, and deleting the uploaded file. Make sure the image doesn't exceed 2MB.\n\n**Scenarios:**\n- **Authentication and authorization:**\n   - Navigate to the BTP Cockpit and assign the `Everyone_RC` and `Everyone_RC_app2` roles to your user. After that use the approuter urls to access `application1` and `application2`. You will be prompted to login using an identity provider.\n   - Too see the current users info navigate to the `userinfo` endpoint of `application1`.\n- **Destination \u0026 Connectivity**\n   - The connectivity and destination scenario relates to the on-premise scenario. You can test the connection to the on-premise system by navigating to the `/onpremise` endpoint of `application2`. You should see the response from the on-premise hello servlet.\n- **Document Management Service (ECM):**\n   - You can test the ECM service by navigating to the `/documents` endpoint of `application2` and uploading a photo to the server.\n- **Persistency:**\n   - Easiest way to test the connection to the database is to upload an image using the SAP UI5 application. The image will be stored in the database. You can see the ids of the stored images if you navigate to the `management` endpoint of `application1`.\n    \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsap-samples%2Fbtp-neo-java-app-migration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsap-samples%2Fbtp-neo-java-app-migration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsap-samples%2Fbtp-neo-java-app-migration/lists"}