poniedziałek, lipca 15, 2013

Adria by Dom Development




















































czwartek, lipca 11, 2013

Jak łamać tekst w HTML-u

-ms-word-break: break-all; word-break: break-all; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto;

środa, lipca 10, 2013

Warszawa z góry









wtorek, czerwca 18, 2013

Nówka sztuka nie śmigany


poniedziałek, czerwca 17, 2013

Provident chce być nowoczesny

Provident Polska chce udzielać małych kredytów na sms-a (limit jednorazowej pożyczki dla osoby fizycznej to 600 zł, miesięcznie 4000 zł, a rocznie 10 000 zł). Usługa byłaby realizowana w ramach systemu HalCash - klient Providenta po otrzymaniu sms-a mógłby wykorzystać znajdujący się tam kod referencyjny do wypłaty pieniędzy w bankomacie. System HalCash zintegrowany jest z bankomatami Euronet, BZ WBK oraz SKOK24. Provident Polska nie będzie współpracował bezpośrednio z HalCash, ale za pomocą BZ WBK. Patrząc na T-Mobile, PKO BP, a tera Providenta widać spory ruch na styku obszaru finansowego i mobilnego.

czwartek, czerwca 13, 2013

Cytaty z Godsona

http://politykier.pl/gid,15728760,gpage,3,img,15728797,kat,1025795,galeria.html

Global Future 2045: Mechanizm do wyłudzania pieniędzy?

http://www.theverge.com/2013/6/12/4422924/dmitry-itskov-wants-to-help-you-live-forever-by-swapping-your-body

Ciekawa dyskusja pod artykułem. Ickow jest właścicielem portali http://www.dni.ru/, http://russia.ru/, gazety internetowej http://www.vz.ru/, gry online http://dozory.ru/ oraz papierowego czasopisma. W branży medialnej dorobił się milionów.

Java EE 7: JMS 2.0

Co nowego w JMS 2.0 - Session.createSharedDurableConsumer pozwala na wielu konsumentów na tej samej subskrypcji durable. JMSDeliveryTime pozawala na opóźnione wysyłanie/dostarczanie komunikatów. Wysyłanie może być asynchroniczne z notyfikacją za pomocą interfejsu CompletionListener.

Java EE 7: Concurrency

Interfejs javax.enterprise.concurrent.ManagedExecutorService dostępny przez JDNI pozwala na zlecanie zadań przez kontener i wykonywanie ich po stronie serwera aplikacyjnego (submit(), execute(), invoke*(), schedule*()):

@Resource(name=”concurrent/LongRunningTasksExecutor”)
ManagedExecutorService mes;

Future reportFuture = mes.submit(new Runnable() { public void run() { /* do the work */} });

Zadania wysyłane do Executora mogą być indetyfikowalne dzięki użyciu metody getIdentityName() z interfejsu javax.enterprise.concurrent.ManagedTask.
Specyfikacja definiuje przykładowe typy Executorów w zależności od parametrów puli wątków, czasu życia zadania i polityki kolejkowania/powtarzania zadań:
Typical Thread Pool, Long-RunningTasks Thread Pool, Shared OLTP Thread Pool, Typical Timer. Executor obsługuje transakcje. Zadania moga korzystać z ContextService-u.
Logowanie w kontenerze może być realizowane przez Executor-a, co może znacząco przyspieszyć wykonywanie zadań, jeśli logowanie jest bazodanowe.

środa, czerwca 12, 2013

How to fix checkboxes in Grails Spring Security Management Console

Edit springSecurityUI.gsp, before the end of body add script block:

function fixInputs() {
 var container = document.getElementById("tab-roles");
 var inputs = container.getElementsByTagName("input");
 for (var i = 0; i < inputs.length; i++) {
  inputs[i].removeAttribute('style');   
 }
 var imgs = container.getElementsByTagName("img");
 for (var i = 0; i < imgs.length; i++) {
  imgs[i].setAttribute('style', 'display: none');  
 }
}
window.setTimeout(fixInputs, 500);

wtorek, czerwca 11, 2013

Jak z Mokotowa jedziesz to Parczew masz po lewej

piątek, czerwca 07, 2013

Nowe ekskluzywne osiedle Saska

Skypt do niezależnego budowania war-a Grails

@echo off
::SET SCRIPT_NAME=%~n0
::SET TARGET_ENV=%SCRIPT_NAME:make_=%
SET TARGET_ENV=prod0
SET CANON_ENV=%TARGET_ENV:0=%
SET CANON_ENV=%CANON_ENV:1=%
SET CANON_ENV=%CANON_ENV:2=%
echo *** Downloading Grails framework
echo ***
wget -c http://dist.springframework.org.s3.amazonaws.com/release/GRAILS/grails-2.2.2.zip >NUL
echo *** Unzipping Grails distro
echo ***
unzip -n grails-2.2.2.zip >NUL
SET PREV_HOME=%GRAILS_HOME%
SET PREV_PATH=%GRAILS_HOME%\bin
SET GRAILS_HOME=%~dp0
SET GRAILS_HOME=%GRAILS_HOME%grails-2.2.2
CALL SET CLEANED_PATH=%%PATH:%PREV_PATH%=%%
set PATH="%GRAILS_HOME%\bin";%CLEANED_PATH%
SET PREV_HOME=
SET PREV_PATH=
SET CLEANED_PATH=
echo *** I will make WAR file for %TARGET_ENV% (%CANON_ENV%) using %GRAILS_HOME%
echo ***
copy grails-app\conf\Config.groovy.%TARGET_ENV% grails-app\conf\Config.groovy
start /b /wait grails %CANON_ENV% war
pause

czwartek, czerwca 06, 2013

Bufetowa musi odejść

Bałtroczyk przedstawia

poniedziałek, czerwca 03, 2013

EMS planetary pattern


EMS server holds its state and message structures in memory and therefore has a limit for maximal number of messages. Considering compiler options and memory alignment EMS server requires about 0,5KB per one JMS message. With EMS server using 4GB RAM you can have 8 mln messages.
When memory limit of EMS server is too low you can refactor your infrastructure with planetary pattern:
Applications have their local EMS instances with routing enabled towards master server and defined proxy queues:
billing.data@EMS-SERVER-MASTER store=$sys.failsafe,secure
billing.voice@EMS-SERVER-MASTER store=$sys.failsafe,secure
billing.premium@EMS-SERVER-MASTER store=$sys.failsafe,secure

Master server has limits forced on these queues:
billing.data@EMS-SERVER-MASTER store=$sys.failsafe,secure,maxmsgs=1000000
billing.voice@EMS-SERVER-MASTER store=$sys.failsafe,secure,maxmsgs=1000000
billing.premium@EMS-SERVER-MASTER store=$sys.failsafe,secure,maxmsgs=1000000

When you send messages to local server's queue and master server still has got free capacity - they are routed. When master's limit is reached messages are stored on local server - until master regained capacity.
With EMS planetary pattern you can get rid of EMS server memory limits. If client connects to EMS server via JNDI it can be transparently redirected to other server, so you can migrate easily from single server to planetary infrastructure. If connection factory config is taken from local JNDI you can add additional server behind local EMS without reconfiguring client.

niedziela, czerwca 02, 2013

Fail fast

Duże firmy mają tendencję do przedłużania projektów już skazanych na porażkę, pompowania w nie pieniędzy i dodawania zasobów mimo braku sensu kontynuowania projektu. Tymczasem pozwolenie na upadek projektu byłoby czasem oczekiwanym i pozytywnym działaniem. Jeśli projekt nie toczy się zgodnie z założeniami, to znaczy że był źle zdefiniowany. Lepiej jest zamknąć projekt i zacząć od nowa, oszczędzając pieniądze. Przeterminowany projekt oznacza zazwyczaj niespełnienie biznes planu i rynkowe fiasko. Metodyką przyjazną koncepcji fail fast jest Rational/Open Unified Process.

Tibco BusinessWorks 6.0 is coming

ActiveMatrix application server concept has failed as a product and Tibco is changing its focus back to BW. BW 6.0 at the component level will be OSGI based and will allow for custom plugins via stable and well defined interface. No hacking, no Java glue - you will be able to easily deliver needed functionalities. Adapters are gone, they are replaced by Java-based plugins. SAP activities will run at the component level (ouch, possible licensing issues). BW 6.0 beta is going through QA tests - it should be available by the end of year. BW 5.x will be long term supported.

środa, maja 29, 2013

Naturalny Rotterdam

poniedziałek, maja 27, 2013

How to make EMS-centric Tibco BW to be HA

Hihghly available means accessible and consistent. The concept is to synchronize EMS servers across data centers using global queues routing and use pair of them for service endpoints. For highly available transactions BW instances need to have shared object stores for Arjuna XA Transaction Manager.


More complex solution:

Complementary routes from local EMS instances are omitted for picture clarity. TM should not be local to App instance.

And simple solution:


piątek, maja 24, 2013

How to generate standalone GRAILS/GORM views

import java.util.Calendar
import org.codehaus.groovy.grails.web.servlet.DefaultGrailsApplicationAttributes;
import org.codehaus.groovy.grails.commons.*
import grails.gsp.PageRenderer
import grails.gsp.ExtendedPageRenderer

class StandaloneContentGenerator {

def PageRenderer groovyPageRenderer

def generateContent() {
  ...
  HashMap map = new HashMap()
  map.put(DefaultGrailsApplicationAttributes.CONTROLLER_NAME_ATTRIBUTE, 'logEntry')
  map.put(DefaultGrailsApplicationAttributes.APP_URI_ATTRIBUTE, 'http://host:port/App')

  def content = new ExtendedPageRenderer(groovyPageRenderer, map).render(view: "/logEntry/list",
model: [logEntryInstanceList: results, logEntryInstanceTotal: results.size,
"flash.message": 'Content generated'])
  return content
}
}

środa, maja 22, 2013

Początkowa faza implementacji serwera JMS

Provider potrafiący wysłać dane na kolejkę i odbierać z kolejki. Zawartość edukacyjna.

QInitialContext ctx = new QInitialContext();
ctx.setUrl("direct://C://temp");
QConnectionFactory connFactory = (QConnectionFactory) ctx.lookup("QueueConnectionFactory");
QueueConnection conn = (QueueConnection) connFactory.createConnection();
QueueSession sess = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
Queue q = sess.createQueue("test123");
QueueSender sender = sess.createSender(q);
int cnt = 0;
for (int i=0; i < 10; i++)
sender.send( sess.createTextMessage(System.currentTimeMillis() + "X" + ++cnt) );
QueueReceiver receiver = sess.createReceiver(q);
TextMessage m = null;
do {
m = (TextMessage) receiver.receive();
if (m!=null) {
System.out.println(m.getJMSMessageID() + ": " + m.getText());
}
}
while (m!=null);
sess.close();
conn.close();

Czemu ptaszki uciekły?

Jestem dłuuuuga

Reklama

Nowa Kia Ceed 130Km

Prezent komunijny według Tesco

środa, maja 15, 2013

Jak spróbować odzyskać niedawno skasowane pliki pod warunkiem, że jakiś proces ma je jeszcze otwarte

export FOPEN_PID=`lsof | grep sync-msgs.db | awk '{print $2}'`
cd /proc/$FOPEN_PID/fd
ls -al


lrwx------ 1 tibco tibco 64 Apr  9 00:13 8 -> /storage/tibco/tibco/cfgmgmt/ems/data/datastore/async-msgs.db (deleted)
lrwx------ 1 tibco tibco 64 Apr 11 17:36 80 -> socket:[123929714]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 81 -> socket:[122106504]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 82 -> socket:[105165735]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 83 -> socket:[104899617]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 85 -> socket:[104899618]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 86 -> socket:[122106507]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 87 -> socket:[122106512]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 88 -> socket:[115068666]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 89 -> socket:[123882138]
lrwx------ 1 tibco tibco 64 Apr  9 00:13 9 -> /storage/tibco/tibco/cfgmgmt/ems/data/datastore/meta.db (deleted)
lrwx------ 1 tibco tibco 64 Apr 11 17:36 90 -> socket:[124029587]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 91 -> socket:[117795240]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 92 -> socket:[123973925]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 93 -> socket:[124029595]
lrwx------ 1 tibco tibco 64 Apr 11 17:36 94 -> socket:[123973937]

[root@s12165 fd]# dd if=8 of=/storage/tibco/tibco/cfgmgmt/ems/data/datastore_async-msgs.db
9481645+0 records in
9481645+0 records out
4854602240 bytes (4.9 GB) copied, 44.7987 s, 108 MB/s

Shield pattern

Application is sensitive to input data. Certain combinations cause it to crash or do not behave correctly (for example: create record and do not perform rollback when processing fails). Create proxy before app and filter input data. Do not allow bad data to flow to app.

Cloud link pattern

Your infrastructure is located in two sites (maybe your company has divisions in different geographical locations). You would like to easily access services available in DC2 from local site in DC1 and vice versa. Without complex VPN and routing configuration. You can run two instances of Cloud Redirector (technology preview) on 2 machines - each in one DC.



This is a master configuration. Frontlink mapping contain mapping of transport TCP and UDP ports available in master's local network to services defined in slave's local network. Backlink mapping contain mapping of services exposed via CDRI to master's local network. Shared secret is used as a security key agreement between sites (also all data transferred between sites is encypted with dynamic key). Web App credentials are needed to access CRDI www interface.

Example of client config:
crdi.siteId=client
crdi.backlinkMapping=udp:7500=udp:127.0.0.255:7500,udp:7474=udp:127.0.0.255:7474,udp:7475=udp:127.0.0.255:7475
crdi.frontlinkMapping=40521=1521,udp:7500=udp:7500,udp:7474=udp:7474,udp:7475=udp:7475,7500=7500,7474=7474,7475=7475,7222=7222,8080=8080,40000=80
crdi.controlPort=32765
crdi.sibling=212.76.100.110:32768
crdi.transportPortRange=7000-9000,40000-41000
crdi.udpTransportPortRange=7000-9000,40000-41000
crdi.logLevel=TRACE
crdi.sharedSecret=passw0rd
crdi.webAppCredentials=admin:admin

java -Xms512m -Xmx512m -Dcrdi.config=C:/CRDI/crdi.client.properties -jar crdi.jar


wtorek, maja 14, 2013

Tibco BW HealthCheck pattern

It is possible for every BW component exposing services via HTTP or JMS to create HealthCheck process. It can be started with HTTP Receiver (no SOAPAction header) or JMS Receiver (Ping property used with JMS selector). Process should ping uderlying components or external systems and return success of failure status. Also it is possible to get current CPU/GC/MEM usage from JMX and Tibco BW processes statistics from Hawk. You open one URL and get detailed statistics from which you can check overal health of flows.


poniedziałek, maja 13, 2013

Czemu RedHat zarzucił Xen-a

Technologię Xen Source kupił Citrix, a RedHat koniecznie chciał być liderem aktywnie rozwijającym produkt do wirtualizacji - z możliwością definiowania własnych funkcjonalności, decydowaniu o planach wydawniczych, pełnym zarządzaniem kodem w ramach własnej firmy. W przypadku Xen-a nie miałby takiej kontroli. Dlatego decyzja o kontynuowaniu rozwiązania do wirtualizacji z KVM-em była jedyną słuszną. Klienci mający wykupiony support byli/są wspierani w migracji.

środa, maja 08, 2013

Ranczo rządzi

Poczta Polska - ostatni bastion socjalizmu

UKE zbadał terminowość doręczania przesyłek. Nadal jest źle, ale trochę lepiej. Są takie przypadki, że na zwykły list czeka się 6 dni albo dłużej (priorytetowy 4+).


wtorek, kwietnia 30, 2013

How get real JDBC connection in BW Java

com.tibco.plugin.java.JavaConnectionAccessor ac = (com.tibco.plugin.java.JavaConnectionAccessor) conn;
java.sql.Connection wrappedConn = ac.getDBConnection();
java.sql.PreparedStatement ps = null;
java.sql.Clob val_binary = null;
try {
    java.lang.reflect.Field connField = null;
    for (java.lang.reflect.Field f : wrappedConn.getClass().getDeclaredFields()) {
if (java.sql.Connection.class.isAssignableFrom(f.getType()))
connField = f;
    }
    if (connField==null)
throw new RuntimeException("Cannot get original JDBC connection from Tibco Wrapper");
    connField.setAccessible(true);
    java.sql.Connection oraConn = (java.sql.Connection) connField.get(wrappedConn);
    /* do the work */
}
catch (java.sql.SQLException sqle) {
sqle.printStackTrace();
ac.releaseConnection(sqle);
wrappedConn = null;
throw sqle;
}
catch (Throwable t) {
t.printStackTrace();
ac.releaseConnection();
wrappedConn = null;
throw new RuntimeException("Unexpected Java code error", t);
}
finally {
if (ps!=null) {
try {
ps.close();
}
catch (Exception e) {}
}
if (wrappedConn!=null)
ac.releaseConnection();
}

niedziela, kwietnia 28, 2013

Java file names encoding

public static void main(String[] args) throws IOException {
Path p1 = Files.newDirectoryStream(Paths.get("/home/user/jdk/test"))
.iterator().next();
System.out.println("API 1.7: "+p1.toUri().getPath());
System.out.println("API 1.7: "+p1.toFile().getAbsolutePath());
String p2 = new java.io.File("/home/user/jdk/test").list()[0];
System.out.println("API 1.4: "+p2);
}

user@user-Aspire-4530:~/workspace/TestApp/bin$ LC_ALL="pl_PL.cp1250" java -Dfile.encoding=utf8 TestApp
API 1.7: /home/user/jdk/test/gżegżółka-ąęćśń
API 1.7: /home/user/jdk/test/gżegżółka-ąęćśń
API 1.4: g��eg������ka-����������
user@user-Aspire-4530:~/workspace/TestApp/bin$ LC_ALL="pl_PL.cp1250" java -Dfile.encoding=cp1250 TestApp
API 1.7: /home/user/jdk/test/g�eg���ka-����
API 1.7: /home/user/jdk/test/gżegżółka-ąęćśń
API 1.4: g??eg??????ka-??????????
user@user-Aspire-4530:~/workspace/TestApp/bin$ LC_ALL="pl_PL.utf-8" java -Dfile.encoding=cp1250 TestApp
API 1.7: /home/user/jdk/test/g�eg���ka-����
API 1.7: /home/user/jdk/test/gżegżółka-ąęćśń
API 1.4: g�eg���ka-����
user@user-Aspire-4530:~/workspace/TestApp/bin$ LC_ALL="en_US" java -Dfile.encoding=utf8 TestApp
API 1.7: /home/user/jdk/test/gżegżółka-ąęćśń
API 1.7: /home/user/jdk/test/gżegżółka-ąęćśń
API 1.4: g��eg������ka-����������
user@user-Aspire-4530:~/workspace/TestApp/bin$ LC_ALL="en_US" java TestApp
API 1.7: /home/user/jdk/test/g?eg???ka-?????
API 1.7: /home/user/jdk/test/g??eg??????ka-??????????
API 1.4: g??eg??????ka-??????????

user@user-Aspire-4530:~/workspace/TestApp/bin$ LC_ALL="pl_PL.utf8" java -Dfile.encoding=utf8 TestApp
API 1.7: /home/user/jdk/test/gżegżółka-ąęćśń
API 1.7: /home/user/jdk/test/gżegżółka-ąęćśń
API 1.4: gżegżółka-ąęćśń

Why there are differences?

sun.nio.fs.UnixDirectoryStreamIterator creates String from bytes with default JVM encoding:

private Path readNextEntry() {
            assert Thread.holdsLock(this);

            for (;;) {
                byte[] nameAsBytes = null;

                // prevent close while reading
                readLock().lock();
                try {
                    if (isOpen()) {
                        nameAsBytes = readdir(dp);
                    }
                } catch (UnixException x) {
                    IOException ioe = x.asIOException(dir);
                    throw new DirectoryIteratorException(ioe);
                } finally {
                    readLock().unlock();
                }
...

File.list() is a native C/C++ method (suprise!):

JNIEXPORT jobjectArray JNICALL
Java_java_io_UnixFileSystem_list(JNIEnv *env, jobject this,
                                 jobject file)
{
    DIR *dir = NULL;
    struct dirent64 *ptr;
    struct dirent64 *result;
    int len, maxlen;
    jobjectArray rv, old;

    WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
        dir = opendir(path);
    } END_PLATFORM_STRING(env, path);
    if (dir == NULL) return NULL;

    ptr = malloc(sizeof(struct dirent64) + (PATH_MAX + 1));
    if (ptr == NULL) {
        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
        closedir(dir);
        return NULL;
    }

    /* Allocate an initial String array */
    len = 0;
    maxlen = 16;
    rv = (*env)->NewObjectArray(env, maxlen, JNU_ClassString(env), NULL);
    if (rv == NULL) goto error;

    /* Scan the directory */
    while ((readdir64_r(dir, ptr, &result) == 0)  && (result != NULL)) {
        jstring name;
        if (!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, ".."))
            continue;
        if (len == maxlen) {
            old = rv;
            rv = (*env)->NewObjectArray(env, maxlen <<= 1,
                                        JNU_ClassString(env), NULL);
            if (rv == NULL) goto error;
            if (JNU_CopyObjectArray(env, rv, old, len) < 0) goto error;
            (*env)->DeleteLocalRef(env, old);
        }
        name = JNU_NewStringPlatform(env, ptr->d_name);
...

JNIEXPORT jstring JNICALL
JNU_NewStringPlatform(JNIEnv *env, const char *str)
{
    jstring result;
    result = nativeNewStringPlatform(env, str);
    if (result == NULL) {
        jbyteArray hab = 0;
        int len;

        if (fastEncoding == NO_ENCODING_YET)
            initializeEncoding(env);

        if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
            return newString8859_1(env, str);
        if (fastEncoding == FAST_646_US)
            return newString646_US(env, str);
        if (fastEncoding == FAST_CP1252)
            return newStringCp1252(env, str);

        if ((*env)->EnsureLocalCapacity(env, 2) < 0)
            return NULL;

        len = (int)strlen(str);
        hab = (*env)->NewByteArray(env, len);
        if (hab != 0) {
            (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
            if (jnuEncodingSupported(env)) {
                result = (*env)->NewObject(env, JNU_ClassString(env),
                                           String_init_ID, hab, jnuEncoding);
            } else {
                /*If the encoding specified in sun.jnu.encoding is not endorsed
                  by "Charset.isSupported" we have to fall back to use String(byte[])
                  explicitly here without specifying the encoding name, in which the
                  StringCoding class will pickup the iso-8859-1 as the fallback
                  converter for us.
                 */
                jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
                                                    "", "([B)V");
                result = (*env)->NewObject(env, JNU_ClassString(env), mid, hab);
            }
            (*env)->DeleteLocalRef(env, hab);
            return result;
        }
    }
    return NULL;
}

Conclusions: When you get file names of everything other than native filesystem, you may have damaged strings. It they are not damaged, but in different UTF-8 representations you can translate them with Normalizer.

czwartek, kwietnia 25, 2013

Tibco Software Support is a failure

8 months of diagnosing  and fixing XA issue and... Tibco Software cannot fix XA transactions in their ESB stack. If you deal with money you shouldn't use EMS + BW, otherwise you will end up with inconsistent balances, stucked transactions, missing data and fatal manual recovery cases - everything without proper help from vendor. Leaving clients alone with serious problems can be the just that one argument to switch to different vendor. This bird won't fly. Where is 2 second advantage?

czwartek, kwietnia 18, 2013

Płatności mobilne

Dwa lata prac, więcej niż kilka milionów wydatków i 10000* użytkowników w 5 miesięcy - to płatności mobilne T-Mobile (PTC na chwilę obecną nie jest w stanie ustalić ilu jest realnych użytkowników płatności, 10000 to tylko liczba sprzedanych usług). 10000 użytkowników w niecałe 3 tygodnie i dalszy dynamiczny wzrost - to aplikacja IKO od PKO B.P. Czemu PTC odniosło taką porażkę a PKO sukces?

PTC:
  • wymagana dedykowana karta SIM z zapisaną aplikacją i kluczami kryptograficznymi
  • niewiele wspieranych telefonów z NFC, w zasadzie tylko Samsung Galaxy S3, skomplikowany dewelopment, brak własnych ekspertów
  • skomplikowana architektura systemu
  • specjaliści od bezpieczeństwa twierdzą, że NFC ma luki '0 day/in the wild'
  • usługa wymaga kooperacji z bankiem: Raiffeisen, mBank, Getin.
  • drogi abonament
  • wysokie koszty operatora (infrastruktura własna, T-Mobile DE, opłaty operatora transakcji Gemalto)
PKO:
  • aplikacja IKO na dowolna komórkę z Androidem, iOS-em, Blackberry (ale wymaga internetu)
  • bezpieczeństwo oparte na kryptografii i tokenach
  • usługa jest darmowa
  • można płacić w sklepach i robić wypłaty z bankomatów
  • można sprawdzić bieżący stan konta i historię wpływów/wydatków
Latem mało wygodnie jest nosić ze sobą portfel albo karty luzem, a komórkę ma się zawsze. PKO pokazuje, że jest bankiem otwartym na młodych ludzi i zależy im na wygodzie klientów.

Dla myWallet powinny zostać zrobione badania rynkowe: przepytanie grupy docelowej przez SMG/KRC co potencjalni klienci sądzą o usłudze, czy by chcieli jej używać, jakie widzą plusy a jakie minusy. Wyniki badania powinny zostać przeanalizowane i stanowić podstawę do nowej bardziej szczegółowej ankiety a potem warsztatów grupy testowej z makietą. Właścicieli biznesowi powinni wcześniej odrobić pracę domową jak wygląda proces kreacji produktu, wybrać do tego metodykę uwzględniającą strategiczną konieczność synergii między biznesem a NT/IT. Czy biznes plan był naciągany ze względu na naciski z Niemiec i wszystkie te rzeczy pominięto? Nie wiadomo. Jedno jest jednak pewne - każdy duży projekt powinien mieć dobrze sprawdzone uzasadnienie biznesowe.

czwartek, kwietnia 11, 2013

Massively parallel BW XML processing

1. Create Java Code parsing XML and finding appropriate nodes, with asynchronous requests creation and response handling:

Document doc = XmlHelper.getDocumentBuilder().parse(new InputSource(new StringReader(xml)));

List<Node> matchingParentNodes = XmlHelper.getNestedElementsByTagNs(doc, "http://namespace.example.com", "EntityNode");
int cnt = matchingParentNodes.size();
final CountDownLatch gate = new CountDownLatch(cnt);

for (Node node : matchingParentNodes) {
    final Message m = new Message();
    m.param1 = XmlHelper.getNodeValueNs(node, "Param1");
    m.cookie = node;
    m.requestReply(timeoutMillis, new MessageCallback() {
        @Override
        public void onMessage(Message resp) {
            Node owner = (Node) resp.cookie;
    XmlHelper.setNodeValueNs(owner, "Param2", resp.param2);
    gate.countDown();
        }
    });
}

gate.await(timeoutMillis, TimeUnit.MILLISECONDS);
if (gate.getCount() != 0)
    throw new RuntimeException("Not all subrequests "+gate.getCount()+" of "+matchingParentNodes.size()+" has been handled in given time "+timeoutMillis+"ms");

return XmlHelper.nodeToString(doc);

2. Java Event Starter reads Messages from LinkedBlockingQueue and handles single record.