Až Vám zčerná obrazovka, přejděte na Linux!

Proč používat Linux
Zobrazují se příspěvky se štítkemITapikování. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemITapikování. Zobrazit všechny příspěvky

pátek 21. října 2011

Grails, Searchable plugin a org.hibernate.NonUniqueObjectException

Podařilo se mi při testování Searchable plugin získat org.hibernate.NonUniqueObjectException při Create operaci. Je to způsobeno chybou při vkládání do složeného indexu. Tvůrce pluginu s tím má nějaké potíže, takže je potřeba použít workaround: je potřeba během save() vypnout mirorring a občas pro jistotu reindexovat.

def searchableService
def save = {
def polozkaInstance = new Polozka(params)
searchableService.stopMirroring()
if (polozkaInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'polozka.label', default: 'Polozka'), polozkaInstance.id])}"
redirect(action: "edit", id: polozkaInstance.id)

}
else {
render(view: "create", model: [polozkaInstance: polozkaInstance])
}
searchableService.startMirroring()
}


Třeba to někomu pomůže.

pátek 23. září 2011

Generování PDF v grails - chybějící české znaky


PDF plugin do Grails je rychlé a šikovné řešení, ale, samozřejmě jako se vším, co udělají kluci v USA, neřeší korektně kódování. Takže je potřeba embedovat font, který obsahuje patřičné znaky. Zde je ukázka, jak to udělat.
Třeba to někomu pomůže.
<style>
    @page {
        size: 210mm 297mm;
    }
    @font-face {
        src: url(file:///c:/windows/fonts/arialuni.ttf);
        -fs-pdf-font-embed: embed;
        -fs-pdf-font-encoding: Identity-H;
    }
    body {
        font-family: "Arial Unicode MS", Arial, sans-serif;
    }
    </style>

sobota 12. března 2011

Jak málo někdy rozhoduje při souboji cechů

Za poslední dva dny jsme my v kofola_teamu na Shakes&Fidget zaznamenali tři naprosto rozdílné bitvy cechů.
První jsme prohráli velice těsně. Dobře si prohlédněte souboj druhého nejlepšího hráče protivníka a naše nejlepšího - Highlandera. Polomrtvá dá kritický zásah, který ubere víc než polovinu životů :-(
Tady je: http://www.youtube.com/watch?v=HTso6_ryqDU

Oproti tomu zase Highlander sám vymlátil téměř půlku cechu:

http://www.youtube.com/watch?v=lg1Bz8k--3E

A poslední je o tom, že když se spojí síly celého cechu, tam jdou vymlátit i daleko silnější soupeři: http://www.youtube.com/watch?v=z0g_i_S8cv0

sobota 5. března 2011

Onlajnovky a zamindrákované děti

Je zvláštní, jak "moderní" on-line hry zasáhly svět. Desítky různých her, desítky různých principů, a přitom vše o jednom. Chcete-li něčeho dosáhnout, musíte si zaplatit speciální bonusy.
Kde jsou staré dobré zlaté časy MUDů, neboli MultiUserBungeonů, jako byla Moria. Nedokážu si představit, že bych si kupoval lepší zbraně. Proto je zvláštní, že většinu hráčů tvoří děti.

Synovec, který hraje bůhvíco o mezihvězdných válkách, se mě z vážnou tváří zeptal, jestli si myslím, že by tuto hru hrál i takový stařík, který má, považte, třicet tři let! Bylo pro něj naprosto nepředstavitelné. Teprve když jsem mu připomněl, že já také občas pařím nějakou tu onlajnovku, zarazil se a řekl, že teda asi jo. A tyto děti podle mne tvoří také většinu platících účastníků. Podle mého průzkumu si to platí SMSkama z mobilu. A to buď tajně a nebo když jim přesvědčí dědečka či babičku.

Je to pěkný výchovný hnus, ale daleko horší vliv na ně má ona anonymita. Každý si hned myslí, že když nikdo neví, kdo on je, tak že si může dovolit urážet a být sprostý. A pak se to přenese do běžného života. Každopádně dnes nad ránem jsem si užil úžasný otřesný zážitek.

Jeden devítiletý kluk, říkejme mu Pepa Vařák, mně (účet Telcontar) a ještě jednomu důstojníkovi (říkejme mu dust) cechu kofola_team na S4.sfgame.cz, pod účtem josef120 napsal asi toto: "Pošli mi pozvánku"

Žádné prosím, please ani PLZ nebo můžu a tak. Prostě příkaz. Protože podmínka byla úroveň 60 a on měl jen 48, odespal jsem mu ve stejném stylu: "MUHAHAHAHAHÁÁÁÁÁ!!! AHAHAHAHA!!!!!"

Na to napsal: "Tak jo odešli mi tu pozvánku." A v dalším mailu přidal, že je houbičkář. Řekl jsem si, že ho přijmu, protože je cechu třeba každého houbičkáře (toho, kdo si kupuje bonusy (houbičky)), protože jenom za houbičky je možné vylepšovat vlastnosti cechu.

Součástí Shakes & Fidget je cechovní chat neboli kecátko. Když se přihlásil do cechu, rozvinula se na chatu následující debata:
:ahoj
Telcontar: cus
:čus
josef120: Ahoj čus cus co to jako má bejt?
: pozdrav?
josef120: Si mislíte že sem číňan? Debilové!
Telcontar: No nic

A dál to pokračovalo v podobném duchu. Mezi tím jsme si s mým prvním důstojníkem povídali, co si o něm myslíme. A protože ono kecátko umožňuje posílat zprávy taky samotnému hráči, psali jsme si to přímo v chatu a prokládali tím veřejnou komunikaci. Takže to v jednu chvíli vypadalo takto:

josef120: Jak se menuješ?
dust: A proč to chceš vědět?
josef120: si pičus? to je jasn. ja sem pepa v.
dust->Telcontar: Co si o něm myslíš?
Telcontar->dust: Asi pěkné pako.
dust-> Je to houbičkář?
dust: Aha. Můžeš mi říct, kolik je ti let?
Telcontar->dust: tvrdil že jo
josef120: devět a neser kreténe
dust: Myslel jsem si to. Víš o tom, že by tu někteří z nás mohli být tvoji taťkové? Tak by ses měl chovat slušně.
Telcontar->dust: Hmmm. Kolik hub z něho vytáhneme, než ho vykopneme? :-D
dust->Telcontar: :D Podívej se na jeho profil, já se zasmál, až jsem se za břicho popadal.
josef120: Pošuku!
Telcontar->dust: Tý brďo, on píše, že je pod ochranou hráče s levelem o jedna vyšším!
Telconar: josefe, kdy dodáš slibované houbičky a kolik?
dust->Telcontar: Dost dobrá otázka.
Telcontar->dust: Ty, ten hráč, pod kterého je ochranou, je asi on sám. Jmenuje se varak12...

A pak jsem dostal poštu od josef120:
žekni tim tvem pitomem hraču klidně tet.

A pak opustil cech.

neděle 13. února 2011

Jak nastavit GMail jako výchozí mailer pro mailto: v Google Chrome

Postupně přecházím na svět Google+Linux. Pořídil jsem si Android, na Ubuntu používám jako výchozí prohlížeč Google Chrome, poštu čtu na GMailu, Kalendář mám v Google Aps, dokumenty tam začínám mít také. Jenom mne pořád štvalo, že se mi při kliknutí na mailto: vždy spustí evolution místo otevření GMailu. Ale to je již minulostí.
Hledal jsem v nastavení, jestli mi to neumožní, nic. Trochu jsem Gůglil a našel jsem rozšíření, které to umí. Kde stažení je zde: https://chrome.google.com/extensions/detail/dgkkmcknielgdhebimdnfahpipajcpjn .
Instalace jednoduchá, funkcionalita perfetní.
Třeba to někomu pomůže.

pondělí 31. ledna 2011

První potkání s Grails

Tak jsem se po dlouhém odkládání konečně dostal k tomu vyzkoušet si Grails. Na tento framework jsem četl poměrně hodně chvalozpěvů, jak moc je to jednoduché v něm něco udělat, a tak jsem si říkal, že by to snad ani nemuselo být nijak složité.
Stáhl jsem si Grailsy a protože vím, že IntelliJ IDEA má pro Grailsy podporu, zkusil jsem bez jakékoli přípravy to zkusit rozjet.
To, že IDEA je naprosto fantastická, jsem věděl už dávno. Ale to, co jsem právě prožil, to je prostě fantazie.
  1. V prvé řadě vytvoříte Grailsový projekt. Tady není co zkazit, jenom odklikáte from scratch, název a cestu (tak jak jste zvyklí), jenom místo Java projektu zvolíte Grails.
  2. Otevře se Vám místo klasického stromečku Project stromeček GrailsView, které obsahuje logicky uspořádané objekty. V tuto chvíli jsem naprosto nevěděl, co dělat, i sáhl jsem po Gůglu a vygůglil tutoriál Getting Started with Grails od Scotta Davise a Jasona Rudolpha. Je zdarma ke stažení na infoq.com, ale vyžaduje registraci. Tam jsem se dočetl o tom, co je doménová třída, controller a view (skončil jsem na straně 27 u "Hello World")
  3. Přes pravé tlačítko na Domain classes jsem si vytvořil první doménovou třídu Race a nakopíroval do ní seznam atributů z tutoriálu.
  4. Klikl jsem na RaceController - Generate controller, čímž se vygeneroval zajímavě vypadající CRUD Controller.
  5. Klikl jsem na Race Views - Generate views, čímž se vygenerovaly čtyři soubory GSP.
  6. Ze srandy jsem klikl na Run. Otevřel se prohlížeč a v něm uvítací stránka Grailsů a v ní odkaz na RaceController.
  7. Klikl jsem na něj a BINGO! Otevřela se mi velice hezky vypadající jednoduchá, ale plnohodnotná webová aplikace - evidence mých objektů Race!  
V tuto chvíli mi spadla čelist..

Všechno je to pěkně popsáno i s ukázkami zde 
Příště popíšu další zkušenosti s touto na první pohled geniální dvojicí - Grails a IDEA.

úterý 20. července 2010

Zastaralé Lotus Notes and A gdk Window is being destroyed out of DestroyWindow

Taky se vám po čase přestal zobrazovat obsah tabů v Lotus Notes?
No mně se to stalo. Spustím si Notesy z příkazové řádky a najdu tam:

A gdk Window is being destroyed out of DestroyWindow                                                                                                            

/opt/ibm/lotus/notes/libemulator.so [0xb569c315]                                                                                                                
/opt/ibm/lotus/notes/libemulator.so [0xb5665bb1]                                                                                                                
/usr/lib/libgobject-2.0.so.0 [0xb47edb41]                                                                                                                      
/usr/lib/libglib-2.0.so.0(g_datalist_id_set_data_full+0x386) [0xb4e08d86]                                                                                      
/usr/lib/libgobject-2.0.so.0 [0xb47ee1f9]                                                                                                                      
/usr/lib/libgobject-2.0.so.0(g_object_unref+0xd8) [0xb47ee378]                                                                                                  
/usr/lib/libgdk-x11-2.0.so.0(gdk_window_destroy+0x3a) [0xb48fc0fa]                                                                                              
/opt/ibm/lotus/notes/libemulator.so [0xb567d20b]                                                                                                                
/opt/ibm/lotus/notes/libemulator.so [0xb567d0a0]                                                                                                                
/opt/ibm/lotus/notes/libemulator.so(DestroyWindow+0x183) [0xb567d3e7]                                                                                          
/opt/ibm/lotus/notes/notes(Quit+0x20e) [0x83ff77a]                                                                                                              
/opt/ibm/lotus/notes/notes(EndSession+0x47f) [0x8400845]                                                                                                        
/opt/ibm/lotus/notes/notes(MainWndProc+0x14a2) [0x834f406]                                                                                                      
/opt/ibm/lotus/notes/libemulator.so(CallWindowProcW+0xc0) [0xb566b472]                                                                                          
/opt/ibm/lotus/notes/libemulator.so [0xb5680b83]                                                                                                                
/opt/ibm/lotus/notes/libemulator.so(DispatchMessageW+0x13) [0xb5680bc9]                                                                                        
/opt/ibm/lotus/notes/notes(NEMMainLoop+0x3f5) [0x8365977]                                                                                                      
/opt/ibm/lotus/notes/notes(WinMain+0x5e1) [0x832507e]                                                                                                          
/opt/ibm/lotus/notes/notes(main+0x1b6) [0x83284ac]                                                                                                              
/lib/libc.so.6(__libc_start_main+0xfe) [0xb4ee4ace]   

No a tak jsem zjišťoval, čím by to asi mohlo být a našel jsem toto . Problém je v nekompatibilitě nového GTK s tím, které chtějí Notesy. Ať už je to chybou GTK či Notesů (spíš bych podezíral vývojáře GTKčka), obejít se to dá lehce. Stáhněte si z http://www.freetechie.com/upload/lotus_notes/ starší verze knihoven pro GTK, nahrajte je k ostatním knihovnám Notesů (typicky /opt/ibm/lotus/notes) a máte to!

Nebudou sice Notesy vypadat tak krásně jako dřív, ale aspoň něco...

čtvrtek 17. června 2010

Znovuzrození Obnoveného řádu

Wesnothu Zdar!

Tak už je to tady. Po dalších dlouhých měsících a letech jsem zase něco malého udělal pro komunitu nás Wesnoťáků. Jedno z nejzajímavějších tažení, Obnovený řád (v originále A New Order) od Arkadiusze Danielckiho, které napsal pro Wesnoth verzi 0.9.3 a které bylo naposledy funkční pod Wesnothem 1.2, je spravováno a je hratelné v nejčerstvějším vydání (nyní 1.8.2) této naprosto báječné a jedinečné strategie. Ano, milí přátelé, zajisté jste pochopili, spravuji je já a mám na svědomí jeho vzkříšení.

Hrajte, jak je vám libo. Nechte se vtáhnout do děje, zabíjejte, kecejte, vyslýchejte, mučte, zkrátka kochejte se.


Aktuálně je vydána verze 1.1.98 . Verze, která by měla beze zbytku fungovat a být v plné míře naportována na jedna-osmičkový stroj, bude 1.2 . Do té doby sháním všechny možné i nemožné beta testovače.

Užijte si to ve zdraví.

úterý 15. června 2010

Jak vyřešit ORA-01591: zámek uplatněný spornou distribuovanou transakcí

Tak jsem si jednou hrál s Hibernate a automatickým vytvářením tabulek nad skoro produkční databází Oracle 10 a dostal jsem se do jedné poněkud choulostivé situace. Při deployi earu jsem dostával
ORA-01591: zámek uplatněný spornou distribuovanou transakcí
Chvíli jsem si myslel, že to má na svědomí špatně navržený deployment Hibernate. Po čase jsem začal Gůglit ve vodách mimo Javu a dostal jsem se k jednoduchému řešeni:

Jedná se o problém, kdy transakce selhala v okamžiku, kdy se dostala do stavu prepared. Jediné řešení je ji odstranit. A řešení jsou dvě: buď se k ní připojit a rollbacknout, nebo ji smahnout přímo v databázi.

Druhé řešení je poměrně elegantní. Oracle definuje SQL příkaz ROLLBACK FORCE a jemu odpovídající PL/SQL funkci dbms_transaction.rollback_force(xid). V tabulce "SYS"."PENDING_TRANS$" je uložen záznam o všech čekajících transakcích. Ve sloupci LOCAL_TRAN_ID je XID.

Stačí se tedy přihlásit jako uživatel SYSTEM s funkcí SYSDBA (například v sqlplus), spustit
exec dbms_transaction.rollback_force(moje_xid)
a je vymalováno.

pondělí 31. května 2010

Hibernate error - identifier altered from 1 to 1

Nějakou dobu jsem laboroval s toto poněkud podivnou hláškou - jak může změna z 1 na 1 vygenerovat chybu? A kde se vůbec ta změna bere, když jedinou operaci, kterou dělám, je session.save()?

Nakonec jsem chybu našel. Při laborování s formátem dat v databázi a ručním copy&paste psaní hbm.xml jsem zavlekl typovou nekonzistenci do dat. V databázi (PostgreSQL) jsem měl u ID Integer (což onu chybu ale nevyvolá), v hbm.xml java.lang.Integer, ale ve třídě java.lang.Long. No a protože long nelze bez přetypování uložit do intu, ona alterace byla na světě.

Řešení tohoto problému je tedy prosté. Zkontrolujte si, že vám PŘESNĚ sedí jednotlivé typy v Javě a v hbm.xml

Kéž to někomu pomůže.

pondělí 3. května 2010

Jak ignorovat skryté adresáře v doplňování v bashi

bash completion, neboli inteligentní doplňování v bashi, je strašně mocná zbraň. Poměrně hodně mi ale vadilo, že mi bash při průchodu zdrojáků uložených v Subversion permanentně nabízel v možnostech pro příkaz cd i adresář .svn . Tak jsem Gůglil, až jsem zjistil, jak se s tím vypořádat.
Nabízení skrytých adresářů je vlastnost knihovny readline, která je v bashi použita. A tu lze vypnout jednoduše pomocí nastavení readline. Do ~/.inputrc přidáte
set et match-hidden-files off
a je to. Eqivalentem pro právě běžící bash je použití interního příkazu bind:
bind 'set match-hidden-files off'
Třeba to někomu pomůže.

čtvrtek 11. února 2010

Blokování nájezdů na server přes SSH

Dnes jsem řešil, jak více zabezpečit SSH před možným průnikem. Po chvilce Gůglení jsem narazil na podrobný popis, jak to zařídit na OpenSuSE 11.1 .
Použití sshguardu je rychlé, pěkné a účinné. K danému odkazu ještš přidám, že existuje OpenSuSE repository csbuild, které sshguard obsahuje.
Stačí tedy

sudo zypper ar http://download.opensuse.org/repositories/home:/csbuild/openSUSE_11.1/ csbuild

sudo zypper in sshguard

a nakonfigurovat podle onoho návodu na stránkách OpenSuSE.

POZOR! Pokud nemáte korektně rozchozený AppArmor, nechejte jej být. Při jeho nastartování vám syslog-ng zařve "Broken Pipe" na odeslání dat do roury sshguardu, takže Vám to nebude fungovat.

Snad to někomu pomůže

úterý 9. února 2010

JBoss 4.2 a kumulující se instance Stateless EJB

Asi týden jsem si hrál s J2EE aplikací Westico Visibility Platform a každou chvíli mi aplikace sletěla na OutOfMemoryError. Asi memory leak, řekl jsem si.
Stáhl jsem si tedy NetBeansy (qůli profileru) a začal hledat, kde tesař nechal v paměti díru. Zjistil jsem, že mi permanentně narůstá počet instancí dvou Session Stateless EJB, které volám z MDB ihned po sobě, těsně před ukončením zpracování zprávy. Protože provádím JMS ack ihned po příchodu zprávy, říkal jsem si, že si asi lookup vytvoří nové instance fazolí, ale požadavek neskončí a proto to bobtná. Dlouho jsem trasoval onu Message Driven Beanu, dokud jsem si opravdu nebyl jistý, že požadavek skončil a tudíž GC by měl odstranit "nepotřebné" instance a v poolu by měly zůstat jenom "potřebné". Tak jsem se zaměřil na pool a zjistil následující:
JBoss má oddělené pooly pro MDB a stateless EJB. Pro obejítí klasické Javovské synchronizace používá JBoss ThreadLocal pool. A v tom je právě šutr úrazu. Díky klasickému implicitnímu chování MDB se stane, že každý požadavek je zpracován jiným vláknem a tedy pool pro bezestavové fazole bobtná, přestože má nastaven maximální počet instancí v poolu.
Pokud tedy chcete v JBossu volat stateless EJB z MDB, musíte patřičné bezestavové fazoli nastavit jiný typ poolu. Ideálně org.jboss.ejb3.StrictMaxPool, a to třeba pomocí JBossí anotace @PoolClass, jak je popsáno zde.

Třeba to někomu zachrání kupu nervů.

úterý 19. ledna 2010

Jak rozchodit Joomla! pod Microsoft Windows

Nedávno jsem musel po telefonu a FTP rozchodit Joomla! na Widlích 2003, kde už navíc běží Lotus Notes. Pro příští generace tu zanechám minimalistický postup, jak to udělat:

Nejdřív si stáhneme Joomla!, MySQL, Apache a PHP (5.2.11)

V prvé řadě nainstalujte MySQL - stačí spustit instalátor a proklikat se na konec. V nastavení samozřejmě zvolte Server a Multilingual, zadejte heslo.
Potom v okně příkazového řádku
cd \Program Files\mysql\bin
mysql -u root -p
Password: sem zadejte heslo z instalace
mysql> CREATE USER 'joomla'@'localhost' IDENTIFIED BY 'heslo';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'joomla'@'localhost'
-> WITH GRANT OPTION;
mysql> \q

A tím je databáze připravena.
Potom nainstalujte Apache. Ponechejte základní nastavení.
Jako volbu při instalaci zvolte samostatnou aplikaci místo servisy - nastavíte ji až nakonec, až bude vše chodit. Nastavte port 8080.

Potom nainstalujte PHP. Doporučuji nainstalovat do adresáře C:\Program Files\Apache Software Foundation\PHP5.2.11 , protože pak je možné říct FileZille, aby Vám jako root spřístupnila pouze C:\Program Files\Apache Software Foundation a máte k dispozici jak httpd.conf, tak php.ini . V rámci instalace zvolte instalaci do Apache 2.2 jako modul (modul je rychlejší, pro testy je ale lepší použít CGI - nemusí se pořád restartovat Apache při změně php.ini).

V httpd.conf odkomentujte LoadModule pro moduly proxy, proxy_http a rewrite, v DirectoryIndex změňte na
DirectoryIndex index.php index.html

V sekci
změňte AllowOverride z None na All

A to by mělo být prozatím vše.

Otestujte konfiguraci pomocí Test Configuration ve Startmenu Apache.

V php.ini nastavte date.timezone na hodnotu, kterou považujete za rozumnou, například Europe/Prague

Přímo do adresáře C:\Program Files\Apache Software Foundation\Apache2.2\htdocs nakopírujte obsah adresáře joomla z instalačního balíku Joomla!
Přejmenutje htaccess.txt na .htaccess a odkomentujte v něm řádek
RewriteBase /

V danou chvíli je vše nachystáno ke konfiguraci Joomla!

Objevil se problém
Call stack
# Function Location
1 JSite->dispatch() C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\index.php:68
2 JComponentHelper->renderComponent() C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\includes\application.php:124
3 JError->raiseError() C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\libraries\joomla\application\component\helper.php:95
4 JError->raise() C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\libraries\joomla\error\error.php:171
5 JException->__construct() C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\libraries\joomla\error\error.php:136

Řešení je jednoduché:
http://discussion.accuwebhosting.com/joomla-issue-404-component-not-found_blog_by_ryan_125.html

Nakonec je třeba poslední věc: co s porty?
Jsou dvě možnosti - buď budete akceptovat, že na Joomla! půjdete přes port 8080 a necháte vše tak, nebo budete muset přesunout LotusNotes na jiný stroj a z Apache udělat reverzní proxy pro notesy.

Pokud to druhé, tak nejdříve Lotus Notes přemigrujte (to nechám na Vás jak).

Shoďte Notesy a Apache. V httpd.conf Apache změňte Listen 8080 na Listen 80 a restartujte Apache.

Pak je třeba nastavit mod_rewrite a mod_proxy.

TBD.

A je to.

úterý 8. prosince 2009

Invalid checksum na UDP paketech

Nějakou dobu jsem laboroval s tím, že mi javovská aplikace běžící na IBM xSeries x3650 s OpenSuSE 11.0 generovala invalidní UDP pakety. Hlásil mi to WireShark (dříve ethreal).
Firmware jednočipu G2 to nebyl sto sežrat a pokud jsem na něj chtěl data dostat, musel jsem to vyřešit. Tak jsem Gůglil a zkoušel...

Výsledek mého snažení lze shrnout do těchto bodů:
  • Je to víc jak rok známý problém a řeší se, ale ještě není vyřešen.
  • Problém není v Javě, ale někde mezi jádrem a síťovkou. Stejný kernel na jiné síťovce funguje, jsou prý kernely, které s těmito síťovkami fungují. V tomto případě to nechodí na Broadcom Corporation NetXtreme II BCM5708 Gigabit Ethernet (rev 12)
  • Na vině je chybné generování checksumu síťovkou, neboť při použití Raw Socket (což Java dělá), generuje checksum právě síťovka (nebo její modul, nevím, ve zdrojácích jsem nebyl)
  • Řešením je použití TCP checksum offload, které vypíná ono generování kontrolního součtu.
  • Na Linuxu se k vypnutí použije ethtool -K ethN rx off tx off, kde ethN odpovídá konkrétní síťovce, kde to chcete vypnout (tedy eth0, eth1,...)

Třeba to někomu pomůže...

středa 2. prosince 2009

Pochromovaný chameleon aneb Google Chrome na OpenSuSE 11.2

JO! Už je to tady! Máme hrábě v ruce! Teda nikoli hrábě, ale Google Chrome. Jeden z uživatelů OpenSuSE Build Service, dbuck, připravil OpenSuSE Chromium repository s oním přelomovým prohlížečem. Až budu mít nějaké dlouhodobější zkušenosti, dám vědět. Na Ubuntu 9.10 64bit běhá naprosto krásně, a to včetně nepodporovaného Flashe.

Instalace probíhá násůedovně:
1) Přidejte dbuckovu repository pro zypper:
Pro uživatele openSUSE 11.2:
sudo zypper ar http://download.opensuse.org/repositories/home:/dbuck/openSUSE_Factory/ Chromium

Pro uživatele openSUSE 11.1:
sudo zypper ar http://download.opensuse.org/repositories/home:/dbuck/openSUSE_11.1/ Chromium

Pro uživatele openSUSE 11.0:
sudo zypper ar http://download.opensuse.org/repositories/home:/dbuck/openSUSE_11.1/ Chromium

Díky tomu, že dbuck nachystal build tak, že se zdrojáky tahají přímo ze svn projektu chromium, prohlížeč je tedy chromium-browser, nikoli chrome.

Když je repository přidána, můžeme instalovat:
sudo zypper in chromium-browser

No a spustí se pomocí
chromium-browser

Spolu pak můžeme jenom poděkovat dbuckovi za dobře odvedenou práci..

čtvrtek 26. listopadu 2009

Kdy parametrizovaný GET a kdy dvě operace GET a QUERY?

Na můj předchozí blogpost ze série oRESTování reagoval Petr Ferschmann, člen týmu WinStromu. Kromě poděkování za pochvalu ale také píše:
Osobně považuji za ekvivalentní tyto formy zápisu:
/faktura-vydana/(stavUhrK='uhrazeno%27)
/faktura-vydana/?filter=stavUhrK=%3d%27uhrazeno%27
Jak jistě tušíte, nemohu s tímto souhlasit, a proto vznikl tento článeček.

Věc, která vypadá z pohledu HTTP eqivalentně, z pohledu Java kódu eqivalentně, dokonce i z pohledu uživatele, z pohledu RESTu eqivalentní není. Webovému prohlížeči je jedno, které URL uživatel napíše, je to jenom směs znamének. Jestli je na serveru logika udělaná tak, že v metodě doGet() HttpServletu vezmete z request.getRequestPath() jednu část a prohlásíte ji za vyhledávací řetězec (filtr) nebo tutéž část získáte pomocí request.getParameter("filter"), je také celkem buřt. Pro HTTP protokol je to jedno, protože první řádek bude pokaždé vypadat stejně, tedy buď

GET /faktura-vydana/(stavUhrK='uhrazeno%27) HTTP/1.1

nebo

GET /faktura-vydana/?filter=stavUhrK=%3d%27uhrazeno%27 HTTP/1.1

Jak je to ale z pohledu RESTu? Začněměž tím, že si řekneme kousek základní definice RESTu - je to množina N operací, kde N je dostatečně malé číslo, společným pro všechny objekty systému (kterým říkáme zdroje neboli resources). Každý zdroj je unikátně identifikovatelný pomocí URI, za které se považuje buď URL nebo URN.

Tolik základní definice. Teď něco k operacím. Smysl mít několik málo jednotných operací je fakt, že se klient nemusí příliš zajímat o jaký zdroj se jedná a jaké má rozhraní, prostě s ním provede operaci, kterou požaduje, a ta buď půjde nebo nepůjde nebo udělá něco jiného než na jiném zdroji atd. Vzhledem k tomu, že operace se provádějí na zdrojích, které jsou URIčkované, můžeme prohlásit, že parametrem každé obecné operace je URI zdroje.

Těch parametrů ale může být povícero, a to hned ve dvou směrech. Uvedu dva příklady:

RESTová implementace Facebookového "Sdílet" by měla čtyři parametry: URI mojí zdi (tedy URI kolekce, kde se má zdroj (nový záznam o sdílení) vytvořit), URI toho, co chci sdílet, URI autora (ano, URI, Facebook mne musí UNIKÁTNĚ identifikovat!!!), a komentář.

Druhým příkladem budiž operace GET z WinStromu. GET na URL s jedním záznamem má parametr Accept, který definuje formát záznamu, který klient požaduje (XML,PDF,...).

Když jsme si toto řekli, vraťme se k WinStromu a jeho filtru. Každé URI reprezentuje zdroj. Jiný zdroj! Pakliže budeme chápat operaci GET klasicky, tedy "vrať obsah", tak GET na /faktura-vydana/ vrátí obsah kolekce faktura-vydaná, kdežto GET na /faktura-vydana/(stavUhrK='uhrazeno%27) vrací obsah - ČEHO? Z logiky věci zdroje reprezentujícího všechny zdroje z kolekce "faktura-vydana", které mají stav UhrK "uhrazeno%27". Jenomže - co můžeme říct o tom zdroji? Jedná se o zdroj nezávislý? Můžeme ho čapnout a přenést jinam? Jak se vlastně vytváří? Jaké jsou na něm nadefinovány jiné operace než GET? Není to vlastně jenom takový "virtuální" zdroj?

Musím se přiznat, že při slovním spojení "Virtuální RESTový zdroj" zamrazí v zádech. Zkusme se na to podívat z jiné stránky věci. To, co chceme, není IMHO až tak nový zdroj, jako spíše JINÝ POHLED kolekci "faktura-vydana", tedy na zdroj /faktura-vydana/ . Takový pohled, který bude obsahovat pouze takové zdroje, které odpovídají podmínce 'mají stav UhrK "uhrazeno%27" '. Tento pohled pak z hlediska RESTu můžeme udělat na třech místech: na straně klienta, poskytovatele zdroje či interceptorem. Protože chceme dát klientovi maximální komfort a navíc minimalizovat tok dat, předpokládejme, že tento nový pohled budeme budovat na straně poskytovatele zdroje, tedy na serveru.

Jak toho docílit? Velice jednoduše. Rozšíříme operaci GET o nepovinný parametr Filtr (nebo povinný s existující konstantou reprezentující nefiltrování). Na serveru se pak rozhodneme, zda máme či nemáme filtrovat a jak se k tomu dostaneme. Nemáme tak žádný další, tfuj, "virtuální zdroj", tfuj. A jak to v praxi provedeme? Jak to dělá HTTP - k operaci GET na kolekci přidáme parametr filter.

Pojďme ale ještě dál. Onen pohled reprezentovaný parametrem Filtr mění poměrně významně obsah, který klient dostane. Nejde tedy o čistý "jiný pohled na data". Ihned po interní operaci GET se na výsledek provede operace FILTR (a jestli je to uděláno v Javě, v XSLT/XPath či SQL, je celkem buřt). Můžeme tedy tuto dvojoperaci považovat za jednu - FILTEREDGET. GET pak nemá parametr Filtr, tento parametr je parametrem nové operace.

Zeptáte se - no jo, ale když HTTP operaci FILTEREDGET nemá, tak co s tím? Ale to je přece jednoduché, milý Watsone! Tak jak RESTová operace GET není HTTP GET, pouze se na ni mapuje, pak si řekněmež, že si operaci FILTEREDGET namapujeme tak, že URL HTTP GETové operace na kolekci rozšíříme o parametr filter ... :-D

Že je to stejné jako v případě parametru? Ale jděte. Pouze převod do HTTP je stejný. Na straně serveru vám to napoví, že tuto cestu je dobré řešit jinou interní operací. Při vytvoření RESTové (nebo i SOAPové) WebServisy to budete zveřejňovat jako jinou operaci.

Zkusím to teď ještě zobecnit:

Základní otázka Života, vesmíru a vůbec má jasnou odpověď - 42. Nejasná je právě ona otázka.

Otázka, zda cpát či necpát jazyk do URL má také jasnou odpověď - pro všechnu matku přírodu NEE!!!

Jasná otázka, zda použít princip separátních zdrojů, parametrizovanou operaci GET nebo dvě operace GET a FILTEREDGET/QUERY/COKOLI_PODOBNÉHO, jasnou odpověď nemá. Je třeba k tomu přistupovat s mužskou schopností plnohodnotné syntézy či ženskou intuicí:

Rozdílné zdroje použijte tam, kde se opravdu o dva rozdílné zdroje jedná. GET "Aktuální seznam členů CZLUGu", GET "seznam členů CZLUGu počáteční", GET "seznam členů CZLUGu verze 234".

Parametrizujte tam, kde se jedná o jiné formy reprezentace téhož zdroje. GET "Seznam členů CZLUGu"?platny_ke_dni=[puvodni|fcil|YYYY-MM-DD]. Nebo jiný formát záznamu ala WinStrom.

Jinou operaci, pokud se jedná o stejný zdroj dat, ale s až diametrálně odlišným obsahem - typicky vyhledávání. GET "Seznam členů CZLUGu", QUERY "Seznam členů CZLUGu"?query=ti_co_nezaplatili_a_zacinaji_pismenem_fň "

Ufff. Doufám, že to někomu pomůže při rozhodování či pro lepší pochopení principů RESTu.

pátek 20. listopadu 2009

WinStrom - krásný příklad REST API

Tak jsem se zase rozhodl vrátit se k oRESTování. První příspěvek bude o tom, že i u nás v republice umíme udělat pěkné RESTózní API.
Při shánění materiálů jsem dnes narazil na REST API k účetnímu systému WinStrom. A je opravdu pěkné. Ale má i své mouchy.

Samozřejmě jako transportní protokol použili HTTP. Podporují HTTPS a HttpBasic - což ve spolupráci s přístupovými právy dostatečně zabezpečuje bezpečnost dat. Používají klasické operace GET, POST, PUT a DELETE (PUT a POST zeqivaletnili, což ale samozřejmě není nic proti RESTóznosti API), používají celkem hojně HTTP status.

URL jsou taky HTTP. Celkem logicky nejsou neprůhledná - mají svoji logiku.

Pro práci s kolekcí jedné evidence to jsou:
/ID.firmy/typevidence{/[reports|properties|relations|filtr]}

a pro práci s konkrétní položkou
/ID.firmy/typevidence/ID.záznamu{.formát}{/podevidence} (tady si nejsem jist, jestli ten formát je povinný nebo není, IMHO by být neměl, ale z docky plyne, že je)

Co se týká RESTových operací, tak si vystačí se čtyřmi - klasický CRUD.

CREATE se volá na kolekci. Návratová hodnota je buď neúspěch nebo úspěch. Úspěch v sobě obsahuje identifikátor vytvořeného zdroje.

UPDATE se volá na konkrétní zdroj - tam jdou nová data, zpátky status operace.

DELETE je klasický - jenom jsem nenašel, na co vše se dá volat.

GET je pěkný. Je sice parametrizovaný, ale parametry lze rozdělit do tří kategorií - stránkování a řazení, přidání metadat a (s tím mám kapku problém) XPath na výsledek, jestliže je ve formátu XML (z důvodu omezení přenášených dat)

Až doposud popis a chvála. Teď ale vady na kráse:
  • XPath jsem už zmínil, ale to není zas takový problém
  • Operace CREATE vrátí identifikátor záznamu, nikoli URL, takže URL si uživatel musí sám poskládat, a to je samozřejmě proti RESTu
  • GETové URL obsahuje formát výsledku - zde by bylo na místě použít parametr v QUERY_STRING, ale chápu, že MS Explorer by si s tím nemusel poradit (alespoň v dřevních dobách používal MSIE příponu ke stanovení content-type :-) )
  • A na závěr to nejhorší. PARAMETR filtr pro fitrování dat na kolekci není použit jako parametr, nýbrž jako součást identifikátoru, což je VYSOCE nehezké. Cpát přímo do URL ořezanou obdobu SQL (viz syntaxe Filtrování záznamů) mi přijde více než nechutné.

pondělí 16. listopadu 2009

Lotus Domino na OpenSuSE a Unable to bind to port Port = 6400 Error

Poslední dobou se kromě jiného zase věnuji Notesům (čti notesům :-D) a při poslední instalaci jsem narazil na poměrně fatální problém:
Unable to bind to port Port = 6400

Gůglím a gůglím, až jsem našel http://www-01.ibm.com/support/docview.wss?rs=899&uid=swg21167181 . Přečti si to a nevěřím vlastním očím:
Note: Port 25 is incorrectly reported as port 6400 in the error message because Hex 0x0019 is intepreted as 0x1900, which is 6400.


O co se tedy jedná? Domino se při startu SMTP modulu snaží samozřejmě provést bind() serverového portu číslo 25. Pokud už ale na stroji nějaké to MTAčko běží (např. postfix, který instaluji na všechny servery), je onen port 25, default pro MTA, samozřejmě obsazený. Proto musí naprosto logicky zařvat, že se onen bind() nepodařil a SMTP modul nenastartoval. Jenomže v tom mají kluci drobnou chybku. Domino místo portu 25 zahlásí port 6400. Proč? 25 je v hexa 0x19. 6400 je v hexa 0x1900 ... pochopili? Ano, pravděpodobně opačný 2bajtový indyán. Takže až na Vás Lotus Domino zařve "Unable to bind to port Port=xyzž, podělte ono číslo 256, zbytek vynásobte 256, sečtěte oba výsledky a dostanete správné číslo portu (prostě převeďte do hexa, prohoďte horný a dolní bajt a převeďte zase zpátky do desítkové soustavy). Takže pro port 20480 to bude 80 atd.

Snad to někomu pomůže.

čtvrtek 13. srpna 2009

Válka o Word aneb Velké Patentování

Právě jsem si přečetl zprávu, že Microsoft nesmí prodávat Word, který bude umět pracovat s rodinou .DOCX souborů, tedy s Mrqosoftím OpenXML. A to proto, že firma i4i (čti áj fór áj, neboli eye for eye, což v překladu znamená Oko za Oko) podala žalobu na porušení jejich patentu. i4i si patentovali roztržení obsahu dokumentu od jejich metadat a nad metadaty pak generovali různé pohledy. VELMI mi to připomíná DocBook (který jsem používal rok po podání onoho patentu a to určitě nebyla první verze) nebo mnohem známější kaskádové styly.
To, že šlo o inovativní přístup, je naprosto jasné. Proč ale šlo něco takového patentovat, to mi zůstává rozum stát. Vzpomínáte na kauzy patentové ochrany tlačítka "Buy It Now" na E-Bay či použití cookies pro přenos informací na stránku s platbou od Amazon?
Každopádně Mrqosofti mají dle výroku federálního soudu zaplatit 290 milionů USD (200 podle soudu první instance (20.května) plus soudní výlohy a penále a já nevím co ještě...).