Technology Blog Posts by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Sudhir_Lenka
Contributor
2,268

Introduction

The SAP BTP Document Management Service(DMS) helps in managing business documents. It's based on the OASIS (Organization for the Advancement of Structured Information Standards) industry standard CMIS (Content Management Interoperability Services) and includes features like versioning, hierarchies, access control, and document management.

In this blog, I am going to explain how to create a custom spring boot application in SAP BTP cloud foundry and integrate it with SAP BTP DMS.

Business Scenario

Let’s say we have a requirement where we need to replicate documents from different SAP SaaS applications(e.g.  SAP SuccessFactors) to SAP BTP Document Management Service. In this case, we can create a custom Java Spring Boot application and deploy it to BTP Cloud Foundry as an MTA(multi-target application). Spring Boot application can have scheduled Cron Jobs(if there is any need for automation) or REST APIs(to be triggered from UI and any other application) to interact with DMS rest APIs and SuccessFactors.

Or if you have a custom application, and you want to use SAP BTP DMS for document management then this example will be helpful.

Technical Details

 In this blog, I will create a maven-based spring boot application(MTA) and will expose a REST API that will upload a document in the DMS.  Spring Boot application will interact with DMS REST API through BTP destinations. The main reason for using BTP destinations is the DMS authentication will be taken care of by BTP destinations.  I will be using SAP Cloud SDK to interact with BTP Destinations from Spring Boot.

Architecture

sudhiranjan_lenka_0-1723849924131.png

Prerequisite

  1. Access to SAP BTP Cloud Foundry, and org & space are created.
  2. Access to BTP destination.
  3. Access to SAP BTP DMS service and DMS repository is created.
  4. Eclipse(with Spring tool suite and Lombok plugin) and JDK(1.8) are installed in the development system.
  5. Cloud Foundry command line interface (CF CLI) is installed, and the path is set in the environment variable.
  6. Cloud MTA build tool (MBT) is installed, and the path is set in the environment variable.
  7. Make tool is installed, and the path is set in the environment variable.

Create a destination in SAP BTP for DMS service

sudhiranjan_lenka_1-1723849924142.png

 

  • Please make sure the URL contains the repository ID and folder name(if no folder is created in the repository, then use root)

Steps to create the Application

  1. Create a maven based spring boot project in Eclipse.

sudhiranjan_lenka_2-1723849924148.png

  1. Open the pom.xml file and replace it with the below code.

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.sl</groupId>
	<artifactId>SampleSAPBTPApplication</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>SampleSAPBTPApplication</name>
	<description>Sample SAP BTP App with Spring Boot</description>
	<url/>
	<licenses>
		<license/>
	</licenses>
	<developers>
		<developer/>
	</developers>
	<scm>
		<connection/>
		<developerConnection/>
		<tag/>
		<url/>
	</scm>
	<properties>
		<java.version>1.8</java.version>
		<swagger.version>2.9.2</swagger.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.sap.cloud.sdk.cloudplatform</groupId>
			<artifactId>scp-cf</artifactId>
			<version>3.46.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web-services</artifactId>
		</dependency>
		        <dependency>
		    <groupId>org.apache.httpcomponents</groupId>
		    <artifactId>httpclient</artifactId>
		    <version>4.5.10</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.httpcomponents</groupId>
		    <artifactId>httpmime</artifactId>
		    <version>4.5.10</version>
		</dependency>
		<dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-bean-validators</artifactId>
            <version>${swagger.version}</version>
        </dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<packaging>war</packaging>
</project>

 

 

  1. Create a Java class and replace the code with the below code (please check the package and class name).

 

package com.sl.demo.api;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor;
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor;
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

@RestController
public class BTPDMSService {

	private final Logger log = LoggerFactory.getLogger(this.getClass());

	/**
	 * Attaches a generic file to an existing work.
	 */
	@RequestMapping(method = RequestMethod.POST, path = "/uploadFile", produces = "application/json", consumes = "multipart/form-data")
	@ApiOperation(value = "Attaches a generic file to an existing work.")
	@ApiResponses({ @ApiResponse(code = 200, message = "OK", responseContainer = "Map", response = Long.class),
			@ApiResponse(code = 400, message = "Bad request"),
			@ApiResponse(code = 401, message = "Unauthorized, basic auth required"),
			@ApiResponse(code = 403, message = "Forbidden") })
	public String uploadFile(@RequestParam("attachment") MultipartFile file) throws IOException {

		log.info("Upload file started");

		String DESTINATION_NAME = "MyDestinationForDMS";
		byte[] content = file.getBytes();
		String filename = file.getOriginalFilename();
		String contentType = file.getContentType();

		HttpDestination destination = DestinationAccessor.getDestination(DESTINATION_NAME).asHttp();
		HttpClient httpclient = HttpClientAccessor.getHttpClient(destination);

		MultipartEntityBuilder builder = MultipartEntityBuilder.create();

		log.info("Uploading file : {}", filename);
		builder.addTextBody("cmisaction", "createDocument");
		builder.addTextBody("propertyId[0]", "cmis:name");
		builder.addTextBody("propertyValue[0]", "testSudhir01.json");
		builder.addTextBody("propertyId[1]", "cmis:objectTypeId");
		builder.addTextBody("propertyValue[1]", "cmis:document");
		builder.addTextBody("filename", "testSudhir01");
		builder.addTextBody("_charset_", "UTF-8");
		builder.addTextBody("includeAllowableAction", "true");
		builder.addTextBody("succinct", "true");
		builder.addBinaryBody("media", content, ContentType.create(contentType), filename);

		HttpEntity postData = builder.build();
		HttpPost httpPost = new HttpPost();
		httpPost.setEntity(postData);
		HttpResponse response = httpclient.execute(httpPost);
		HttpEntity entity = response.getEntity();
		log.info("Response from post File: {}", response.getStatusLine().getStatusCode());
		log.info("******** Response Body **********: {}", EntityUtils.toString(entity));

		return "Executed with status Code:" + response.getStatusLine().getStatusCode();
	}

}

 

  1. Create a Java class for swagger config and replace the code with the below code.

 

package com.sl.demo.swagger;

import java.util.Collections;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class SpringFoxConfig {

	String appTitle = "DMS Integration";

	@Bean
	public Docket api() {
		return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
				.apis(RequestHandlerSelectors.basePackage(parentPackageName())).paths(PathSelectors.ant("/**")).build();
	}

	private String parentPackageName() {
		String thisPackageName = getClass().getPackage().getName();
		int lastDotPos = thisPackageName.lastIndexOf('.');
		String parentPackageName = thisPackageName.substring(0, lastDotPos);
		return parentPackageName;
	}

	private ApiInfo apiInfo() {
		return new ApiInfo(appTitle + " API", "This is the API for the " + appTitle + " application.", "v1", null,
				new Contact("SL", "", "test@sl.com") , null, null,
				Collections.EMPTY_LIST);
	}
}

 

  1. Create a mta.yaml file in the workspace (where the project is created) and paste the below code into the mta.yaml file.

 

_schema-version: '3.0.0'
ID: com.sl.sampleApplication
description: Sample Application
version: 1.0.0
modules:
  - name: SampleSAPBTPApplication
    type: java
    path: SampleSAPBTPApplication
    parameters:
        stack: cflinuxfs4
        memory: 2048M
        instances: 1
        buildpacks:
           - java_buildpack
        build-parameters:
             builder: custom
             timeout: 10m
             build-result: target/SampleSAPBTPApplication-*.jar
             commands:
               - mvn clean install -Dcheckstyle.skip -DskipTests=true -Pdev
    requires:
      - name: BTPDestinationResource
# Binding services
resources:
  - name: BTPDestinationResource
    type: org.cloudfoundry.managed-service
    parameters:
      service-name: MyDestinationInstance
      service-plan: lite
      service: destination

 

  1. Select the project in Eclipse and update(Maven) the project, please make sure there is no compilation error.

Build and Deployment

  1. Open the command prompt from the workspace(where the mta.yaml file is placed) folder.

sudhiranjan_lenka_3-1723849924151.png

  1. Build the project to generate the “.tar” file by using the below command in the command prompt.

 

mbt build -t SampleSAPBTPApplication/generatedTAR --mtar SampleApplication.tar

 

sudhiranjan_lenka_14-1723850889798.png

sudhiranjan_lenka_15-1723850889809.png

  1. If the build is successful, then SampleApplication.tat file will be created in the generatedTAR folder.

 

sudhiranjan_lenka_16-1723850889814.png

 

  1. Use the below commands in the command prompt to log in to the BTP cloud foundry and deploy the project. (It will prompt you to enter the username and password for BTP. it will prompt you to select org and space if there is more than one)

 

cf login -a https://api.<CF API host>.hana.ondemand.com
cf deploy SampleSAPBTPApplication/generatedTAR/SampleApplication.tar

 

sudhiranjan_lenka_17-1723850889821.png

  1. Once the deployment is successful, it will be shown in the applications under the space.

sudhiranjan_lenka_18-1723850889828.png

  1. If everything is fine, then the status will be showing as started and the application can be accessed by using the URL shown under application routes.

sudhiranjan_lenka_19-1723850889838.png

Testing

  1. The application can be tested by using the swagger URL from the application as mentioned below.

https://<app URL-dev-samplesapbtpapplication.hana.ondemand.com>/swagger-ui.html 

sudhiranjan_lenka_20-1723850889848.png

  1. Click on “/uploadFile” API to test the file upload functionality.

sudhiranjan_lenka_21-1723850889852.png

  1. Choose any file and click on “Execute”.
  2. If everything is fine, then the file will be uploaded to DMS and can be found in DMS.

sudhiranjan_lenka_22-1723850889857.png

Conclusion

This blog is written based on my learning and understnading, please feel free to comment for the improvement.  Same thing can be achieved by creating a CAP appllication, in the next blog I will explain how to achieve the same requirement through a CAP (Java) application.

If anybody is interested for the code, please feel free to pull it from git.

https://github.com/sudhirlenkagit/MTASpringBootIntegratesDMS.git 

Thanks,

Sudhir Lenka.