Blog do projektu Open Source JavaHotel

środa, 27 kwietnia 2016

Oracle, DB2, Hive, data migration

Introduction
I created a simple program to migrate data from Oracle, MS/SQL and any JDBC reachable relational database to DB2 and Hive.  The source code is available here.
For DB2, the program extracts data from the source database and prepares SQL script to load data to DB2 database. A script should be executed on the DB2 host machine and all extracted data should be transferred there.
For Hive, the program creates a script with Hive table declaration based on the source database and Hive script to push extracted data into Hive.
Solution description
The solution is a combination of Java program and bash script. Can be executed on Linux system.
Eclipse project for Java part can be downloaded here. The jar file containing Java code extracting data from a source database is launched in wrapping bash script, it is not accessible directly.
The solution layout:
  • export.sh Main script
  • export.rc Environment variables
  • {db}.properties Property file referenced by CONNPROP variable in export.rc. Contains connection parameters.
  • jars Directory containing jar exported from Eclipse project with Java code
  • jdbc Directory containing all dependencies, particularly JDBC drivers appropriate for the database used.
  • log Log directory
Configuration, export.rc file
  • EXPORT_DIR Directory where extracted data are downloaded. 
  • LOGIR Log directory
  • LOADSQL File name for load data script created by the solution
  • CONNPROP Property file with JDBC connection details
Example

# EXPORT_DIR : directory where all export file are stored
EXPORT_DIR=/tmp/data
# log directory
LOGDIR=$PWD/log
# DB2 load script created
LOADSQL=$PWD/db2load.sql
# connection properties
CONNPROP=$PWD/oracleexp.properties
#CONNPROP=$PWD/mssqlexpdb.properties
#CONNPROP=$PWD/db2expdb.properties

Property file 
  • sourceurl
  • user
  • password
  • drivername
  • sourcedb  db2, mssql, oracle. It is important to specify oracle value for Oracle database. For some reason, Oracle JDBC driver does not report properly Oracle temporary table. In order to exclude temporary tables from data extraction process, a specific Oracle catalog view is referenced.
  • destdb db2 or hive. The default is db2. It is important to specify hive if data extracted is going to be consumed by Hive later on.
Example of property file for MS/SQL

sourceurl=jdbc:sqlserver://win7ms:49186;databaseName=AdventureWorks2012
user=test
password=secret
drivername=com.microsoft.sqlserver.jdbc.SQLServerDriver
sourcedb=mssql
destdb=hive # Data extraction for Hive
Example of property file for Oracle database
sourceurl=jdbc:oracle:thin:@rhelora:1521:hcidb
user=test
password=secret
drivername=oracle.jdbc.driver.OracleDriver
sourcedb=oracle
Example of property file for DB2
sourceurl=jdbc:db2://re64:50040/HCI:retrieveMessagesFromServerOnGetMessage=true;
user=db2inst1
password=db2inst1
drivername=com.ibm.db2.jcc.DB2Driver
sourcedb=db2
export.sh, main script description
Format
./export.sh {action} parameters related to {action}
listoftables
  • Parameters: list of schemas
  • Creates a list of tables extracted from source database and schemas. The list is stored in the table.list file. The list is later reused by extractfromlist action. The list can be reviewed and modified manually.
  • Example: ./export.sh listoftables DATA ACCOUNT
extracttable
  • Parameters: list of tables.
  • Extract data from tables specified. More than one table can be provided.
  • Example: ./export  extract.sh extracttable data.invoices data.lines account.customers
extractlist
  • No parameters
  • Extract data from tables found in table.list file. The table.list file can be created by listoftable action.
  • Example: extract.sh extractfromlist
extractschemas
  • No parameters
  • Extract list of schemas from a source database. The list is stored in schema.list file. This action is not connected with any other actions, can be used as a data discovery.
  • Example: ./export.sh extractschemas
extracthivetables
  • No parameters
  • Creates create.list script file containing Hive table CREATE commands. The table.list file contains a list of tables in source database. Look below for more details.
  • Example: ./export.sh extracthivetables
extracthivetable
  • Parameters: list of tables
  • Extract data from tables specified as the parameters. Data is going to be consumed by Hive later on. Important: in order to have data extracted properly destdb=hive parameter should be specified additionally in the property file.
  • Example: extract.sh extracthivetable Sales.CountryRegionCurrency Sales.CreditCard Sales.Currency
extracthivefromlist
  • No parameters
  • Extract data from all tables found in table.list file. Data are extracted in the format expected by Hive.
  • Example:  extract.sh extracthivefromlist
extractnumberofrecords
  • Parameters: output file name
  • Extract number of records for tables found in table.list file. CSV file is created, every line containing information related to a single table. The command can be used as a rough data migration verifier. Look below.
  • Example: extract.sh extractnumberofrecords number.db2
DB2 data loader
The solution does not have any support for database schema migration. To migrate database schema use free tool IBM Database Conversion  Workbench.
Exported data are downloaded to EXPORT_DIR directory (for instance /tmp/data). Together with data extraction a LOADSQL script is created with a sequence of DB2 LOAD command to load data into DB2 database. DB2 command line processor, db2, is used for data consumption.  An example of LOAD command prepared

LOAD FROM /tmp/data/sales_personal_data.txt
OF DEL
MODIFIED BY LOBSINFILE  CODEPAGE=1208  COLDEL~ ANYORDER  USEDEFAULTS CHARDEL"" DELPRIORITYCHAR
DUMPFILE=/tmp/data/dump/sales_personal_data.txt
MESSAGES /tmp/data/msg/sales_personal_data.txt
REPLACE INTO SALES.PERSONAL_DATA

Also, all LOB columns are migrated. If input table contains any LOB column, additional /tmp/data/{table name} directory is created and in this directory files containing data extracted from LOB columns are stored and LOAD command contains a clause to load LOB data from that directory.
Before starting loading process, all extracted data should be moved to the DB2 host machine, otherwise LOAD command fails.
A typical scenario for data migration from Oracle or MSSQL database to DB2
  1. Prepare property file containing connection data for Oracle database. The property file should contain sourcedb=oracle parameter
  2. Extract all schemas from Oracle database using ./export.sh extractschemas. Identify schema or schemas containing application data to be migrated.
  3. Extract list of tables using command ./export.sh listoftables. Verify and modify the list if necessary.
  4. Extract data from source database using ./export.sh exportfromlist command.
  5. Move extracted data and db2load.sql script to the DB2 host machine. Important: extracted data should be moved to the same directory. 
  6. Connect to DB2 instance and execute command: db2 -tf db2load.sql
  7. Verify the migration using ./extract.sh extractnumberofrecords command. Look below for details.
  8. If necessary, repeat the process for all tables or for a single table using ./export.sh extracttable command.
HIVE data loader
For HIVE not only data migration is implemented but also schema migration. A mapping between JDBC data types and Hive data types can be checked out in Java source code. Columns not compatible with any Hive data types, for an instance LOB columns, are ignored. Because data are extracted in CSV format, it is very important that Hive data table schema is synchronized with data extracted.
A typical scenario for data migration from MSSQL to Hive.
  1. Prepare property file with connection data for MS/SQL database. The property file should contain destdb=hive parameter.
  2. Extract all schemas from MS/SQL database using ./export.sh extractschemas. Identify schema or schemas containing application data to be migrated.
  3. Extract list of tables using command ./export.sh listoftables. Verify and modify the list if necessary.
  4. Identify all schemas, create necessary databases/schemas manually in hive.
  5. Prepare script to create Hive tables by executing ./export.sh extracthivetables.
  6. Move script to Hive host machine and run beeline -f create.list command.
  7. Extract data from source database using ./export.sh exportfromlist command.
  8. Move extracted data and db2load.sql script to the DB2 host machine. Important: extracted data should be moved to the same directory.
  9. Load data into Hive using beeline -f db2load.sql command
  10. If necessary, repeat the process for all tables or for a single table using ./export.sh extracttable command.
Data migration verification
./export.sh extractnumberofrecords action can be used as a rough verification if data migration did not fail. Assume that we have an access to DB2 instance.
  1. Make sure that table.list contains a list of all table to be migrated.
  2. Execute ./export.sh extractnumberofrecords number.oracle for Oracle source database.
  3. Prepare property file for DB2 connection. Modify export.rc configuration file.
  4. Execute ./export.sh extractnumberofrecords number.db2 for DB2 source database. The command should be executed over the same table.list file
  5. Execute db2 commands:
  6. db2 "create table oracle_table(tname varchar(2500),nor int)"
  7. db2 load client from $PWD/number.oracle of del MODIFIED BY COLDEL',' insert into oracle_table
  8. db2 "create table db2_table like oracle_table"
  9. db2 load client from $PWD/number.db2 of del MODIFIED BY COLDEL',' insert into db2_table
  10.  db2 "select cast (d.tname as char(30)),d.nor as db2,o.nor as oracle from db2_table d,oracle_table o where d.tname = o.tname and d.nor != o.nor"
The last command should select all tables where number of records does not match and requiring additional concern.

czwartek, 21 kwietnia 2016

Byliśmy na operze

22 marca byliśmy na wykonaniu Stabat Mater Gioacchino Rossiniego w Kościele Świętej Anny, podobało nam się bardzo. Stabat Mater jest jednym z dzieł Rossiniego powstałych po zaprzestaniu przez niego pisania oper w 1929 roku. Pracę nad tym dziełem zaczął w 1831 roku, ale, po różnych perturbacjach, ostateczna wersja powstała dopiero w 1841 roku. Stabat Mater to pobożny i posiadający długą tradycję katolicki hymn do Matki Bożej będący natchnieniem dla wielu kompozytorów przez stulecia. W Stabat Mater Rossiniego słychać wyraźnie, że autorem jest kompozytor oper, to dzieło dynamiczne, pełne pięknych melodii, emocji, radości i smutku, przykuwające uwagę od początku do końca. Wykonanie w Kościele Świętej Anny przez solistów, chór i orkiestrę Warszawskiej Opery Kameralnej wydobyło całe piękno tej kompozycji.

23 marca byliśmy także na przedstawieniu Salome Richarda Straussa w Teatrze Wielkim. Salome to dzieło trudno poddające się prostym ocenom, zaś niestandardowa inscenizacja Mariusza Trelińskiego tę złożoność dodatkowo pogłębia. Całkowicie zniknął starożytny kontekst, sceną jest współczesny, nowobogacki dom, w którym mieszka uwikłana w toksycznych relacjach rodzina, topiąca smutki i stresy w alkoholu. Słynny taniec siedmiu zasłon nie jest przesyconą erotyzmem wschodnią egzotyką, ale restrospektywną pantonimą, gdzie w siedmiu miniaktach odsłaniania jest ponura, rodzinna tragedia o molestowaniu dziecięcej Salome przez ojczyma, Heroda.  Jak w Hamlecie, gdzie przedstawienie teatralne odsłania królowi Klaudiuszowi własną zbrodnię. Salome w tej pantonimie ma założoną nieruchomą maskę, trauma wyryła na jej duszy niemożliwą do zatarcia ranę, jej życie uczuciowe zastygło w wyniku doznanej krzywdy, co ma tłumaczyć obsesyjne i prowadzące do śmierci dążenie do bliskości z prorokiem Jochanaanem. Sam prorok nie pojawia się na scenie, jest tylko głosem, nawet nie wiemy do końca czy to prawdziwa osoba czy tylko złowieszczy głos sumienia prześladujący głównych aktorów spektaklu. Dla Salome materializuje się jako muskularna sylwetka młodego mężczyzny, a potem odciętej głowy, dla Herodiady to nawracający koszmar nie pozwalający zapomnieć o popełnionym grzechu, jakim było kazirodcze małżeństwo z Herodem, zaś dla chwiejnego i miotającego się Heroda to niepewność, czy Jochanaam to prawdziwy prorok i łącznik z zewnętrznym światem dobra, od którego Herod oddalił się dawno temu, czy tylko oszczerca którego należy ściąć. Debata uczonych Żydów jest projekcją niepokoju Heroda próbującego rozwiązać tę rozterkę za pomocą teologicznej debaty mędrców. Ale debata nie przynosi żadnego rozstrzygnięcia, wprowadza tylko zapowiedź jeszcze jednego proroka, prawdziwego Mesjasza, który czyni cuda i wskrzesza zmarłych. Skoro ani alkohol ani uczeni mędrcy nie przynoszą uspokojenia, ukojeniem dla Heroda ma być taniec Salome, co prowadzi do tragicznego końca.
Sceny przenoszą nad od jednego ponurego epizodu do drugiego, wszystko przesycone jest księżycową, nierealistyczną poświatą, scenografia dynamicznie nadąża za obsesjami bohaterów przedstawienia. Prawdziwy dwór Heroda, gdzie pośliźnięcie się na krwi i znalezienie zwłok nie wywołuje nawet specjalnego zdziwienia, a wyłącznie chwilowy dyskomfort. Sam Herod jest ubrany tylko w szlafrok i bieliznę, zas Herodiada w sportowy dres. W końcowej scenie wszyscy pokryci się krwawymi plamami niczym na filmie Tarantino.
W przedstawieniu zagubił się tylko wątek tragicznej miłości Narrabotha do Salome, przechodzi bez echa.
Z inscenizacją współgra bardzo dobre wykonawstwo. Głowną postacią, która dźwiga całe przedstawienie od początku do końca jest Salome i w tej roli doskonale się sprawdzała Alex Penda. Także Jacek Laszczykowski jako zamroczony alkoholem i chwiejny Herod wypadł bardzo dobrze. To samo można powiedziec o pozostałych wykonawcach i orkiestrze.
Przedstawienie na pewno bardzo udane pod każdym względem, budzące niepokój i zostające w pamięci.

piątek, 25 marca 2016

Oracle -> DB2 migration, useful awk scripts

Introduction
Database migration is a painstaking process but by means of Oracle Compatible Feature migration from Oracle to DB2 can be done very easy. There is an excellent redbook explaining the process in more details. Although the complexity is reduced I created some useful awk scripts to support it.
While working on migration of SQL code it is very convenient to split all objects into separate files and in the case of any trouble to focus on a single file containing the object under scrutiny.
So I created a set of useful and simple awk scripts which make it easy. The source code is available here. It can be modified and extended according to needs.
Splitting Oracle source file
The following objects can be extracted and split into separate files: tables including indexes and constraints, foreign keys, packages headers, packages bodies, triggers, views, stored procedures outside packages, UDF, sequences and types.
The main script is obj.awk.
The launching sequence:
awk -v extracttype={value} -v objtype={value} -f obj.awk {input file(s)}
Two parameters are recognized: extracttype and objtype
objtype can have the following values
  • TABLE
  • VIEW
  • TRIGGER
  • PROCEDURE
  • FUNCTION
  • FOREIGN
  • TYPES
  • PACKAGE
  • PACKAGEBODY
  • SEQUENCE
extracttype can have the following values
  • TABLES
  • ALLOTHERS
  • LIST
 The following actions are triggered:
  • extracttype=TABLES, no objtype, all tables object are extracted
  • extracttype=ALLOTHERS, no objtype, all objects but tables are extracted
  • extracttype=LIST, objtype can have value or be ignored, only object names are listed
  • no extracttype, objtype=value, only objects pointed by objtype are extracted
Example
  awk -v extractype=TABLES -f obj.awk {input file}
All tables are extracted.

awk -v extracttype=LIST objtype=SEQUENCE -f obj.awk {input file}
All sequence names are printed.

awk -f objtype=PACKAGE -f obj.awk {input file}
All package headers are extracted.

Extracted objects are saved in the following directories
  • TABLE, tables
  • VIEW, views
  • TRIGGER, triggers
  • PROCEDURE, procedures
  • FUNCTION, functions
  • FOREIGN, foreign
  • TYPES, types
  • PACKAGE, packages
  • PACKAGEBODY, packagesbody
  • SEQUENCE, sequences
Extracted code modification
Although very little is supposed to be done to have Oracle SQL code running on DB2, sometimes small adjustments can make life easier.
The following awk scripts are executed on the fly against every extracted object.
  • TABLE, modiftable.awk
  • VIEW, modifview.awk
  • TRIGGER, modiftrigger
  • PROCEDURE, (none)
  • FUNCTION, (none)
  • FOREIGN, (none)
  • TYPES, modiftypes.awk
  • PACKAGE, modifpackage.awk
  • PACKAGEBODY, (none)
  • SEQUENCE, modifsequence.awk
An example of modification script for the sequence.
@include "fun.awk"

{
  line = gensub(/CREATE SEQUENCE/,"CREATE OR REPLACE SEQUENCE","g",$0)   
  line = gensub(/MAXVALUE\ +[0-9]+\ /,"NO MAXVALUE ","g",line)
  printline(line)
}
The modification scripts can be extended or modified as needed.

poniedziałek, 29 lutego 2016

BoaTester. Netezza PDA, testing

Introduction

 IBM PureData System Analytics, Netezza, is IBM warehouse solution for a huge volume of data. Netezza comes with a lot of tools, most commonly used is nzsql, command line tool. The nzsql command can be used as a typical REPL tool, for running ad-hoc queries and do managerial or administrative tasks and also a part of a broader solution, engine to run scripts and queries in batch mode. As it happens with development, a question arises how to test it, and, next step, how to create a suite of regression test to be sure that during maintenance, updates, bug fixing, the software still performs correctly

Problem 
Assume that we developed a script doing very important stuff inside big PDA appliance. It could be backuping, user and groups synchronization with external user maintenance system, like Active Directory or LDAP, vacuuming, refreshing, moving data between databases, loading and transforming external data. The script covers several use cases and should run over a different combination of data. The script should be tested after every fix or introducing a new feature. It is a good idea to have this task automated to avoid tedious and mundane manual testing. Every test should start with a predefined precondition and finish with expected result. If the current result matches the expected result then the test passes otherwise test fails. All setup and verify task can be done as a single SQL statement or a nzsql script in case of more complex setting. So what is necessary is a test harness allowing run aforementioned tasks in a simple way.
So what I need is a test harness allowing executing the following tasks in a simple way.
  • nzsql script
  • nzsql and single SQL statement
  • bash script
  • verification feature to determine whether the test passed or failed
Solution
I found that an extension of BoaTester framework provides the solution to the aforementioned problem. The whole add-on logic is contained in a single Python module. The source code is available here. Once installed and configured, it makes defining and adding new test scenarios very easy.
Technical description and usage example is available here.

niedziela, 31 stycznia 2016

Byliśmy na koncercie i operze

8 stycznia 2016 roku byliśmy na koncercie na Zamku Królewskim w wykonaniu orkiestry Warszawskiej Opery Kameralnej, ale wyszliśmy z mieszanymi uczuciami. Repertuar tworzyła muzyka barokowa, w pierwszej części utwory Vivaldiego, zaś w drugiej części dodatkowo muzyka Georga Philippa Telemanna. Co powodowało uczucie niedosytu u słuchaczy pięknej muzyki we wspaniałym wnętrzu Sali Wielkiej warszawskiego Zamku ? W pierwszej części wykonawcy wyraźnie się męczyli z instrumentami i partyturą, strona wykonawcza pozostawiała wiele do życzenia. Znacznie lepiej się słuchało w drugiej części, gdy artyści się rozgrzali. Wspaniale zwłaszcza zabrzmiał koncert na dwie altówki Telemana, brzmienie rzadziej spotykane. Także brawurowy koncert h-moll Vivaldiego na czworo skrzypiec ogromnie się podobał. Ale nierówny poziom wykonawczy zostawił nas z mieszanymi wrażeniami.

18 stycznia 2016 byliśmy na przedstawieniu mało popularnej opery Mozarta "Łaskawość Tytusa" w Teatrze Wielkim, podobało nam się ogromnie. Sam spektakl, w innym wykonaniu, można obejrzeć na Opera Platform.
"Łaskawość Tytusa" zawsze przedstawiała kłopot dla miłośników Mozarta, dla wielu najlepiej by było, gdyby Mozart do tej opery nigdy by nie usiadł. Jedni twierdzą, że kunszt kompozytora wzniósł się ponad statyczny i ociekający patosem tekst, inni uważają, że geniusz Mozarta poległ w starciu z tą materią, "nec Hercules contra plures". Najlepiej jednak zdanie wyrobić sobie samemu kupując bilety.
Mimo widocznych mielizn libretta kto kupił bilety na pewno nie żałował. Od strony muzycznej i wokalnej słuchało się znakomicie. Trochę słabo brzmiała Anna Bonitatibus w roli Sesta, chociaż dużo nadrabiała ekspresją aktorską. Doskonale wypadł majestatyczny i dostojny Charles Workman w tytułowej roli. Także ogromie się podobała Anna Bernacka śpiewająca jako Annio.
Trudny natomiast do odczytania był zamysł inscenizatorski, aczkolwiek od strony estetycznej i kolorystycznej oglądało się bardzo dobrze. Na scenie patrzyliśmy na współczesne wnętrze zamożnego domu, śpiewacy odczytują wiadomości na tabletach, rozmawiają przez komórki i wysyłają SMSy. Gdy ujawniany jest spisek przeciwko Tytusowi na scenie pojawiają się detektywi oznaczający ślady policyjnymi marketami.
Jednak takie współczesne odczytanie tekstu nie przydawało tutaj żadnego znaczenia, sprawiało wrażenie wystawiania pustych gadżetów. Namiętności targające bohaterami, miłość, namiętność, zdrada, przyjaźń, szlachetność, w osobie Vitelli przemawia żądza władzy, polityczne wyrachowanie, to wszystko brzmiało blado, tekst nie miał oparcia w inscenizacji.
Znacznie lepiej byłoby wrócić do źródeł, niech Tytus nadal będzie rzymskim cesarzem, Publio dowódcą Gwardii Pretorianów, Senat senatem a nie widownią telewizyjnego show, zaś w spisku na życie cesarza niech pojawią się Kapitol, spiskowcy, sztylety i zbuntowany rzymski motłoch. W ten sposób tekst miałby oparcie w inscenizacji i przedstawienie nabrałoby kolorów. Główna oś dramatyczna opery, konflikt między prawem nakazującym skazać zdrajcę na śmierć a wzdragającym się przed przemocą miłosierdziem, znacznie mocniej by wybrzmiał, gdyby tymi rozterkami był miotany cesarz, od którego podpisu na dokumencie zależy los milionów poddanych, niż gość pięciogwiazdkowego hotelu czy lokator luksusowego apartamentu.
Ale przedstawienie powinno być na pewno obowiązkowym punktem każdego melomana w Warszawie, trochę więc dziwiło, że widownia świeciła pustkami.

niedziela, 3 stycznia 2016

IBM InfoSphere Streams, PowerBI operator

Introduction
Previously I created a simple Java helper package to get access to PowerBI REST API. Now the time has come to develop Streams operator shipping data out  to PowerBI. Full source code is available here as StreamsStudio project.
Operator description, parameters
Operator (Java source code is available here) accepts seven parameters, five mandatory and two optional.
  • oauth_username
  • oauth_password
  • oauth_clientid: Parameters are required to receive access token to PowerBI. More details about PowerBI REST API and authentication is available here.
  • datasetName
  • tablename: Defines the table in PowerBI namespace.
  • flushsize: optional (default 1). Specifies the buffer size threshold before pushing data to PowerBI. Increasing the value improves performance but there is a delay between data is received and stored to PowerBI. The default is 1, every tuple is sent immediately to PowerBI. Value 0 has special meaning. Data is pushed to PowerBI when punctuation marker is received.
  • cleanfirstly: optional (default false). A logical parameter, if true then PowerBI table is truncated at the beginning.
Operator description, data loading
Pushing data is very simple, just create input streams reflecting the table structure in PowerBI and let the tuples flow. Only primitive data types are allowed (source).

private Map createTableSchema(OperatorContext context) throws PowerException {
  StreamSchema sche = context.getStreamingInputs().get(0).getStreamSchema();
  Map bischema = new HashMap();
  for (String name : sche.getAttributeNames()) {
   Type.MetaType ty = sche.getAttribute(name).getType().getMetaType();
   String biType = null;
   switch (ty) {
   case RSTRING:
   case USTRING:
   case ENUM:
    biType = PowerBI.STRING_TYPE;
    break;
   case INT8:
   case INT32:
   case INT64:
   case UINT8:
   case UINT16:
   case UINT32:
   case UINT64:
   case INT16:
    biType = PowerBI.INT64_TYPE;
    break;
   case DECIMAL128:
   case DECIMAL32:
   case DECIMAL64:
   case FLOAT32:
   case FLOAT64:
    biType = PowerBI.DOUBLE_TYPE;
    break;
   case BOOLEAN:
    biType = PowerBI.BOOL_TYPE;
    break;
   case TIMESTAMP:
    biType = PowerBI.DATETIME_TYPE;
    break;
   default:
    break;
   }
   if (biType == null)
    failure("Attribute " + name + " type " + ty.getLanguageType() + " not supported");
   log.log(TraceLevel.DEBUG, "Attribute " + name + " type " + ty.getLanguageType() + " mapped to " + biType);
   bischema.put(name, biType);
  }
  return bischema;
 }

Usage example

namespace application.test ;

use com.ibm.streams.powerbi::PowerBI ;

composite Main
{
 graph
  (stream
   Beacon_1_out0 as O) as Beacon_1 = Beacon()
  {
   logic
    state : mutable int32 i = 0 ;
   param
    iterations : 100 ;
    period : 0.1f ;
   output
    O : name = "Name " +(rstring)(i ++), num =(uint32)(i ++), flo = 1.23, log =
     i / 2 == 0 ? true : false, ti = createTimestamp(1000l, 100u) ;
  }

  () as PowerBI_2 = PowerBI(Beacon_1_out0)
  {
   param
    oauth_clientid : "22dfcddc-d5b4-4e8a-8358-1658fabdad0b" ;
    oauth_password : "Szczuja123" ;
    oauth_username : "szczodry@szczerbek.onmicrosoft.com" ;
    datasetName : "InfoS6" ;
    tablename : "table6" ;
    flushsize : 10 ;
  }

  () as Custom_3 = Custom(Beacon_1_out0 as inputStream)
  {
   logic
    onTuple inputStream :
    {
     println(inputStream) ;
    }

  }

}
More examples.
Loading modes
Three loading modes are supported. It is specified by parameter flushsize, described above.

  • flushsize = 1 (default). The incoming tuple is immediately pushed to PowerBI. Data is immediately available but there is a performance penalty.
  • flushsize > 1. Sending tuples to PowerBI is held off until the threshold is exceeded and then the whole buffer is shipped out in a single operation. It is more efficient but there is a gap between the time when data arrive and are available in PowerBI.
  • flushsize = 0. Tuples are buffered and sent to PowerBI when punctuation marker is received.
Dependency
In addition to PowerBI Java package, additional dependency is imposed by this library. It is specified by pom.xml file. The dependencies are stored in imp/lib directory in operator structure. The directory is defined by Lib annotation in operator body.

Additional remarks
  • Only one table can be defined per dataset. I cannot tell if it is a limitation of PowerBI or defect in PowerBI REST API
  • If a table does not exist then it is created during initialization of the operator. The table schema mirrors the schema of the operator input stream. Table schema cannot be changed later. If the table is already created then changing operator input stream schema later will cause a crash. 


czwartek, 31 grudnia 2015

New version of JavaHotel application

Introduction
The new version of JavaHotel application has been deployed. Demo version (U/P user/user), full source code is available here. A new option is a journal, a register of daily activities of the user. The journal gives the manager an insight into daily business and workload of all users.
Journal
Journal is available from upper menu: Administrator->Journal

A subset of user action is recorded, the actions related to changes in the status of database and reservation or some customer actions like sending a confirmation note or registering a payment.
Filtering
Also, a convenient journal filtering is implemented. Activities can be filtered on users and activity type.


Future

  • Graphic presentation of journal
  • More granular reporting related to the time of the day, answering the question: "at what time of the day some type of action is more frequent ?"