poniedziałek, lipca 15, 2013
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
wtorek, czerwca 18, 2013
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
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.
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.
@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
piątek, czerwca 07, 2013
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
::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
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
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
}
}
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.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();
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();
ś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
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.
java -Xms512m -Xmx512m -Dcrdi.config=C:/CRDI/crdi.client.properties -jar crdi.jar
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
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();
}
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-ąęćśń
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
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.
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),
"
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:
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)
- 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.
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.
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.
Subskrybuj:
Posty (Atom)





































































