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
Prerequisite
Create a destination in SAP BTP for DMS service
Steps to create the Application
<?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>
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();
}
}
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);
}
}
_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
Build and Deployment
mbt build -t SampleSAPBTPApplication/generatedTAR --mtar SampleApplication.tar
cf login -a https://api.<CF API host>.hana.ondemand.com
cf deploy SampleSAPBTPApplication/generatedTAR/SampleApplication.tar
Testing
https://<app URL-dev-samplesapbtpapplication.hana.ondemand.com>/swagger-ui.html
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
7 | |
6 | |
6 | |
4 | |
4 | |
4 | |
3 | |
3 | |
3 | |
3 |