В предыдущей статье мы рассказали о том, как создать тестовый экземпляр облачной платформы (далее HCP — HANA Cloud Platform) и как связать среду разработки Eclipse с облаком на примере простейшего XS приложения (XS — eXtended Services).

Сейчас мы хотели бы пойти дальше и показать, как можно загружать данные в базу данных из внешнего сервиса. При этом будут показаны некоторые тонкости при работе с trial облаком, связанные с требованиями изоляции пользователей в рамках одной trial системы.

Итак, что мы имеем. Первое — доступ к панели управления нашего облака по адресу https://account.hanatrial.ondemand.com/cockpit

Второе — созданный экземпляр платформы на SAP HANA под названием helloworldtrial.
image

Третье — установленную среду разработки Eclipse с плагином для SAP HANA Cloud и с созданным подключением к helloworldtrial:
image

Что мы хотим сделать: создать таблицу в базе данных SAP HANA и загрузить туда данные из внешнего источника. Для наших целей будем хранить информацию о текущей температуре воздуха в нескольких городах. Данные, для примера, будем брать с openweathermap.org.

Начнём с создания нового проекта. Запускаем наш Eclipse, открываем перспективу SAP HANA Development (Window > Open Perspective > Other...):
image

Создаём новый проект XS приложения, указав его название (File > New > Project… > SAP HANA Cloud):
image

Далее нам требуется выполнить стандартные шаги по выбору workspace’а и пакета. Внимание! Для нашего примера важно выбрать пакет, соответствующий нашему экземпляру облачной системы, вида pXXXXXXXXtrial.helloworldtrial. Где pXXXXXXXXtrial — имя пользователя в облачной системе:
image

И укажем наш главный файл со скриптом, который и будет выполнять всю работу — get_weather.xsjs:
image

Контроль доступа к пакету. Файл .xsaccess
С помощью файла .xsaccess мы указываем свойства нашего XS приложения (например, требуемая авторизация для исполнения скрипта и т.д.). Заменим содержимое этого файла на:
{
     "exposed" : true,
     "default_file" : "get_weather.xsjs"
}

Свойство exposed показывает, что данное XS приложение может быть выполнено на сервере из URL. Свойство default_file указывает главный исполняемый файл приложения; это позволит нам запустить его напрямую из панели управления (cockpit), не дописывая имя файла.

Теперь активируем наше приложение для проверки того, что на данном этапе все шаги были выполнены правильно. Для этого щёлкнем правой кнопкой мыши на нашем проекте во вкладке Project Explorer и в контекстном меню выберем Team > Activate.

Перезапустим панель управления в веб браузере нажав обновить (F5); иначе наше XS приложение не отображается в списке:
image

Щёлкнем на URL нашего XS приложения:
image

Должно открыться новое окно с содержимым “Wrong content type request use application/json”. Удостоверившись, что наша заготовка запускается, мы можем двигаться дальше.

Создание таблицы в базе данных
Создадим таблицу в базе данных, которая будет содержать столбцы: дата и время, наименование населённого пункта и текущую температуру воздуха.
Есть несколько способов создать таблицу в системе — с помощью интерактивного дизайнера, SQL скрипта или .hdbtable файла.

Самый быстрый способ — запустить на выполнение скрипт, подставив имя нашей схемы. Идём на вкладку Systems и запускаем SQL консоль для нашего облака:
image

Запускаем такой скрипт, подставив имя нашей схемы 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_, увидим нашу таблицу:
image

Роль пользователя БД. Файл .hdbrole
В бесплатной trial системе у пользователя есть весьма ограниченный набор прав. Это касается, в частности, авторизации на изменение объектов в каталоге и управления пользовательскими аккаунтами. Поэтому в trial системе есть набор процедур в схеме “HCP”, которые позволяют пользователю управлять правами на созданные им объекты.

Для записи и чтения данных таблицы T_WEATHER нам потребуется новая роль. Добавим файл типа .hdbrole в наш проект (в главном меню File > New > Other…):
image

назовём его weather_access:
image

Заменим содержимое этого файла на следующий фрагмент, а затем активируем файл:
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<<<>>>');

Дополнительные встроенные процедуры в trial системе
Хотелось бы обратить внимание на то, что при изменении таблиц, представлений, процедур в каталоге trial системы необходимо в явном виде обновлять разрешения на доступ к этим объектам. Это делается вызовом процедуры:
call "HCP"."HCP_GRANT_SELECT_ON_ACTIVATED_OBJECTS";

После изменения и активации файла .hdbrole необходимо выполнить:
call "HCP"."HCP_GRANT_ACTIVATED_ROLES";


Основной скрипт. Файл .xsjs
Итак, у нас есть заготовка XS скрипта и таблица в базе данных, для которой мы добавили разрешение на запись и чтение данных. В эту таблицу мы будем записывать данные о текущей погоде.
Откуда можно получать данные о погоде
Для получения температуры мы используем API от openweathermap.org. Подробнее данный сервис был описан в статье на Хабре.
Пример 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
}


Мы извлечём данные о погоде и запишем их в таблицу.
Исходный код скрипта
Важно! Замените значения констант в первых двух строках на ваш логин (заканчивается на -trial) и наименование схемы базы данных NEO_:
image

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 в наш проект:
image

И заменим содержимое этого файла на:
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:
image

Кликнув на URL нашего приложения, запустим скрипт и получим приблизительно такой результат на экране:
image

Теперь в Eclipse проверим, что данные были сохранены в таблице. Для этого по правой кнопке мыши на таблице T_WEATHER выберем Open Data Preview:
image

И убедимся, что новая запись в базе данных была создана:
image

Итого
Итак, в данной статье мы создали XS приложение, которое умеет получать данные из внешнего источника (в нашем случае — веб сервис) и сохранять их в таблице в базе данных HANA. Кроме того, мы создали два специальных объекта: определение ролей (weather_access.hdbrole) и определение канала для доступа к внешнему веб-сервису (o_weather.xshttpdest). А также вызвали хранимые процедуры для того, чтобы в trial системе дать разрешения на доступ к таблице базы данных.

Комментарии (8)


  1. MaxFactor
    14.05.2015 03:47

    А геморроя то сколько. Уже 10 лет прошло, как я когда то программировал под SAP, а интерфейс они делают все такой же не удобный.


    1. Xyzyx Автор
      14.05.2015 11:53

      В основном это связано с тем, что в trial системе у юзера очень ограниченные админские права. Поэтому и требуются все эти вызовы хранимых процедур, чтобы дать разрешения пользователю(-ям) доступ к таблицам и вьюшкам.

      Интерфейс среды разработки и окон плагина — в стиле Eclipse. Со всеми плюсами и минусами. Интерфейс панели управления (cockpit), скажем, прост и лаконичен. А вот до интерфейса приложений для конечного пользователя (вкладка HTML5 Applications) мы в наших публикациях ещё не дошли.


  1. ReGloom
    14.05.2015 10:32

    После всего прочитанного, у меня один вопрос: «зачем?». Я понимаю, конечно, что это лишь пример использования, но в чем преимущество/плюшки/удобство?


    1. Xyzyx Автор
      15.05.2015 11:09

      Очень правильный вопрос. Основная плюшка — это in-memory база данных в облаке, с соответствующими сервисами для интеграции всего этого хозяйства в инфраструктуру предприятия. То есть, на SAP HANA Platform мы можем 1) построить хранилище данных на SAP HANA 2) создать приложения для real-time аналитики 3) интегрировать это хранилище в инфраструктуру предприятия 4) разрабатывать приложения для визуализации данных (XS-приложения, Java и HTML5).


  1. avz
    18.05.2015 17:35

    А дебажить это как? Зашел в Web-based Development Workbench. Поставил точку. Запустил. В отладчик не вывалился.


    1. Xyzyx Автор
      29.05.2015 19:06

      Отладка в веб интерфейсе на англ. описана здесь: help.hana.ondemand.com/help/frameset.htm?a6357286d6a14880bd9af42672e2c75e.html

      Если кратко, то:

      1. Получаем имя DEV_ пользователя. Для этого выполняем SQL скрипт SELECT current_user FROM dummy на нашей базе.

      2. Даём разрешение на отладку. Переходим на s8hanaxs.hanatrial.ondemand.com/sap/hana/xs/debugger и этому DEV_ юзеру даём разрешение, скажем, на год.
        image
      3. В браузере открываем URL нашего приложения. В Google Chrome нажимаем F12 и получаем id сессии:
        image
      4. Открываем веб интерфейс, ставим брейкпоинты. Открываем xsjs файл и нажимаем на кнопку 'Settings' на панели инструментов:
        image
        Появится окно с полем выбора xs сессии. В нём необходимо выбрать значение, полученное из браузера на предыдущем шаге.
        image




  1. Xyzyx Автор
    29.05.2015 19:11

    Мне больше по душе всё же отладка из Eclipse. Но настройка несколько нетривиальна.

    Для отладки из Eclipse необходимо выполнить следующие действия:

    1. Получить имя DEV_ пользователя. Для этого выполняем SQL скрипт SELECT current_user FROM dummy на нашей базе.

    2. Дать разрешение на отладку. Переходим на s8hanaxs.hanatrial.ondemand.com/sap/hana/xs/debugger и этому DEV_ юзеру даём разрешение, скажем, на год.
      image
    3. Создать Debug конфигурацию в эклипсе: XS JavaScript: Manual Session. Это делается в меню Run > Debug Configurations. Нужно выбрать в раскрывающемся списке наш cloud сервер и снять флажок с Stored Procedures.
    4. В браузере открываем URL, оканчивающийся на наш .xsjs файл. Пример: s8hanaxs.hanatrial.ondemand.com/p12345678trial/helloworldtrial/TryWeather/get_weather.xsjs.
      (Внимание! Отладчик не схватывает сессию, если мы в браузере откроем URL вида https: //s8hanaxs.hanatrial.ondemand.com/p12345678trial/helloworldtrial/TryWeather/)
    5. Из Eclipse запустить отладку (Run > Debug As… наша конфигурация), поставив точки остановки. Появится маленькое окно с выбором пользователя и сессии. Необходимо выбрать пользователя p1234567 (не DEV_ !) и соответствующую сессию.
      image
    6. Перезагрузить страницу браузера с нашим XS-приложением (см. пункт 4).
    .


  1. avz
    30.05.2015 12:01

    Спасибо за инструкции по включению отладки. Еще не пробовал, но сразу видно — «сделано людьми для людей» =\
    ЗЫ. image