Repository: metamodel-membrane Updated Branches: refs/heads/master 2d6fcaae1 -> 6f929c29c
Improved postman tests and logging. Fixes #11 Project: http://git-wip-us.apache.org/repos/asf/metamodel-membrane/repo Commit: http://git-wip-us.apache.org/repos/asf/metamodel-membrane/commit/6f929c29 Tree: http://git-wip-us.apache.org/repos/asf/metamodel-membrane/tree/6f929c29 Diff: http://git-wip-us.apache.org/repos/asf/metamodel-membrane/diff/6f929c29 Branch: refs/heads/master Commit: 6f929c29c80832fed57089365b1dfd0800cb89e9 Parents: 2d6fcaa Author: Kasper Sørensen <[email protected]> Authored: Sun Oct 1 10:54:57 2017 -0700 Committer: Kasper Sørensen <[email protected]> Committed: Sun Oct 1 10:54:57 2017 -0700 ---------------------------------------------------------------------- .../controllers/DataSourceController.java | 4 +- .../membrane/controllers/QueryController.java | 15 +- .../membrane/controllers/RestErrorHandler.java | 35 +- .../controllers/TableDataController.java | 14 +- .../membrane/controllers/TenantController.java | 7 + postman-tests/Membrane.postman_collection.json | 391 ++++++++++++++++++- .../metamodel/membrane/server/WebServer.java | 12 + 7 files changed, 437 insertions(+), 41 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/6f929c29/core/src/main/java/org/apache/metamodel/membrane/controllers/DataSourceController.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/membrane/controllers/DataSourceController.java b/core/src/main/java/org/apache/metamodel/membrane/controllers/DataSourceController.java index 1efcfed..0dea52e 100644 --- a/core/src/main/java/org/apache/metamodel/membrane/controllers/DataSourceController.java +++ b/core/src/main/java/org/apache/metamodel/membrane/controllers/DataSourceController.java @@ -90,7 +90,7 @@ public class DataSourceController { final String dataSourceIdentifier = dataSourceRegistry.registerDataSource(dataSourceId, properties); - logger.info("Created data source: {}/{}", tenantId, dataSourceIdentifier); + logger.info("{}/{} - Created data source", tenantId, dataSourceIdentifier); return get(tenantId, dataSourceIdentifier); } @@ -139,7 +139,7 @@ public class DataSourceController { final DataSourceRegistry dataSourceRegistry = tenantContext.getDataSourceRegistry(); dataSourceRegistry.removeDataSource(dataSourceName); - logger.info("Deleted data source: {}/{}", tenantId, dataSourceName); + logger.info("{}/{} - Deleted data source", tenantId, dataSourceName); return new DeleteDatasourceResponse().deleted(true).type("datasource").name(dataSourceName); } http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/6f929c29/core/src/main/java/org/apache/metamodel/membrane/controllers/QueryController.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/membrane/controllers/QueryController.java b/core/src/main/java/org/apache/metamodel/membrane/controllers/QueryController.java index 1fefa27..33a0567 100644 --- a/core/src/main/java/org/apache/metamodel/membrane/controllers/QueryController.java +++ b/core/src/main/java/org/apache/metamodel/membrane/controllers/QueryController.java @@ -29,6 +29,8 @@ import org.apache.metamodel.membrane.app.TenantContext; import org.apache.metamodel.membrane.app.TenantRegistry; import org.apache.metamodel.membrane.swagger.model.QueryResponse; import org.apache.metamodel.query.Query; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; @@ -39,10 +41,12 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping(value = { "/{tenant}/{dataContext}/query", - "/{tenant}/{dataContext}/q" }, produces = MediaType.APPLICATION_JSON_VALUE) +@RequestMapping(value = { "/{tenant}/{dataContext}/query", "/{tenant}/{dataContext}/q" }, + produces = MediaType.APPLICATION_JSON_VALUE) public class QueryController { + private static final Logger logger = LoggerFactory.getLogger(QueryController.class); + private final TenantRegistry tenantRegistry; @Autowired @@ -62,10 +66,11 @@ public class QueryController { final Query query = dataContext.parseQuery(queryString); - return executeQuery(dataContext, query, offset, limit); + return executeQuery(tenantContext, dataSourceName, dataContext, query, offset, limit); } - public static QueryResponse executeQuery(DataContext dataContext, Query query, Integer offset, Integer limit) { + public static QueryResponse executeQuery(TenantContext tenant, String dataSource, DataContext dataContext, + Query query, Integer offset, Integer limit) { if (offset != null) { query.setFirstRow(offset); @@ -74,6 +79,8 @@ public class QueryController { query.setMaxRows(limit); } + logger.info("{}/{} - Executing query: {}", tenant.getTenantName(), dataSource, query); + final List<String> headers; final List<List<Object>> data = new ArrayList<>(); http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/6f929c29/core/src/main/java/org/apache/metamodel/membrane/controllers/RestErrorHandler.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/membrane/controllers/RestErrorHandler.java b/core/src/main/java/org/apache/metamodel/membrane/controllers/RestErrorHandler.java index 1b5ec4d..4feab87 100644 --- a/core/src/main/java/org/apache/metamodel/membrane/controllers/RestErrorHandler.java +++ b/core/src/main/java/org/apache/metamodel/membrane/controllers/RestErrorHandler.java @@ -23,6 +23,8 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import javax.servlet.http.HttpServletRequest; + import org.apache.metamodel.membrane.app.exceptions.AbstractIdentifierNamingException; import org.apache.metamodel.membrane.app.exceptions.DataSourceAlreadyExistException; import org.apache.metamodel.membrane.app.exceptions.DataSourceNotUpdateableException; @@ -35,6 +37,8 @@ import org.apache.metamodel.membrane.app.exceptions.NoSuchTenantException; import org.apache.metamodel.membrane.app.exceptions.TenantAlreadyExistException; import org.apache.metamodel.membrane.controllers.model.RestErrorResponse; import org.apache.metamodel.query.parser.QueryParserException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; @@ -48,9 +52,10 @@ import org.springframework.web.bind.annotation.ResponseStatus; @ControllerAdvice public class RestErrorHandler { + private static final Logger logger = LoggerFactory.getLogger(RestErrorHandler.class); + /** - * Method binding issues (raised by Spring framework) - mapped to - * BAD_REQUEST. + * Method binding issues (raised by Spring framework) - mapped to BAD_REQUEST. * * @param ex * @return @@ -70,8 +75,8 @@ public class RestErrorHandler { final List<FieldError> fieldErrors = result.getFieldErrors(); final Map<String, Object> fieldErrorsMap = new LinkedHashMap<>(); for (FieldError fieldError : fieldErrors) { - fieldErrorsMap.put(fieldError.getObjectName() + '.' + fieldError.getField(), fieldError - .getDefaultMessage()); + fieldErrorsMap.put(fieldError.getObjectName() + '.' + fieldError.getField(), + fieldError.getDefaultMessage()); } final Map<String, Object> additionalDetails = new LinkedHashMap<>(); @@ -81,8 +86,8 @@ public class RestErrorHandler { if (!fieldErrorsMap.isEmpty()) { additionalDetails.put("field-errors", fieldErrorsMap); } - final RestErrorResponse errorResponse = new RestErrorResponse(HttpStatus.BAD_REQUEST.value(), - "Failed to validate request"); + final RestErrorResponse errorResponse = + new RestErrorResponse(HttpStatus.BAD_REQUEST.value(), "Failed to validate request"); if (!additionalDetails.isEmpty()) { errorResponse.setAdditionalDetails(additionalDetails); } @@ -117,8 +122,7 @@ public class RestErrorHandler { } /** - * DataSource not updateable exception handler method - mapped to - * BAD_REQUEST. + * DataSource not updateable exception handler method - mapped to BAD_REQUEST. * * @param ex * @return @@ -127,13 +131,12 @@ public class RestErrorHandler { @ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseBody public RestErrorResponse processDataSourceNotUpdateable(DataSourceNotUpdateableException ex) { - return new RestErrorResponse(HttpStatus.BAD_REQUEST.value(), "DataSource not updateable: " + ex - .getDataSourceName()); + return new RestErrorResponse(HttpStatus.BAD_REQUEST.value(), + "DataSource not updateable: " + ex.getDataSourceName()); } - + /** - * DataSource invalid exception handler method - mapped to - * BAD_REQUEST. + * DataSource invalid exception handler method - mapped to BAD_REQUEST. * * @param ex * @return @@ -142,8 +145,7 @@ public class RestErrorHandler { @ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseBody public RestErrorResponse processDataSourceNotUpdateable(InvalidDataSourceException ex) { - return new RestErrorResponse(HttpStatus.BAD_REQUEST.value(), "DataSource invalid: " + ex - .getMessage()); + return new RestErrorResponse(HttpStatus.BAD_REQUEST.value(), "DataSource invalid: " + ex.getMessage()); } /** @@ -168,7 +170,8 @@ public class RestErrorHandler { @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody - public RestErrorResponse processAnyException(Exception ex) { + public RestErrorResponse processAnyException(HttpServletRequest req, Exception ex) { + logger.error("{} {} - Unexpected error!", req.getMethod(), req.getRequestURI(), ex); final Map<String, Object> additionalDetails = new HashMap<>(); additionalDetails.put("exception_type", ex.getClass().getName()); return new RestErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getMessage(), additionalDetails); http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/6f929c29/core/src/main/java/org/apache/metamodel/membrane/controllers/TableDataController.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/membrane/controllers/TableDataController.java b/core/src/main/java/org/apache/metamodel/membrane/controllers/TableDataController.java index afbc37c..f31f690 100644 --- a/core/src/main/java/org/apache/metamodel/membrane/controllers/TableDataController.java +++ b/core/src/main/java/org/apache/metamodel/membrane/controllers/TableDataController.java @@ -19,6 +19,7 @@ package org.apache.metamodel.membrane.controllers; import java.math.BigDecimal; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -50,6 +51,8 @@ import org.apache.metamodel.query.SelectItem; import org.apache.metamodel.schema.Column; import org.apache.metamodel.schema.Table; import org.apache.metamodel.update.RowUpdationBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; @@ -68,6 +71,7 @@ import com.google.common.collect.Lists; "/{tenant}/{dataContext}/s/{schema}/t/{table}/d" }, produces = MediaType.APPLICATION_JSON_VALUE) public class TableDataController { + private static final Logger logger = LoggerFactory.getLogger(TableDataController.class); private final TenantRegistry tenantRegistry; @Autowired @@ -90,7 +94,7 @@ public class TableDataController { final Query query = dataContext.query().from(table).selectAll().toQuery(); - return QueryController.executeQuery(dataContext, query, offset, limit); + return QueryController.executeQuery(tenantContext, dataSourceName, dataContext, query, offset, limit); } @RequestMapping(method = RequestMethod.POST) @@ -107,6 +111,10 @@ public class TableDataController { final Table table = traverser.getTable(schemaId, tableId); + logger.info("{}/{}/s/{}/t/{} - Data update: {} updates, {} deletes, {} inserts", tenantContext.getTenantName(), + dataSourceName, schemaId, tableId, size(postDataReq.getUpdate()), size(postDataReq.getDelete()), + size(postDataReq.getInsert())); + final UpdateSummary result = dataContext.executeUpdate(new UpdateScript() { @Override public void run(UpdateCallback callback) { @@ -163,6 +171,10 @@ public class TableDataController { return response; } + private static int size(Collection<?> col) { + return col == null ? 0 : col.size(); + } + private void setWhere(WhereClauseBuilder<?> whereBuilder, Table table, List<WhereCondition> conditions) { for (WhereCondition condition : conditions) { final Column column = table.getColumnByName(condition.getColumn()); http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/6f929c29/core/src/main/java/org/apache/metamodel/membrane/controllers/TenantController.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/membrane/controllers/TenantController.java b/core/src/main/java/org/apache/metamodel/membrane/controllers/TenantController.java index 76197a1..e94983b 100644 --- a/core/src/main/java/org/apache/metamodel/membrane/controllers/TenantController.java +++ b/core/src/main/java/org/apache/metamodel/membrane/controllers/TenantController.java @@ -29,6 +29,8 @@ import org.apache.metamodel.membrane.app.TenantRegistry; import org.apache.metamodel.membrane.swagger.model.DeleteTenantResponse; import org.apache.metamodel.membrane.swagger.model.GetTenantResponse; import org.apache.metamodel.membrane.swagger.model.GetTenantResponseDatasources; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; @@ -41,6 +43,7 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping(value = "/{tenant}", produces = MediaType.APPLICATION_JSON_VALUE) public class TenantController { + private static final Logger logger = LoggerFactory.getLogger(TenantController.class); private final TenantRegistry tenantRegistry; @Autowired @@ -75,6 +78,8 @@ public class TenantController { final TenantContext tenantContext = tenantRegistry.createTenantContext(tenantName); final String tenantIdentifier = tenantContext.getTenantName(); + logger.info("{} - Created tenant", tenantIdentifier); + final GetTenantResponse resp = new GetTenantResponse(); resp.type("tenant"); resp.name(tenantIdentifier); @@ -87,6 +92,8 @@ public class TenantController { public DeleteTenantResponse deleteTenant(@PathVariable("tenant") String tenantName) { tenantRegistry.deleteTenantContext(tenantName); + logger.info("{} - Deleted tenant", tenantName); + final DeleteTenantResponse resp = new DeleteTenantResponse(); resp.type("tenant"); resp.name(tenantName); http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/6f929c29/postman-tests/Membrane.postman_collection.json ---------------------------------------------------------------------- diff --git a/postman-tests/Membrane.postman_collection.json b/postman-tests/Membrane.postman_collection.json index d8f0896..62e816f 100644 --- a/postman-tests/Membrane.postman_collection.json +++ b/postman-tests/Membrane.postman_collection.json @@ -2,12 +2,37 @@ "variables": [], "info": { "name": "Membrane", - "_postman_id": "084c91ce-fccc-8fc4-a3c4-1dc5d5b41388", + "_postman_id": "1265d16a-b1fd-26a4-7ea5-d2e4015df97e", "description": "", "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" }, "item": [ { + "name": "Get swagger file", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"title is Apache MetaModel Membrane\"] = jsonData.info.title === \"Apache MetaModel Membrane\";" + ] + } + } + ], + "request": { + "url": "{{baseUrl}}/swagger.json", + "method": "GET", + "header": [], + "body": {}, + "description": "" + }, + "response": [] + }, + { "name": "Create my-tenant", "event": [ { @@ -18,7 +43,10 @@ "tests[\"Status code is 200\"] = responseCode.code === 200;", "", "var jsonData = JSON.parse(responseBody);", - "tests[\"type is tenant\"] = jsonData.type === \"tenant\";" + "tests[\"type is tenant\"] = jsonData.type === \"tenant\";", + "", + "postman.setGlobalVariable(\"membrane_tenant\", jsonData.name);", + "" ] } } @@ -42,7 +70,7 @@ "response": [] }, { - "name": "Get my-tenant", + "name": "Get tenant info", "event": [ { "listen": "test", @@ -58,7 +86,7 @@ } ], "request": { - "url": "{{baseUrl}}/my-tenant", + "url": "{{baseUrl}}/{{membrane_tenant}}", "method": "GET", "header": [], "body": {}, @@ -67,7 +95,7 @@ "response": [] }, { - "name": "Create my-tenant/example-pojo", + "name": "Create data source - postgres", "event": [ { "listen": "test", @@ -78,13 +106,16 @@ "", "var jsonData = JSON.parse(responseBody);", "tests[\"type is datasource\"] = jsonData.type === \"datasource\";", - "tests[\"is updateable\"] = jsonData.updateable;" + "tests[\"is updateable\"] = jsonData.updateable;", + "", + "postman.setGlobalVariable(\"membrane_data_source\", jsonData.name);", + "" ] } } ], "request": { - "url": "{{baseUrl}}/my-tenant/example-pojo", + "url": "{{baseUrl}}/{{membrane_tenant}}/example-postgres", "method": "PUT", "header": [ { @@ -95,14 +126,14 @@ ], "body": { "mode": "raw", - "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}" + "raw": "{\n \"type\":\"jdbc\",\n \"url\": \"jdbc:postgresql://example-postgres/membrane\",\n \"username\": \"membrane\",\n \"password\": \"secret\"\n}" }, "description": "" }, "response": [] }, { - "name": "Create my-tenant/example-postgres", + "name": "Create data source - couchdb", "event": [ { "listen": "test", @@ -113,13 +144,16 @@ "", "var jsonData = JSON.parse(responseBody);", "tests[\"type is datasource\"] = jsonData.type === \"datasource\";", - "tests[\"is updateable\"] = jsonData.updateable;" + "tests[\"is updateable\"] = jsonData.updateable;", + "", + "postman.setGlobalVariable(\"membrane_data_source\", jsonData.name);", + "" ] } } ], "request": { - "url": "{{baseUrl}}/my-tenant/example-postgres", + "url": "{{baseUrl}}/{{membrane_tenant}}/example-couchdb", "method": "PUT", "header": [ { @@ -130,14 +164,14 @@ ], "body": { "mode": "raw", - "raw": "{\n \"type\":\"jdbc\",\n \"url\": \"jdbc:postgresql://example-postgres/membrane\",\n \"username\": \"membrane\",\n \"password\": \"secret\"\n}" + "raw": "{\n \"type\":\"couchdb\",\n \"hostname\": \"example-couchdb\",\n \"username\": \"membrane\",\n \"password\": \"secret\"\n}" }, "description": "" }, "response": [] }, { - "name": "Create my-tenant/example-couchdb", + "name": "Create data source - pojo", "event": [ { "listen": "test", @@ -148,13 +182,18 @@ "", "var jsonData = JSON.parse(responseBody);", "tests[\"type is datasource\"] = jsonData.type === \"datasource\";", - "tests[\"is updateable\"] = jsonData.updateable;" + "tests[\"is updateable\"] = jsonData.updateable;", + "", + "postman.setGlobalVariable(\"membrane_data_source\", jsonData.name);", + "postman.setGlobalVariable(\"membrane_schema\", \"Schema\");", + "postman.setGlobalVariable(\"membrane_table\", \"foo\");", + "" ] } } ], "request": { - "url": "{{baseUrl}}/my-tenant/example-couchdb", + "url": "{{baseUrl}}/{{membrane_tenant}}/example-pojo", "method": "PUT", "header": [ { @@ -165,14 +204,330 @@ ], "body": { "mode": "raw", - "raw": "{\n \"type\":\"couchdb\",\n \"hostname\": \"example-couchdb\",\n \"username\": \"membrane\",\n \"password\": \"secret\"\n}" + "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Get data source info", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"type is datasource\"] = jsonData.type === \"datasource\";", + "", + "// find the first non-information schema", + "var schemas = jsonData.schemas;", + "for (var i=0; i<schemas.length; i++) {", + " if (schemas[i].name !== \"information_schema\") {", + " postman.setGlobalVariable(\"membrane_schema\", schemas[i].name);", + " break;", + " }", + "}", + "" + ] + } + } + ], + "request": { + "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}" }, "description": "" }, "response": [] }, { - "name": "Delete my-tenant", + "name": "Get schema info", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"type is schema\"] = jsonData.type === \"schema\";", + "", + "// find the first non-information schema", + "var tables = jsonData.tables;", + "for (var i=0; i<tables.length; i++) {", + " postman.setGlobalVariable(\"membrane_table\", tables[i].name);", + " break;", + "}", + "" + ] + } + } + ], + "request": { + "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Get table info", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"type is table\"] = jsonData.type === \"table\";", + "", + "// find the first non-information schema", + "var columns = jsonData.columns;", + "for (var i=0; i<columns.length; i++) {", + " postman.setGlobalVariable(\"membrane_column\", columns[i].name);", + " break;", + "}", + "", + "postman.setGlobalVariable(\"membrane_column_count\", columns.length);", + "" + ] + } + } + ], + "request": { + "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Add table data", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"status is ok\"] = jsonData.status === \"ok\";", + "" + ] + } + } + ], + "request": { + "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}/d", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"insert\": [\n\t\t{\n\t\t\t\"bar\": 42,\n\t\t\t\"baz\": null\n\t\t}\n\t]\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Get table data", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"type is dataset\"] = jsonData.type === \"dataset\";", + "" + ] + } + } + ], + "request": { + "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}/d", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Query table data", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"type is dataset\"] = jsonData.type === \"dataset\";", + "" + ] + } + } + ], + "request": { + "url": { + "raw": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/q?sql=SELECT * FROM {{membrane_table}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "{{membrane_tenant}}", + "{{membrane_data_source}}", + "q" + ], + "query": [ + { + "key": "sql", + "value": "SELECT * FROM {{membrane_table}}", + "equals": true, + "description": "" + } + ], + "variable": [] + }, + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Get column info", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"type is column\"] = jsonData.type === \"column\";", + "" + ] + } + } + ], + "request": { + "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}/c/{{membrane_column}}", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Delete data source", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"type is datasource\"] = jsonData.type === \"datasource\";", + "tests[\"deleted is true\"] = jsonData.deleted;", + "" + ] + } + } + ], + "request": { + "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}", + "method": "DELETE", + "header": [], + "body": {}, + "description": "" + }, + "response": [] + }, + { + "name": "Delete tenant", "event": [ { "listen": "test", @@ -190,7 +545,7 @@ } ], "request": { - "url": "{{baseUrl}}/my-tenant", + "url": "{{baseUrl}}/{{membrane_tenant}}", "method": "DELETE", "header": [], "body": {}, http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/6f929c29/undertow/src/main/java/org/apache/metamodel/membrane/server/WebServer.java ---------------------------------------------------------------------- diff --git a/undertow/src/main/java/org/apache/metamodel/membrane/server/WebServer.java b/undertow/src/main/java/org/apache/metamodel/membrane/server/WebServer.java index 1643bd8..4e3d188 100644 --- a/undertow/src/main/java/org/apache/metamodel/membrane/server/WebServer.java +++ b/undertow/src/main/java/org/apache/metamodel/membrane/server/WebServer.java @@ -22,6 +22,7 @@ import java.io.File; import javax.servlet.ServletException; +import org.apache.metamodel.util.FileHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.context.ContextLoaderListener; @@ -47,6 +48,8 @@ public class WebServer { private static final int DEFAULT_PORT = 8080; public static void main(final String[] args) throws Exception { + prepareDataDirectoryIfNeeded(); + final String portEnv = System.getenv("MEMBRANE_HTTP_PORT"); final int port = Strings.isNullOrEmpty(portEnv) ? DEFAULT_PORT : Integer.parseInt(portEnv); @@ -57,6 +60,15 @@ public class WebServer { logger.info("Apache MetaModel Membrane server started on port {}", port); } + private static void prepareDataDirectoryIfNeeded() { + final String property = "DATA_DIRECTORY"; + if (System.getProperty(property) == null && System.getenv(property) == null) { + final String tempDirectory = FileHelper.getTempDir().getAbsolutePath() + "/membrane"; + logger.warn("No DATA_DIRECTORY defined, using {}", tempDirectory); + System.setProperty(property, tempDirectory); + } + } + public static void startServer(int port) throws Exception { final DeploymentInfo deployment = Servlets.deployment().setClassLoader(WebServer.class.getClassLoader()); deployment.setContextPath("");
