summaryrefslogtreecommitdiffstats
path: root/components/datalake-handler/des/src/main
diff options
context:
space:
mode:
authorKai <lukai@chinamobile.com>2020-07-29 11:18:59 +0800
committerKai <lukai@chinamobile.com>2020-08-04 12:10:04 +0800
commit18e8674f4ea77cdf99594cf19cb1cc348b160cdf (patch)
tree19a98043493efb0666282fe1ecbbb14632e27581 /components/datalake-handler/des/src/main
parent241494cef9587dd2834e4192c71437a1741d9553 (diff)
seed code of des (data extraction service)
Issue-ID: DCAEGEN2-2258 Signed-off-by: Kai Lu <lukai@chinamobile.com> Change-Id: I576069a0016b2ce690274734d1c4d1c70deb0b05
Diffstat (limited to 'components/datalake-handler/des/src/main')
-rw-r--r--components/datalake-handler/des/src/main/java/org/onap/datalake/des/DesApplication.java43
-rw-r--r--components/datalake-handler/des/src/main/java/org/onap/datalake/des/SwaggerConfig.java67
-rw-r--r--components/datalake-handler/des/src/main/java/org/onap/datalake/des/controller/DataExposureController.java280
-rw-r--r--components/datalake-handler/des/src/main/java/org/onap/datalake/des/domain/DataExposure.java76
-rw-r--r--components/datalake-handler/des/src/main/java/org/onap/datalake/des/dto/DataExposureConfig.java36
-rw-r--r--components/datalake-handler/des/src/main/java/org/onap/datalake/des/repository/DataExposureRepository.java36
-rw-r--r--components/datalake-handler/des/src/main/java/org/onap/datalake/des/service/DataExposureService.java131
-rw-r--r--components/datalake-handler/des/src/main/resources/application.properties73
-rw-r--r--components/datalake-handler/des/src/main/resources/logback.xml20
-rw-r--r--components/datalake-handler/des/src/main/resources/swagger.json67
10 files changed, 829 insertions, 0 deletions
diff --git a/components/datalake-handler/des/src/main/java/org/onap/datalake/des/DesApplication.java b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/DesApplication.java
new file mode 100644
index 00000000..afb0fef9
--- /dev/null
+++ b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/DesApplication.java
@@ -0,0 +1,43 @@
+/*
+* ============LICENSE_START=======================================================
+* ONAP : Data Extraction Service
+* ================================================================================
+* Copyright 2020 China Mobile
+*=================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END=========================================================
+*/
+
+package org.onap.datalake.des;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * Entry point of the Data Extraction Service application
+ *
+ * @author Kai Lu
+ *
+ */
+
+@SpringBootApplication
+@EnableSwagger2
+public class DesApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(DesApplication.class, args);
+ }
+
+}
diff --git a/components/datalake-handler/des/src/main/java/org/onap/datalake/des/SwaggerConfig.java b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/SwaggerConfig.java
new file mode 100644
index 00000000..79022e50
--- /dev/null
+++ b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/SwaggerConfig.java
@@ -0,0 +1,67 @@
+/*
+* ============LICENSE_START=======================================================
+* ONAP : Data Extraction Service
+* ================================================================================
+* Copyright 2020 China Mobile
+*=================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END=========================================================
+*/
+
+package org.onap.datalake.des;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * For Swagger integration
+ *
+ * @author Kai Lu
+ *
+ */
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+
+ /**
+ * produceApi.
+ *
+ * @return Docket Docket
+ *
+ */
+ @Bean
+ public Docket produceApi() {
+ return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
+ .apis(RequestHandlerSelectors.basePackage("org.onap.datalake.des")).paths(PathSelectors.any()).build();
+ }
+
+ /**
+ * Api description.
+ *
+ * @return ApiInfo api Info
+ *
+ */
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder().title("DataLake Rest APIs")
+ .description("This page lists all the rest apis for DataLake.").version("1.0.0-SNAPSHOT").build();
+ }
+}
diff --git a/components/datalake-handler/des/src/main/java/org/onap/datalake/des/controller/DataExposureController.java b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/controller/DataExposureController.java
new file mode 100644
index 00000000..e71ba6b0
--- /dev/null
+++ b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/controller/DataExposureController.java
@@ -0,0 +1,280 @@
+/*
+* ============LICENSE_START=======================================================
+* ONAP : Data Extraction Service
+* ================================================================================
+* Copyright 2020 China Mobile
+*=================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END=========================================================
+*/
+
+package org.onap.datalake.des.controller;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.text.StringSubstitutor;
+import org.onap.datalake.des.domain.DataExposure;
+import org.onap.datalake.des.dto.DataExposureConfig;
+import org.onap.datalake.des.repository.DataExposureRepository;
+import org.onap.datalake.des.service.DataExposureService;
+import org.onap.datalake.feeder.controller.domain.PostReturnBody;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * Data Exposure WS.
+ *
+ * @author Kai Lu
+ *
+ */
+@RestController
+@RequestMapping(value = "/exposure", produces = { MediaType.APPLICATION_JSON_VALUE })
+@Api(value = "/exposure", consumes = "application/json", produces = "application/json")
+public class DataExposureController {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+ @Autowired
+ private DataExposureService dataExposureService;
+ @Autowired
+ private DataExposureRepository dataExposureRepository;
+
+ /**
+ * serve API.
+ *
+ * @param serviceId serviceId
+ * @param requestMap requestMap
+ * @param bindingResult bindingResult
+ * @param response response
+ * @return message that application is started
+ * @throws IOException
+ * @throws SQLException
+ *
+ */
+ @PostMapping("/{serviceId}")
+ @ResponseBody
+ @ApiOperation(value = "Datalake Data Exposure Service.")
+ public HashMap<String, Object> serve(@PathVariable String serviceId, @RequestBody Map<String, String> requestMap,
+ BindingResult bindingResult, HttpServletResponse response) throws IOException, SQLException {
+ log.info("Going to start Datalake Data Exposure Service ... requestMap=" + requestMap);
+ HashMap<String, Object> ret = new HashMap<>();
+ ret.put("request", requestMap);
+ DataExposure dataExposure = dataExposureService.getDataExposure(serviceId);
+ String sqlTemplate = dataExposure.getSqlTemplate();
+ StringSubstitutor sub = new StringSubstitutor(requestMap);
+ String query = sub.replace(sqlTemplate);
+ log.info("Going to start Datalake Data Exposure Service ... query=" + query);
+ // https://prestodb.io/docs/current/installation/jdbc.html
+ String url = String.format("jdbc:presto://dl-presto:8080/%s/%s", dataExposure.getDb().getPrestoCatalog(),
+ dataExposure.getDb().getDatabase());
+ Properties properties = new Properties();
+ properties.setProperty("user", "test");
+ // properties.setProperty("password", "secret");
+ // properties.setProperty("SSL", "true");
+ Connection connection = DriverManager.getConnection(url, properties);
+ Statement stmt = connection.createStatement();
+ ResultSet rs = stmt.executeQuery(query);
+ ResultSetMetaData meta = rs.getMetaData();
+ int columnCount = meta.getColumnCount();
+ ArrayList<HashMap<String, Object>> result = new ArrayList<>();
+ int count = 0;
+ while (rs.next()) {
+ HashMap<String, Object> entry = new HashMap<>();
+ for (int i = 1; i <= columnCount; i++) {
+ String label = meta.getColumnLabel(i);
+ Object value = rs.getObject(i);
+ entry.put(label, value);
+ log.info(label + "\t" + value);
+ }
+ result.add(entry);
+ count++;
+ }
+ ret.put("result", result);
+ ret.put("result_count", count);
+ return ret;
+ }
+
+ /**
+ * queryAllDataExposure API.
+ *
+ * @return data exposure config list
+ *
+ */
+ @GetMapping("")
+ @ResponseBody
+ @ApiOperation(value = "Datalake Data Exposure list")
+ public List<DataExposureConfig> queryAllDataExposure() {
+ return dataExposureService.queryAllDataExposure();
+ }
+
+ /**
+ * query API.
+ *
+ * @param id id
+ * @param response HttpServletResponse
+ * @return DataExposureConfig
+ * @throws IOException
+ *
+ */
+ @GetMapping("/{id}")
+ @ResponseBody
+ @ApiOperation(value = "Get Detail of DataExposure")
+ public DataExposureConfig queryAllDataExposure(@PathVariable String id, HttpServletResponse response)
+ throws IOException {
+ log.info("Get Detail of DataExposure Starting.....");
+ DataExposure oldDataExposure = dataExposureService.getDataExposureById(id);
+ if (oldDataExposure == null) {
+ sendError(response, 400, "DataExposure not found, ID: " + id);
+ return null;
+ } else {
+ log.info("ResponseBody......" + oldDataExposure.getDataExposureConfig());
+ return oldDataExposure.getDataExposureConfig();
+ }
+ }
+
+ /**
+ * delete Kfaka API.
+ *
+ * @param id id
+ * @param response HttpServletResponse
+ * @throws IOException
+ *
+ */
+ @DeleteMapping("/{id}")
+ @ResponseBody
+ @ApiOperation(value = "delete a dataExposure.")
+ public void deleteKafka(@PathVariable String id, HttpServletResponse response) throws IOException {
+ DataExposure oldDataExposure = dataExposureService.getDataExposureById(id);
+ if (oldDataExposure == null) {
+ sendError(response, 400, "DataExposure not found, ID: " + id);
+ } else {
+ dataExposureRepository.delete(oldDataExposure);
+ response.setStatus(204);
+ }
+ }
+
+ /**
+ * Create a DataExposure.
+ *
+ * @param dataExposureConfig dataExposureConfig
+ * @param result BindingResult
+ * @param response HttpServletResponse
+ * @return DataExposureConfig
+ * @throws IOException
+ *
+ */
+ @PostMapping("")
+ @ResponseBody
+ @ApiOperation(value = "Create a DataExposure.")
+ public PostReturnBody<DataExposureConfig> createDataExposure(@RequestBody DataExposureConfig dataExposureConfig,
+ BindingResult result, HttpServletResponse response) throws IOException {
+ if (result.hasErrors()) {
+ sendError(response, 400, "Error parsing DataExposureConfig : " + result.toString());
+ return null;
+ }
+ DataExposure oldDataExposure = dataExposureService.getDataExposureById(dataExposureConfig.getId());
+ if (oldDataExposure != null) {
+ sendError(response, 400, "DataExposure is exist " + dataExposureConfig.getId());
+ return null;
+ } else {
+ DataExposure dataExposure = null;
+ try {
+ dataExposure = dataExposureService.fillDataExposureConfiguration(dataExposureConfig);
+ } catch (Exception e) {
+ log.debug("FillDataExposureConfiguration failed", e.getMessage());
+ sendError(response, 400, "Error FillDataExposureConfiguration: " + e.getMessage());
+ return null;
+ }
+ dataExposureRepository.save(dataExposure);
+ log.info("Kafka save successed");
+ return mkPostReturnBody(200, dataExposure);
+ }
+ }
+
+ /**
+ * Update a DataExposure.
+ *
+ * @param dataExposureConfig dataExposureConfig
+ * @param result BindingResult
+ * @param id id
+ * @param response HttpServletResponse
+ * @return DataExposureConfig
+ * @throws IOException
+ *
+ */
+ @PutMapping("/{id}")
+ @ResponseBody
+ @ApiOperation(value = "Update a DataExposure.")
+ public PostReturnBody<DataExposureConfig> updateDataExposure(@RequestBody DataExposureConfig dataExposureConfig,
+ BindingResult result, @PathVariable String id, HttpServletResponse response) throws IOException {
+ if (result.hasErrors()) {
+ sendError(response, 400, "Error parsing DataExposureConfig : " + result.toString());
+ return null;
+ }
+ DataExposure oldDataExposure = dataExposureService.getDataExposureById(id);
+ if (oldDataExposure == null) {
+ sendError(response, 400, "DataExposure not found: " + id);
+ return null;
+ } else {
+ try {
+ dataExposureService.fillDataExposureConfiguration(dataExposureConfig, oldDataExposure);
+ } catch (Exception e) {
+ log.debug("FillDataExposureConfiguration failed", e.getMessage());
+ sendError(response, 400, "Error FillDataExposureConfiguration: " + e.getMessage());
+ return null;
+ }
+ dataExposureRepository.save(oldDataExposure);
+ log.info("DataExposure update successed");
+ return mkPostReturnBody(200, oldDataExposure);
+ }
+ }
+
+ private PostReturnBody<DataExposureConfig> mkPostReturnBody(int statusCode, DataExposure dataExposure) {
+ PostReturnBody<DataExposureConfig> retBody = new PostReturnBody<>();
+ retBody.setStatusCode(statusCode);
+ retBody.setReturnBody(dataExposure.getDataExposureConfig());
+ return retBody;
+ }
+
+ private void sendError(HttpServletResponse response, int sc, String msg) throws IOException {
+ log.info(msg);
+ response.sendError(sc, msg);
+ }
+}
diff --git a/components/datalake-handler/des/src/main/java/org/onap/datalake/des/domain/DataExposure.java b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/domain/DataExposure.java
new file mode 100644
index 00000000..c1347022
--- /dev/null
+++ b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/domain/DataExposure.java
@@ -0,0 +1,76 @@
+/*
+* ============LICENSE_START=======================================================
+* ONAP : Data Extraction Service
+* ================================================================================
+* Copyright 2020 China Mobile
+*=================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END=========================================================
+*/
+
+package org.onap.datalake.des.domain;
+
+import com.fasterxml.jackson.annotation.JsonBackReference;
+import lombok.Getter;
+import lombok.Setter;
+import javax.persistence.*;
+
+import org.onap.datalake.des.dto.DataExposureConfig;
+import org.onap.datalake.feeder.domain.Db;
+
+/**
+ * Domain class representing DataExposure
+ *
+ * @author Kai Lu
+ */
+@Getter
+@Setter
+@Entity
+@Table(name = "data_exposure")
+public class DataExposure {
+
+ @Id
+ @Column(name = "`id`")
+ private String id;
+ @Column(name = "`sql_template`", nullable = false)
+ private String sqlTemplate;
+ @Column(name = "`note`")
+ private String note;
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "db_id", nullable = false)
+ @JsonBackReference
+ private Db db;
+
+ public DataExposure() {
+ }
+
+ public DataExposure(String id, String sqlTemplate) {
+ this.id = id;
+ this.sqlTemplate = sqlTemplate;
+ }
+
+ /**
+ * getDataExposureConfig.
+ *
+ * @return data exposure config
+ *
+ */
+ public DataExposureConfig getDataExposureConfig() {
+ DataExposureConfig dataExposureConfig = new DataExposureConfig();
+ dataExposureConfig.setId(getId());
+ dataExposureConfig.setSqlTemplate(getSqlTemplate());
+ dataExposureConfig.setNote(getNote());
+ dataExposureConfig.setDbId(getDb().getId());
+ return dataExposureConfig;
+ }
+}
diff --git a/components/datalake-handler/des/src/main/java/org/onap/datalake/des/dto/DataExposureConfig.java b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/dto/DataExposureConfig.java
new file mode 100644
index 00000000..86124f77
--- /dev/null
+++ b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/dto/DataExposureConfig.java
@@ -0,0 +1,36 @@
+/*
+* ============LICENSE_START=======================================================
+* ONAP : Data Extraction Service
+* ================================================================================
+* Copyright 2020 China Mobile
+*=================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END=========================================================
+*/
+
+package org.onap.datalake.des.dto;
+import lombok.Getter;
+import lombok.Setter;
+/**
+ * SON request body for DataExposure manipulation.
+ *
+ * @author Kai Lu
+ */
+@Getter
+@Setter
+public class DataExposureConfig {
+ private String id;
+ private String note;
+ private String sqlTemplate;
+ private Integer dbId;
+}
diff --git a/components/datalake-handler/des/src/main/java/org/onap/datalake/des/repository/DataExposureRepository.java b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/repository/DataExposureRepository.java
new file mode 100644
index 00000000..b77e5d29
--- /dev/null
+++ b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/repository/DataExposureRepository.java
@@ -0,0 +1,36 @@
+/*
+* ============LICENSE_START=======================================================
+* ONAP : Data Extraction Service
+* ================================================================================
+* Copyright 2020 China Mobile
+*=================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END=========================================================
+*/
+
+package org.onap.datalake.des.repository;
+
+import org.onap.datalake.des.domain.DataExposure;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ *
+ * DataExposure Repository
+ *
+ * @author Kai Lu
+ *
+ */
+
+public interface DataExposureRepository extends CrudRepository<DataExposure, String> {
+
+}
diff --git a/components/datalake-handler/des/src/main/java/org/onap/datalake/des/service/DataExposureService.java b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/service/DataExposureService.java
new file mode 100644
index 00000000..c7d642b5
--- /dev/null
+++ b/components/datalake-handler/des/src/main/java/org/onap/datalake/des/service/DataExposureService.java
@@ -0,0 +1,131 @@
+/*
+* ============LICENSE_START=======================================================
+* ONAP : Data Extraction Service
+* ================================================================================
+* Copyright 2020 China Mobile
+*=================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END=========================================================
+*/
+
+package org.onap.datalake.des.service;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.onap.datalake.des.domain.DataExposure;
+import org.onap.datalake.des.dto.DataExposureConfig;
+import org.onap.datalake.des.repository.DataExposureRepository;
+import org.onap.datalake.feeder.domain.Db;
+import org.onap.datalake.feeder.repository.DbRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Service for DataExposure
+ *
+ * @author Kai Lu
+ *
+ */
+@Service
+public class DataExposureService {
+
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+ @Autowired
+ private DataExposureRepository dataExposureRepository;
+ @Autowired
+ private DbRepository dbRepository;
+
+ /**
+ * getDataExposure.
+ *
+ * @param serviceId serviceId
+ *
+ * @return DataExposure
+ *
+ */
+ public DataExposure getDataExposure(String serviceId) {
+ Optional<DataExposure> ret = dataExposureRepository.findById(serviceId);
+ return ret.isPresent() ? ret.get() : null;
+ }
+
+ public List<DataExposureConfig> queryAllDataExposure() {
+ List<DataExposure> dataExposureList = null;
+ List<DataExposureConfig> dataExposureConfigList = new ArrayList<>();
+ dataExposureList = (List<DataExposure>) dataExposureRepository.findAll();
+ if (!dataExposureList.isEmpty()) {
+ log.info("DataExposureList is not null");
+ for (DataExposure dataExposure : dataExposureList) {
+ dataExposureConfigList.add(dataExposure.getDataExposureConfig());
+ }
+ }
+ return dataExposureConfigList;
+ }
+
+ /**
+ * getDataExposureById.
+ *
+ * @param id id
+ *
+ * @return data exposure
+ *
+ */
+ public DataExposure getDataExposureById(String id) {
+ Optional<DataExposure> ret = dataExposureRepository.findById(id);
+ return ret.isPresent() ? ret.get() : null;
+ }
+
+ /**
+ * fillDataExposureConfiguration.
+ *
+ * @param dataExposureConfig DataExposureConfig
+ *
+ * @return data exposure
+ *
+ */
+ public DataExposure fillDataExposureConfiguration(DataExposureConfig dataExposureConfig) {
+ DataExposure dataExposure = new DataExposure();
+ fillDataExposure(dataExposureConfig, dataExposure);
+ return dataExposure;
+ }
+
+ /**
+ * fillDataExposureConfiguration.
+ *
+ * @param dataExposureConfig DataExposureConfig
+ * @param dataExposure DataExposure
+ *
+ * @return data exposure
+ *
+ */
+ public void fillDataExposureConfiguration(DataExposureConfig dataExposureConfig, DataExposure dataExposure) {
+ fillDataExposure(dataExposureConfig, dataExposure);
+ }
+
+ private void fillDataExposure(DataExposureConfig dataExposureConfig, DataExposure dataExposure)
+ throws IllegalArgumentException {
+ dataExposure.setId(dataExposureConfig.getId());
+ dataExposure.setNote(dataExposureConfig.getNote());
+ dataExposure.setSqlTemplate(dataExposureConfig.getSqlTemplate());
+ if (dataExposureConfig.getDbId() == null)
+ throw new IllegalArgumentException("Can not find db_id in db, db_id: " + dataExposureConfig.getDbId());
+ Optional<Db> dbOptional = dbRepository.findById(dataExposureConfig.getDbId());
+ if (!dbOptional.isPresent())
+ throw new IllegalArgumentException("db_id is null " + dataExposureConfig.getDbId());
+ dataExposure.setDb(dbOptional.get());
+ }
+}
diff --git a/components/datalake-handler/des/src/main/resources/application.properties b/components/datalake-handler/des/src/main/resources/application.properties
new file mode 100644
index 00000000..c0997e78
--- /dev/null
+++ b/components/datalake-handler/des/src/main/resources/application.properties
@@ -0,0 +1,73 @@
+#####################App general
+server.port = 16810
+server.servlet.context-path = /datalake/v1
+
+#tolerate inconsistency when system crash, see PullThread.run()
+async=true
+
+#SSL global flag, if enabled, still need to check each individual DB SSL flag
+enableSSL=false
+
+#names for extra fields that DL adds to each record
+timestampLabel=datalake_ts_
+rawDataLabel=datalake_text_
+
+defaultTopicName=_DL_DEFAULT_
+
+#####################Spring connection to MariaDB for ORM
+#spring.jpa.hibernate.ddl-auto=update
+spring.jpa.hibernate.ddl-auto=none
+spring.jpa.show-sql=false
+
+#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.datasource.url=jdbc:mariadb://mariadb-galera:3306/datalake?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8
+spring.datasource.username=dl
+spring.datasource.password=dl1234
+
+
+#####################DMaaP
+dmaapZookeeperHostPort=message-router-zookeeper:2181
+dmaapKafkaHostPort=message-router-kafka:9092
+dmaapKafkaGroup=dlgroup44
+#dmaapKafkaLogin=admin
+#dmaapKafkaPass=admin-secret
+#dmaapKafkaSecurityProtocol=SASL_PLAINTEXT
+
+#in second
+dmaapKafkaTimeout=10
+dmaapKafkaExclude[0]=__consumer_offsets
+dmaapKafkaExclude[1]=__transaction_state
+#dmaapKafkaExclude[2]=msgrtr.apinode.metrics.dmaap
+#check for new topics , in millisecond
+dmaapCheckNewTopicInterval=10000
+
+kafkaConsumerCount=3
+
+#####################Elasticsearch
+elasticsearchType=doc
+
+#####################HDFS
+hdfsBufferSize=4096
+#how often we flush stall updates, in millisecond
+hdfsFlushInterval=30000
+hdfsBatchSize=500
+
+#####################Logging
+logging.level.org.springframework.web=ERROR
+logging.level.com.att.nsa.apiClient.http=ERROR
+logging.level.org.onap.datalake=DEBUG
+
+#####################Verison
+datalakeVersion=0.0.1
+
+#####################KibanaDashboardImportApi
+kibanaDashboardImportApi=/api/kibana/dashboards/import?exclude=index-pattern
+
+#####################KibanaPort
+kibanaPort=5601
+
+#####################Elasticsearch Template API
+esTemplateMappingApi=/_template/
+
+#####################Elasticsearch port
+esPort=9200
diff --git a/components/datalake-handler/des/src/main/resources/logback.xml b/components/datalake-handler/des/src/main/resources/logback.xml
new file mode 100644
index 00000000..436f4f03
--- /dev/null
+++ b/components/datalake-handler/des/src/main/resources/logback.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+<!-- https://logback.qos.ch/manual/layouts.html -->
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>
+ %date |%-5level| [%20.20thread] %-40(%logger:%line) - %msg%n%ex{full}
+ </Pattern>
+ </layout>
+ </appender>
+
+ <logger name="org.onap.datalake" level="debug"
+ additivity="false">
+ <appender-ref ref="STDOUT" />
+ </logger>
+
+ <root level="error">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration> \ No newline at end of file
diff --git a/components/datalake-handler/des/src/main/resources/swagger.json b/components/datalake-handler/des/src/main/resources/swagger.json
new file mode 100644
index 00000000..017f04f8
--- /dev/null
+++ b/components/datalake-handler/des/src/main/resources/swagger.json
@@ -0,0 +1,67 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "description": "This page lists all the rest apis for DataLake.",
+ "version": "1.2.0-SNAPSHOT",
+ "title": "DataLake Exposure Service Rest APIs"
+ },
+ "host": "r-node-1:31157/datalake/v1/",
+ "basePath": "/",
+ "tags": [{
+ "name": "des-controller",
+ "description": "DES Controller"
+ }],
+ "paths": {
+ "/exposure/{serviceId}": {
+ "post": {
+ "tags": ["des-controller"],
+ "summary": "Datalake Data Exposure Service.",
+ "operationId": "serveUsingPOST",
+ "consumes": ["application/json"],
+ "produces": ["application/json"],
+ "parameters": [{
+ "in": "body",
+ "name": "requestMap",
+ "description": "requestMap",
+ "required": true,
+ "schema": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ }
+ }, {
+ "name": "serviceId",
+ "in": "path",
+ "description": "serviceId",
+ "required": true,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ },
+ "201": {
+ "description": "Created"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ },
+ "404": {
+ "description": "Not Found"
+ }
+ },
+ "deprecated": false
+ }
+ }
+ }
+} \ No newline at end of file