Сейчас мы хотели бы пойти дальше и показать, как можно загружать данные в базу данных из внешнего сервиса. При этом будут показаны некоторые тонкости при работе с trial облаком, связанные с требованиями изоляции пользователей в рамках одной trial системы.
Итак, что мы имеем. Первое — доступ к панели управления нашего облака по адресу https://account.hanatrial.ondemand.com/cockpit
Второе — созданный экземпляр платформы на SAP HANA под названием helloworldtrial.
Третье — установленную среду разработки Eclipse с плагином для SAP HANA Cloud и с созданным подключением к helloworldtrial:
Что мы хотим сделать: создать таблицу в базе данных SAP HANA и загрузить туда данные из внешнего источника. Для наших целей будем хранить информацию о текущей температуре воздуха в нескольких городах. Данные, для примера, будем брать с openweathermap.org.
Начнём с создания нового проекта. Запускаем наш Eclipse, открываем перспективу SAP HANA Development (Window > Open Perspective > Other...):
Создаём новый проект XS приложения, указав его название (File > New > Project… > SAP HANA Cloud):
Далее нам требуется выполнить стандартные шаги по выбору workspace’а и пакета. Внимание! Для нашего примера важно выбрать пакет, соответствующий нашему экземпляру облачной системы, вида pXXXXXXXXtrial.helloworldtrial. Где pXXXXXXXXtrial — имя пользователя в облачной системе:
И укажем наш главный файл со скриптом, который и будет выполнять всю работу — get_weather.xsjs:
Контроль доступа к пакету. Файл .xsaccess
С помощью файла .xsaccess мы указываем свойства нашего XS приложения (например, требуемая авторизация для исполнения скрипта и т.д.). Заменим содержимое этого файла на:
{
"exposed" : true,
"default_file" : "get_weather.xsjs"
}
Свойство exposed показывает, что данное XS приложение может быть выполнено на сервере из URL. Свойство default_file указывает главный исполняемый файл приложения; это позволит нам запустить его напрямую из панели управления (cockpit), не дописывая имя файла.
Теперь активируем наше приложение для проверки того, что на данном этапе все шаги были выполнены правильно. Для этого щёлкнем правой кнопкой мыши на нашем проекте во вкладке Project Explorer и в контекстном меню выберем Team > Activate.
Перезапустим панель управления в веб браузере нажав обновить (F5); иначе наше XS приложение не отображается в списке:
Щёлкнем на URL нашего XS приложения:
Должно открыться новое окно с содержимым “Wrong content type request use application/json”. Удостоверившись, что наша заготовка запускается, мы можем двигаться дальше.
Создание таблицы в базе данных
Создадим таблицу в базе данных, которая будет содержать столбцы: дата и время, наименование населённого пункта и текущую температуру воздуха.
Есть несколько способов создать таблицу в системе — с помощью интерактивного дизайнера, SQL скрипта или .hdbtable файла.
Самый быстрый способ — запустить на выполнение скрипт, подставив имя нашей схемы. Идём на вкладку Systems и запускаем SQL консоль для нашего облака:
Запускаем такой скрипт, подставив имя нашей схемы NEO_:
create column table "NEO_<<<>>>"."T_WEATHER"(
"ID" INTEGER GENERATED ALWAYS AS IDENTITY (MINVALUE 0 START WITH 0 INCREMENT BY 1),
"FORECAST_TMSTMP" TIMESTAMP NOT NULL ,
"LOCATION" NVARCHAR(50) NOT NULL,
"TEMPERATURE" REAL NOT NULL,
"TIMESTMP" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY ("ID"));
Обратим внимание на то, что мы создаём таблицу с колоночным хранением. А также неявно создаём т.н. sequence, который генерирует последовательность целых чисел и, при создании записей в таблице, сохраняет их в атрибуте ID.
Обновив каталог NEO_, увидим нашу таблицу:
Роль пользователя БД. Файл .hdbrole
В бесплатной trial системе у пользователя есть весьма ограниченный набор прав. Это касается, в частности, авторизации на изменение объектов в каталоге и управления пользовательскими аккаунтами. Поэтому в trial системе есть набор процедур в схеме “HCP”, которые позволяют пользователю управлять правами на созданные им объекты.
Для записи и чтения данных таблицы T_WEATHER нам потребуется новая роль. Добавим файл типа .hdbrole в наш проект (в главном меню File > New > Other…):
назовём его weather_access:
Заменим содержимое этого файла на следующий фрагмент, а затем активируем файл:
role p<<<>>>trial.helloworldtrial.TryWeather::weather_access {
catalog sql object "NEO_<<<>>>>"."T_WEATHER": SELECT, UPDATE, INSERT;
}
Заменим p<<<>>>trial на имя вашего пользователя. Вместо схемы NEO_<<<>>>> необходимо вставить наименование своей схемы, которую мы сохранили при создании таблицы. А теперь начинается магия, связанная с тем, что наше облако в триал режиме создаёт множество пользователей на одной системе. И для разделения прав доступа у этих пользователей весьма ограниченные привилегии.
Для того чтобы наш системный пользователь получил роль weather_access, мы должны выполнить системную процедуру.
Запустим SQL консоль и в ней выполним такой скрипт:
call "HCP"."HCP_GRANT_ROLE_TO_USER"('p<<<>>>trial .helloworldtrial.TryWeather::weather_access', 'p<<<>>>');
call "HCP"."HCP_GRANT_SELECT_ON_ACTIVATED_OBJECTS";
После изменения и активации файла .hdbrole необходимо выполнить:
call "HCP"."HCP_GRANT_ACTIVATED_ROLES";
Основной скрипт. Файл .xsjs
Итак, у нас есть заготовка XS скрипта и таблица в базе данных, для которой мы добавили разрешение на запись и чтение данных. В эту таблицу мы будем записывать данные о текущей погоде.
Пример URL для получения текущих данных о погоде в Москве: http://api.openweathermap.org/data/2.5/weather?q=Moscow,ru&units=metric.
Полученные данные в виде JSON объекта содержат, в том числе, информацию о температуре воздуха в формате unix timestamp. Тэг “dt”:
{
...
"dt " : 1430318471,
"id " : 524901,
"name " : "Moscow ",
"cod " : 200
}
Мы извлечём данные о погоде и запишем их в таблицу.
var CONST_ROOT_PACKAGE = "<<<pXXXXXtrial>>>";
var CONST_NEO_SCHEMA = "<<<NEO_XXXXXXXXXXXXXXXX>>>";
function getCurrentWeather(city_name) {
var destination_package = "helloworldtrial.TryWeather";
var destination_name = "o_weather";
var destPackagePath = CONST_ROOT_PACKAGE + "." + destination_package;
var dest = $.net.http.readDestination(destPackagePath, destination_name);
var client = new $.net.http.Client();
var req = new $.web.WebRequest($.net.http.GET, "?q=" + city_name
+ "&units=metric");
client.request(req, dest);
var response = client.getResponse();
var weather_data = JSON.parse(response.body.asString(),
function(key, value) {
if (key === "dt") {
return new Date(value * 1000);
}
return value;
});
return [ weather_data.dt, city_name, weather_data.main.temp ];
}
function storeData(data_receiving_time, city, temp) {
var conn = $.db.getConnection();
var stmt = conn
.prepareStatement("INSERT INTO \""
+ CONST_NEO_SCHEMA
+ "\".T_WEATHER (FORECAST_TMSTMP,LOCATION,TEMPERATURE) VALUES (?,?,?)");
stmt.setTimestamp(1, data_receiving_time);// время получения данных о погоде OpenWeatherMap
stmt.setString(2, city);
stmt.setFloat(3, temp);
var rs = stmt.executeQuery();
rs.close();
stmt.close();
conn.commit();
conn.close();
}
function processRequest() {
var cityNames = [ "Moscow,ru", "Saint Petersburg,ru", "Novosibirsk,ru",
"Volgograd,ru", "Krasnoyarsk,ru" ];
var body = "";
var cityName, i;
var dt;
var city;
var temp;
var out_vals;
try {
for (i = 0; i < cityNames.length; i++) {
cityName = cityNames[i];
out_vals = getCurrentWeather(cityName);
dt = out_vals[0];
city = out_vals[1];
temp = out_vals[2];
storeData(dt, city, temp);
body += "Данные сохранены.\nДата: " + dt + "\nГород: " + city
+ "\nТемпература: " + temp + " C\n\n";
}
$.response.setBody(body);
$.response.contentType = "text/plain";
$.response.status = $.net.http.OK;
} catch (e) {
$.response.contentType = "text/plain";
$.response.status = $.net.http.INTERNAL_SERVER_ERROR;
$.response.setBody(e.toString());
}
}
processRequest();
Данный код использует т.н. destination для вызова внешнего API.
А доступ к базе данных из Javascript осуществляется через объект соединения в пространстве имён $.db:
var conn = $.db.getConnection();
var stmt = conn.prepareStatement("INSERT INTO <<table>> (FORECAST_TMSTMP,LOCATION,TEMPERATURE) VALUES (?,?,?)");
Доступ к внешнему URL. Файл .xshttpdest
Добавим новый объект типа .xshttpdest с названием o_weather в наш проект:
И заменим содержимое этого файла на:
host = "api.openweathermap.org";
port = 80;
description = "current weather";
useSSL = false;
pathPrefix = "/data/2.5/weather";
authType = none;
useProxy = true;
proxyHost = "proxy-trial";
proxyPort = 8080;
timeout = 5000; // in milliseconds
Сохраним и активируем этот объект.
Теперь в панели управления HCP на вкладке с XS приложениями мы увидим новый элемент в панели Destinations:
Кликнув на URL нашего приложения, запустим скрипт и получим приблизительно такой результат на экране:
Теперь в Eclipse проверим, что данные были сохранены в таблице. Для этого по правой кнопке мыши на таблице T_WEATHER выберем Open Data Preview:
И убедимся, что новая запись в базе данных была создана:
Итого
Итак, в данной статье мы создали XS приложение, которое умеет получать данные из внешнего источника (в нашем случае — веб сервис) и сохранять их в таблице в базе данных HANA. Кроме того, мы создали два специальных объекта: определение ролей (weather_access.hdbrole) и определение канала для доступа к внешнему веб-сервису (o_weather.xshttpdest). А также вызвали хранимые процедуры для того, чтобы в trial системе дать разрешения на доступ к таблице базы данных.
Комментарии (8)
ReGloom
14.05.2015 10:32После всего прочитанного, у меня один вопрос: «зачем?». Я понимаю, конечно, что это лишь пример использования, но в чем преимущество/плюшки/удобство?
Xyzyx Автор
15.05.2015 11:09Очень правильный вопрос. Основная плюшка — это in-memory база данных в облаке, с соответствующими сервисами для интеграции всего этого хозяйства в инфраструктуру предприятия. То есть, на SAP HANA Platform мы можем 1) построить хранилище данных на SAP HANA 2) создать приложения для real-time аналитики 3) интегрировать это хранилище в инфраструктуру предприятия 4) разрабатывать приложения для визуализации данных (XS-приложения, Java и HTML5).
avz
18.05.2015 17:35А дебажить это как? Зашел в Web-based Development Workbench. Поставил точку. Запустил. В отладчик не вывалился.
Xyzyx Автор
29.05.2015 19:06Отладка в веб интерфейсе на англ. описана здесь: help.hana.ondemand.com/help/frameset.htm?a6357286d6a14880bd9af42672e2c75e.html
Если кратко, то:
- Получаем имя DEV_ пользователя. Для этого выполняем SQL скрипт SELECT current_user FROM dummy на нашей базе.
- Даём разрешение на отладку. Переходим на s8hanaxs.hanatrial.ondemand.com/sap/hana/xs/debugger и этому DEV_ юзеру даём разрешение, скажем, на год.
- В браузере открываем URL нашего приложения. В Google Chrome нажимаем F12 и получаем id сессии:
- Открываем веб интерфейс, ставим брейкпоинты. Открываем xsjs файл и нажимаем на кнопку 'Settings' на панели инструментов:
Появится окно с полем выбора xs сессии. В нём необходимо выбрать значение, полученное из браузера на предыдущем шаге.
- Получаем имя DEV_ пользователя. Для этого выполняем SQL скрипт SELECT current_user FROM dummy на нашей базе.
Xyzyx Автор
29.05.2015 19:11Мне больше по душе всё же отладка из Eclipse. Но настройка несколько нетривиальна.
Для отладки из Eclipse необходимо выполнить следующие действия:
- Получить имя DEV_ пользователя. Для этого выполняем SQL скрипт SELECT current_user FROM dummy на нашей базе.
- Дать разрешение на отладку. Переходим на s8hanaxs.hanatrial.ondemand.com/sap/hana/xs/debugger и этому DEV_ юзеру даём разрешение, скажем, на год.
- Создать Debug конфигурацию в эклипсе: XS JavaScript: Manual Session. Это делается в меню Run > Debug Configurations. Нужно выбрать в раскрывающемся списке наш cloud сервер и снять флажок с Stored Procedures.
- В браузере открываем URL, оканчивающийся на наш .xsjs файл. Пример: s8hanaxs.hanatrial.ondemand.com/p12345678trial/helloworldtrial/TryWeather/get_weather.xsjs.
(Внимание! Отладчик не схватывает сессию, если мы в браузере откроем URL вида https: //s8hanaxs.hanatrial.ondemand.com/p12345678trial/helloworldtrial/TryWeather/)
- Из Eclipse запустить отладку (Run > Debug As… наша конфигурация), поставив точки остановки. Появится маленькое окно с выбором пользователя и сессии. Необходимо выбрать пользователя p1234567 (не DEV_ !) и соответствующую сессию.
- Перезагрузить страницу браузера с нашим XS-приложением (см. пункт 4).
- Получить имя DEV_ пользователя. Для этого выполняем SQL скрипт SELECT current_user FROM dummy на нашей базе.
avz
30.05.2015 12:01Спасибо за инструкции по включению отладки. Еще не пробовал, но сразу видно — «сделано людьми для людей» =\
ЗЫ.
MaxFactor
А геморроя то сколько. Уже 10 лет прошло, как я когда то программировал под SAP, а интерфейс они делают все такой же не удобный.
Xyzyx Автор
В основном это связано с тем, что в trial системе у юзера очень ограниченные админские права. Поэтому и требуются все эти вызовы хранимых процедур, чтобы дать разрешения пользователю(-ям) доступ к таблицам и вьюшкам.
Интерфейс среды разработки и окон плагина — в стиле Eclipse. Со всеми плюсами и минусами. Интерфейс панели управления (cockpit), скажем, прост и лаконичен. А вот до интерфейса приложений для конечного пользователя (вкладка HTML5 Applications) мы в наших публикациях ещё не дошли.