After about a year offline, the site was just re-born from the former
platform.
The current solution still has a few annoyances, but I'm fixing it :)
The most important thing is so sort out the pages that I brought from the
former site.
That needs me to implement auto-generated directory indexes in the JBake
platform this uses.
Until then, the blog below will contain all pages.
Another thing is the duplicated titles. That will go away soon.
← texy-64_med_med.gif
← ./texy-64_med_med.gif
← /favicon.ico
new PropertyModel<String>(this, "path")
Update: Čtvrt roku poté – čtěte na konci.
Již delší dobu zkouším proniknout do světa linuxu – až podezřele moc mých známých jej postupně začínalo opěvovat.
Kdysi jsem zkoušel Knoppix, ale upřímně řečeno, nějak to nebylo ono. Příliš nestabilní a netransparentní.
Potom mi kamarád na notebook, který mi prodával, nainstaloval Gentoo. Pro nováčka v linuxu to také moc dobrá volba nebyla. Nechal mi na linux 20 GB z disku a když jsem chtěl nainstalovat standardní aplikace (asi Mozillu, OpenOffice atd), vše se chtělo překládat, ale během překladu došlo na disku místo a systém emerge se sesypal do nenávratného stavu.
Potom přišlo Ubuntu. Nevím přesně, kdy jsem si ho všimnul, tuším že u verze 5 a nainstaloval jsem šestku. Jelikož jsem to zkoušel na notebooku, nikdy jsem nedokázal vypnout LCD notebooku Acer TravelMate 8080 s ATI Radeon 9600 a obraz přesměrovat na LCD monitor 1600 × 1200 – a to jsem zkoušel všelicos vždy až do totálního rozpadu X serveru :-)
Ve verzi 7 (Gutsy Gibon) již byla jakási grafická utilita, která měla být GUI pro nastavení monitorů a rozlišení, ale ani ta si s touto konfigurací neporadila.
Přelomem pro mě byla verze 8 (Hardy Heroin), ale nikoliv proto, že bych v ní již dokázal přesměrovat výstup grafiky, ale protože jsem si koupil desktop :-) Do něj jsem dal starší disk, co se válel v počítači, který jsem prodal spolubydlovi, a na jeho posledních asi 30 GB šlo Ubuntu.
Musím říci, že Ubuntu již dospělo do stavu, kdy i člověk jako já, který neprahne po tom, aby si vše kompiloval, nastavoval v texťácích a podobně, jej zvládne bez problémů nejen používat, ale i spravovat.
Zásluhu na tom má především vynikající integrace. Na úpravě Gnome je vidět, že Ubuntu se snaží vyjít vstříc uživatelům windows (což je podle mě dobře), a to se projevuje i jinde:
/media/KINGSTON/
.apt-get
,
Synaptic, mě osvobodilo od ubíjejícího řešení
závislostí, které jsem řešil s emerge v Gentoocmd_View
– jdou jen adresáře).sudo dpkg --force-architecture -i skype-...deb
.Je tu ale i pár nevýhod:
Courier New
. Tohle je snad asi
nejpalčivější problém, doufám, že se ukáže, že je to někde
opravitelné.Ctrl+E
je zde pod
Ctrl+K
nebo Ctrl+J
. Ctrl+E
asi nic
nedělá./boot/grub
a tam upravit menu.lst
. Hodil jsem
staré jádro jako default a zas všechno šlape. Vlastně to ani nebylo o moc
složitější než s Windows, jen to stačí znát.Co jsem ještě nezkoušel:
Celkově bych to tedy shrnul tak, že Ubuntu 8 už je systém, který je možné dát do rukou zkušenému Windowsákovi, aniž by neustále něco šteloval, ladil a opravoval, jen aby moh už konečně pohodlně pracovat.
U mě to na přechod ještě nevypadá – ke změně systému mě obvykle dokope něco, co potřebuju, ale ve starém to není. Nic takového ale pro mě Linux zatím nenabízí:
Takže ještě uvidíme – třeba Ubuntu 9 (třeba Instant Ichtyl?) přinese něco naprosto úžasného, co mě přetáhne. Nebo bude mít pravdu Pepa Kyrian, který říká: „Linux je návykovej… Uvidíš, do půl roka budeš linuxák.“ :-)
Je říjen 2008 a já používám Ubuntu již čtvrt roku jako hlavní pracovní platformu. Mé střednědobé dojmy z této distribuce a celkově dojmy z Linuxu dané jejím prostřednictvím shrnuji na následujících řádkách.
V původním textu si stěžuji na antialiasing. Pokusil jsem se to řešit
podle návodu
na zprovoznění microsoftích písem v Ubuntu. Nevím, jestli jsem si už
zvyknul, nebo tento návod zabral, každopádně s MS Courier New
v NetBeans už se mi pracuje hezky a s fonty není problém.
Doufám, že tohle nebude číst někdo z kolegů, jinak by mě asi ukamenovali :-) Stabilita Linuxu jako desktopu mi přijde nižší než stabilita Windows XP. A hned musím uvést konkrétní příklady.
S rychlostí je na tom Linuxový desktop v něčem dobře, v něčem bídně.
Desktop, to jsou hlavně okénkové aplikace, a mezi nimi kraluje Firefox s několika desítkami otevřených záložek. A Firefox na Xkách, to je bída. Schválně si proveďte tento test: Načtěte delší stránku (třeba manuál MySQL v kuse), a mačkněte F11 (fullscreen). Zatímco na Windows se změna provede ihned (tj. nepostřehnutelná prodleva), v Ubuntu čekám několik sekund (cca. pět). Podobně přepínání mezi záložkami je velmi pomalé. Ale to může být problém Firefoxu – nevím.
Nevím, zda je to nastavením, které neznám, ale Ubuntu se docela špatně vyrovnává s velkou zátěží disku. Celý systém začne reagovat velmi pomalu. Když jsem si na disk překopíroval svoji legální sbírku empétrojek a dal ji indexovat Amarokem a na pozadí běžely testy z EJB modulu TCK, celý systém se stal na několik desítek minut skoro nepoužitelným, a to mám 2× QuadCore. Windows jsou v takové situaci stále svěží a čilé, a to i na obyč DualCore.
Naopak velmi dobře je na tom Linux v práci se sítí a nejrůznějšími protokoly. Například FTP lítá na Linuxu mnohem lépe. Jedinou výjimkou je implementace virtuálního diskového systému přes SSH (gvfs), která je schopná na minutu zaseknout programy, které naivně používá blokující volání na filesystem – a to jsou asi všechny: Gnome, Krusader, Konqueror… kupodivu programy psané v Javě (např. NetBeans) s tím problém neměly a prostě načítaly výpis adresářů postupně.
Stejně tak s některým HW asi dokáže Linux pracovat efektivněji, protože když jsem na Ubuntu kopíroval fotky z flašky, lítalo to kolem 32 MB/s, zatímco na Windows mezi 20 a 25 MB/s. Dlužno ale dodat, že šlo o jiné počítače, takže je to dost možná právě tím. Budu muset vyzkoušet na stejném…
Podle mého soudu se Java na Linuxu stává velmi pozvolna, ale čím dál důležitější. Ačkoliv celkově se Linuxová komunita sestává z fundamentalistů, kteří si musí celý den překládat KDE, aby jim jelo o 1% rychleji a ušetřili tak denně několik sekund, postupně se k Linuxu (i díky projektům jako je Ubuntu) dostávají i lidé, kterým je šumák, jestli je všechno přeložené na míru mé architektuře, a raději vyžadují minimální námahu se správou systému a soustředí se na vlastní produktivitu.
Pro takové lidi se programy v Javě stávají mostem mezi Windows a Linuxem. Osobně jsem se již na Windows ustálil na několika málo programech, ve kterých trávím 90 % času (NetBeans, Firefox, Total Commander, Miranda, MySQL Query Browser, Outlook Express, Winamp). Když jsem pro ně před lety v Linuxu hledal náhradu, dopadlo to takto:
Z těchto tří příkladů je myslím jasné, že Java pro Linux hraje důležitou roli, byť je většinou Linuxáků opovrhovaná (obvykle z jejich vlastní hlouposti). Dříve či později se Javovské projekty budou prosazovat čím dál více, a to zejména v oblastech, kde je třeba na vývoj technologií reagovat velice rychle, což jsou momentálně právě IDE, ale do budoucna může jít například i o prohlížeče.
Nyní tedy krátce k dojmům z Javy na linuxu.
Pokud jde o rychlost, žádný výrazný rozdíl oproti Windows jsem nezaznamenal. Trochu potíže jsem měl pouze s výchozí instalací OpenJDK (či jak se to jmenuje), kterou jsem chtěl nahradit JDK od SUNu, ovšem po odinstalaci se po ní například NetBeans vehementně sháněly, a musel jsem přepisovat konfigurační soubor (což jakožto původem nelinuxák samozřejmě považuji za nehorázný opruz :-)
Dále jsem na Linuxu poprvé v životě viděl pád JVM – až doteď jsem si naivně myslel, že Javě se taková věc nemůže stát, a ani jsem o ní předtím nikdy neslyšel. Až zde, při spouštění Antu, mi Java prostě sletěla. To mě vážně rozhodilo a můj dlouhodobý dojem z Javy trochu poškodilo. Nicméně když jsem to samé testoval na Windows, vše bylo OK. Takže asi jde o nedostatek linuxové implementace JVM. Kromě toho, po vypnutí JIT to prošlo i na Linuxu.
Jinak se mi celkově v Javě na Linuxu dělá lépe, prostě je vidět, že je tu více „doma“ – se všemi těmi konzolemi a parametry a konfiguračními skripty… :-)
Miranda je pro mě natolik důležitá, že jí věnuju samostatný podnadpis :-) Ve Wine chodí naprosto skvěle, až na jedinou drobnost – IRC plugin. Ten se prostě nepřipojí. A jelikož IRC je hlavní IM komunikační kanál mojí společnosti, Miranda letěla. Pidgin je sice proti Mirandě velký shit, ale přeci jen mít na IRC Pidgin a vedle toho Mirandu na zbylých pět zpráv denně přes ICQ/Jabber… e-e.
Jinak celkový dojem z Ubuntu, potažmo Linuxu, je dobrý. Žádné zásadní neřešitelné problémy, vše je docela intuitivní a funguje očekávatelně, není třeba nic moc konfigurovat, do konzole chodím jen za svou vlastní prací a nikoliv spravovat rozhašený systém…
Myslím tedy, že tvůrcům Ubuntu se podařilo udělat velmi dobrou kompilaci, která v sobě snoubí dostatek svobody, kterou přináší svět Linuxu, ale zároveň dostatečně dobře zakrývá holá střeva Linuxu, která bych mohl nechtěně potrhat při snaze něco nainstalovat/poladit/nastavit… jak se mi to dříve stávalo s distribucemi Knoppix, Gentoo, Debian, Suse, Mandrake a Ubuntu 6 a 7.
Pokud by se mě tedy nyní nějaký technicky netalentovaný kamarád zeptal, zda má zkusit „ten linux“, poprvé bych mu s klidným srdcem podal právě instalační CD Ubuntu 8.04.
Ubuntu je občas terčem kritiky komunity Linuxu, že má sice nejvíce uživatelů, ale nijak nepřispívá rozvoji Linuxu. No ale co se divíte? Copak to není logické? Kdo z komunity přispívá? Jsou to jednak programátoři, které programování baví natolik, že ve volném čase programují pro Linuxovou komunitu, a jednak profesionálové ze společností vyvíjejících Linux distribuce, jako je např Red Hat.
A teď:
Výkřiky o tom, že z Ubuntu nejde komunitě žádný užitek, jsou
tedy – podle mého – liché. Komunitě skutečně nejde žádný přímý
užitek v podobě rozvoje software, ale – nemá snad komunita radost
z nárůstu počtu uživatelů Linuxu? Nevolala snad komunita dlouhou dobu po
řadových uživatelích? A teď, když se konečně našla distribuce, která
„to konečně dala do pohybu“, adoranti jiných distribucí zhrzeně a
závistivě sledují statistiky počtů
instalací, sledovanosti
diskutovanosti
a oblíbenosti
instalací Ubuntu.
Dále tím, jak díky Ubuntu roste počet uživatelů Linuxu až natolik, že již se dá hovořit o poměru spíše než o počtu, nastávají různé vedlejší efekty:
Navíc, nehledě na to, jestli komunita Ubuntu přispívá do upstreamu, ve výsledku je celé Linuxové komunitě prospěšná – už jenom z této logiky věci: Pokud více jak cca. pětina všech uživatelů Linuxu používá právě Ubuntu, potom je jistě prospěšná minimálně pětině linuxové komunity.
Po napsání předchozího článku Výhody a nevýhody PHP se ozval Jakub Vrána a chvíli jsme si mailovali nad některými body článku, což se, jak to bývá, stočilo na srovnání PHP s technologií, kterou já preferuji – tedy s Javou.
V závěru jsme se dostali k tomu, zda je Java nebo PHP podobnější Linuxu nebo Windows. Zde je část z mailu:
Jednu věc nechápu a budu rád, když mi jako (předpokládám) fanda Linuxu vysvětlíš:
Jak je možné, že lidé, kteří preferují Linux před Windows, zároveň preferují PHP před Javou. Protože pokud bychom zobecnili vlastnosti a požadavky na systémy a plaformy, potom právě Java oproti PHP by byla jako Linux oproti Windows – technologicky vyspělejší, vývojově stabilnější, zpětně kompatibilnější, modulárnější, konfigurovatelnější, víceúčelovější, a druhé ideologicky vykrádá první, přičemž to ani nezvládne dotáhnout do konce a zbyde jenom nedotažený hybrid zatížený historií svého vývoje.
PHP se mi zdá jako takový rozjetý mnohakilometrový vlak tažený slabou mašinkou, ke kterému stále napojují další a další vagóny – některé velice moderní, přepychové, a pokud jedete po rovince, vše je ok – ale pak přijde kopeček a mašinka se sotva vleče; a pak i v těch nejpřepychovějších vagónech poznáte, že je něco špatně. (Mašinka zde nepředstavuje výkonnost, ale právě ono „jádro“.)
Co je tedy podle tebe na PHP lepšího? Co tě k němu táhne kromě citové vazby? (Tvoje zásluhy v PHP komunitě zhruba znám a oceňuji, a chápu a znám z vlastní zkušenosti, že z takového rozjetého vlaku se velmi těžko vyskakuje.) Zkoušels někdy proniknout do J2EE? Znáš základní konceptuální rozdíly? Nechci tě nijak shazovat, jen mě zajímá, jestli se dokážeš vžít do mojí situace a pochopit tak, proč PHP tak „haním“.
Zdraví Ondra Žižka
Dovolím si zkopírovat Jakubovo resumé z článku Je PHP jako Linux nebo jako Windows?:
Jakub Vrána:
PHP a Linux – malé jádro, k tomu volitelné jednoúčelové knihovny s jednoduchým rozhraním.
Java a Windows – vše v jednom spravované přes komplexní objektové rozhraní.
Ondřej Žižka:
PHP a Windows (z pohledu programátora WinAPI): Silně proměnlivá technologie, v lecčems zpětně nekompatibilní, počáteční návrh špatný a směřující k lepšímu po vzoru lepších technologií, mnohé významné featury dodělávané ad hoc a nepřirozeně vmontované do návrhu.
Java a Linux: Stabilní technologie stavěná velmi rozvážně podle promyšleného návrhu dlouho laděného a diskutovaného mnoha IT firmami, silná a zaručená zpětná kompatibilita, standardizované API, mnoho různých použití (od embedded zařízení až po clusterované farmy serverů). Nejčastěji používaná rozšíření časem projdou procesem standardizace a začlení se do jádra, resp. JRE.
Jak někdo poznamenal v tamějších komentářích, Jakub posuzuje z pohledu technického, zatímco já se snažím spíše o ideologické srovnání – zkrátka principy, na kterých vývojáři a komunita dané technologie (ne)staví.
A to je z dlouhodobého hlediska mnohem důležitější – jistě chcete vyvíjet bez obav, že by příští major verze opět přinesla další sadu vlastností z jiných jazyků chaoticky splácaných dohromady se stávající verzí.
Aby byla debata co k čemu, měli bychom tato hesla něčím podpořit, případně vyvrátit. Pusťme se do toho :-)
Jak změřit velikost jádra? A co je vůbec jádro? Řekněme, že je to ta část technologie, která je nezbytně nutná pro její běh.
rt.jar
, což je balík, ve kterém
jsou knihovny obsažené ve standardní distribuci. Z toho se dá jako jádro
počítat maximálně část z nich.php6ts.dll
, má cca. 14 MB (standardní distribuce
windows), a tento modul je dále nedělitelný.php5ts.dll
má cca. 5 MB, a spolu s okolními
.dll
má asi 10 MB.Ale velikost dat není nejlepší ukazatel. Vyberme tedy jiné kritérium. Nabízí se možnost miniaturizace jádra technologie a složitost syntaxe, a Jakubem uvedená „komplexnost jádra“.
Co se týká „ne/komplexnosti“ jádra, tak si nejsem zcela jist, jak rozlišit, co v jádru je či není.
Pokud vím, v jádru Javy je jen několik tříd typu Object, String, Throwable, dále nativní metody základních systémových tříd, a tím to hasne; drtivá většina funkcionality JRE je již implementovaná v Javě a je oddělitelná.
V PHP je mnoho knihoven instalovatelných z repozitáře PEAR, a většina
těch, které jsou ve Windows verzi v phpXts.dll, jsou na linuxu volitelné za
cenu vlastní kompilace PHP. Nicméně nevolitelnou součástí jádra jsou
funkce jako money_format()
, apache_note()
nebo
highlight_file()
, na kterých jistě technologie
závislá není.
V tomto je tedy Linuxu podobnější Java, který v jádru obsahuje pouze to nutné (ať už pro funkčnost systému nebo kvůli výkonu).
Že by Java obsahovala vše v jednom je vyvráceno, a za „all-in-one“ technologii se dá považovat spíše PHP.
U té architektury Windows bych řekl, že se Jakub seknul; od verzí NT až po XP (Visty neznám) je systém poměrně modulárni a dá se očesat skoro až na HAL.
Stejně tak předchozí verze Windows – existuje mnoho různých amatérských minidistribucí Windows 98 (bohužel teď je nenajdu).
„spravované přes komplexní objektové rozhraní“ – to nevím, co tím Jakub u Windows myslel. Na WinAPI není objektového nic, to je čisté C.
Až teprve v extrémních podmínkách se ukáže, co vše lze z „jádra“ vypustit, aby technologie stále byla sama sebou.
Takovými podmínkami jsou například mobilní telefony. Java šlape i na telefonech jako jsou několik let staré mobily Nokia. Zde se velikost jádra těžko určí, protože implementace je do jisté míry hardwarová.
Naproti tomu nejmenší mě známý výskyt PHP je verze PHP pro servery Novell, která je osekaná o leccos, a přesto má hlavní knihovna stále několik MB.
Řekl bych, že tím je v tomto bodě jasno – malé jádro a mnoho volitelných knihoven jednoznačně pasuje spíše na Javu.
//Update:// O tom, že Java je skutečně univerzální, se můžete přesvědčit např. na http://www.knihy.cpress.cz/BookDoc.asp?…, kde najdete publikaci pro grafiky, která se věnuje se programování skeneru pomocí Javy.
Syntaxe Java oproti syntaxi PHP:
systémová volání
global
$GLOBALS
, $_GET
, $_POST
,
$_COOKIE
, $_FILES
,
$_ENV
, $_REQUEST
Naopak:
Java syntaxe je jednodušší než syntaxe PHP.
Co se tedy týký připodobnění Javy a PHP k Linuxu a Windows, není mnoho argumentů, proč PHP připodobňovat k Linuxu a Javu k Windows – spíše naopak.
PHP je prostě na ocasu vývoje a s velkými obtížemi adoptuje vymoženosti jiných technologií (OOP, Unicode, výjimky, synchronizaci a sdílení, …) – stejně jako Windows.
Naproti tomu Java je spolu s C# a .NET na špičce vývoje na poli IT, podobně jako Linux na poli OS.
Jako tečku cituji člověka, který má PHP opravdu v malíku (a autora skvělého Texy!) – Davida Grudla:
Programovat v Javě umí kdekdo. O ASP.NET ani nemluvě. Jen v PHP píši skuteční hrdinové. Renesanční bytosti. Fascinující a neskutečně trpěliví lidé. Trpěliví od slova trpět. Třeba jako já.
-- David Grudl, http://latrine.dgx.cz/php-surprise
It's a JVM bug described here
Also here :
- Another possibility, which I have not verified, might be due to a delay that we put it to the closing of the currentClip.
We put in this delay to workaround a Java Sound bug in Linux.
The resulting scenario is: because the last clip was not closed before the next clip attempts to play,
the audio device is still occupied, thus generating a LineUnavailableException.
Though, we've hardly experienced any problems with the JavaClipAudioPlayer, so I doubt this is the problem.
Also here about „long sentences“:
The problem, it seems is in the code that breaks up a very long sentence. FreeTTS is designed to synthesize text with low latency. When given a very long sentence, such as in your example, it will decide that the sentence is too long to be synthesized in a timely fashion and break it up into smaller bits. This logic is rarely (if every executed) since it only is invoked when very long sentences occur. If I change your sample code to concatenate a period instead of a comma after every „Number xx“, things are synthesized just fine with no line unavailable error.
System.setProperty("com.sun.speech.freetts.audio.AudioPlayer.openFailDelayMs", "100"); System.setProperty("com.sun.speech.freetts.audio.AudioPlayer.totalOpenFailDelayMs", "30000");
Also here :
If you disable the ARts sound daemon under KDE FreeTTS will work and not give the error:
LINE UNAVAILABLE: Format is PCM_SIGNED 16000.0 Hz, 16 bit, mono, 2 bytes/frame, big-endian
Or something simular to t he error above. I believe the issue (and reply if I'm wrong) is the ARts daemon grabs the /dev/dsp device and prevents FreeTTS from using it. Though I don't run ETS (Enlightenment sound daemon) this daemon too, could be a problem for fellow FreeTTS users/developers. I believe this daemon too grabs on to /dev/dsp and prevents others from using it.
Also, testing the line availability :
- To test if an environment supports sound, copy the code in
com.sun.speech.freetts.audio.JavaStreamingAudioPlayer.openLine()
to a method in your application (remember to include the javax.sound.sampled.* packages).
Before you call FreeTTS methods, call this method to see if your environment supports sound.
If it does, remember to close the audio line, since FreeTTS will try to open it again.
Fix FreeTTS according to this link, which is now unavailable because Oracle fucked it up. That page supposedly contained a fix for FreeTTS making it not vulnerable to that JVM's bug.
After I mavenized FreeTTS, I started getting an exception from JDK saying
it can't read ZIP file somewhere in VoiceManager.java
.
I used strace to figure out a „Error opening ZIP file“. That did not
help because it did not tell me about JVM's calls to open()
for
some reason, but anyway, here's the command:
sudo strace -e trace=all -o log.txt \ java -Xrunjdwp:transport=dt_socket,server=y,address=4000 \ -Djpda.listen=true -Djpda.address=4000 \ -Dmbrola.base="`pwd`/../mbrola301"\ -Dfreetts.voicespath="`pwd`/../mbrola301/voices"\ -jar /home/ondra/work/BOTS/SpeechBot/SpeechBot-mavenized/target/SpeechBot-1.0-SNAPSHOT.jar \ irc.eng.brq.redhat.com '#some'
The problem was that mavenization of FreeTTS and MBrola involved re-naming the .jar files.
But FreeTTS not only has hard-coded dependencies in it's
MANIFEST.MF
's Class-Path
, which is quite stupid for a
library, it also has code inside which actually relies on these data, which is
the real peak of stupidity. So if you Mavenize such library, it ends up in
different directories. So it will not usually work in IDE.
You need to flatten the dependencies to a single dir, using e.g.
mvn dependencies:copy
, see this
example. You also need to set Maven to put all app's dependencies to
it's jar's MANIFEST.MF
's Class-Path
– here
it's ok because it's an app, not a library.
Then you need to manually rewrite all FreeTTS libraries' MANIFEST.MF in the
local repository, so that you can rebuild your application. Change the
Class-Path
to reflect the names of the jar files; Usually, that
means adding -<version>
so it's e.g.
cmulex-1.2.jar:freetts-1.2.jar:...
.
Then you run a shell command like
java -Dmbrola.base="`pwd`/../mbrola301"\ -Dfreetts.voicespath="`pwd`/../mbrola301/voices"\ -jar /home/ondra/work/BOTS/SpeechBot/SpeechBot-mavenized/target/SpeechBot-1.0-SNAPSHOT.jar \ irc.eng.brq.redhat.com '#some'
Here you don't need to specify -cp because the deps are in the app's MANIFEST.MF as per the explanation above.
I had some troubles make FreeTTS find MBrola's voices.
Don't forget to set the mbrola.base
system property when you run
your application, e.g.:
java -jar myapp.jar -Dmbrola.base="`pwd`/../mbrola301"
eventually you can set freetts.voicespath
to different dir:
java -jar myapp.jar -Dmbrola.base="`pwd`/../mbrola301" -Dfreetts.voicespath="`pwd`/../mbrola301/voices"
There are few voices in FreeTTS with MBrola.
// This is a tiny database, contains only data for time demo app. System.setProperty("freetts.voices","com.sun.speech.freetts.en.us.cmu_time_awb.AlanVoiceDirectory"); // Using this throws the ClassCastException. You need to recompile it. System.setProperty("freetts.voices", "com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory"); // MBrola voices. System.setProperty("freetts.voices", "de.dfki.lt.freetts.en.us.MbrolaVoiceDirectory");
Even after setting mbrola.voices
, it kept finding only
mbrola_us1
, mbrola_us2
, mbrola_us3
.
I added some voices from their web, but these were not listed as available.
I guess I need some other VoiceDirectory
implementation because
the voices are hardcoded in KevinVoiceDirectory
so I guess
there's no dynamic loading despite all that mess in
VoiceDirectory.java
.
After solving „Error reading ZIP“ by changing FreeTTS's jar's MANIFEST.MF's Class-Path value to reflect my jar names (mavenized), I started getting this:
Exception in thread "main" java.lang.ClassCastException: com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory cannot be cast to com.sun.speech.freetts.VoiceDirectory at com.sun.speech.freetts.VoiceManager.getVoices(VoiceManager.java:113) at cz.dynawest.speechbot.synt.MbrolaSpeaker.<init>(MbrolaSpeaker.java:38) at cz.dynawest.speechbot.SpeechBot.<init>(SpeechBot.java:25) at cz.dynawest.speechbot.SpeechBot.main(SpeechBot.java:65)
After re-compiling KevinVoiceDirectory and storing it in jar, it works.
S pozvolným přechodem od PHP k Javě a J2EE jsem narazil na problém – kam s ním?
Řeč je o nedostečné nabídce Java EE hostingů, a tedy nízká konkurence a z toho plynoucí vysoké ceny. Nejsem si zcela jist, zda java hosting je na správu náročnější než např. LAMP – podle zkušeností kamaráda, který si hostuje sám, je to jednodušší – prostě nainstalujete Apache Tomcat a hotovo.
Pro upřesnění – kamarádovi příliš nesedly aplikační servery (JBoss, IBM WebSphere, BEA WebLogic a další mamuti – zjistil, že pro něj je lepší řešení Tomcat a všechny featury z aplikačních serverů instaluje do Tomcatu jako jednotlivé moduly, případně je vkládá přímo do webové aplikace.
Mě samotnému se ovšem o server starat nechce – znamenalo by to najít server housing, koupit server, naučit se dobře administrovat Linux, … a jak říká Honza Svoboda – není možné dobře umět a dobře dělat všechno.
S jedním kamarádem, zavilým Céčkařem a PHPčkářem, jsme (také :-) vedli debatu o výhodách a nevýhodách PHP. Tak jsme se dostali k tomu, že já vyvíjím nějaké projektíky v Javě, ale nemám je kam dát.
Kamarád měl tehdy zakoupený docela silný stroj (nějaké čtyřjádro s 8 GB paměti a čtyřmi SAS disky @ 10k RMP), který ovšem neměl jak využít, tak jsem na něm aspoň učil nějaké ty neuronové sítě z mojí diplomky :-)
Později jsem se dozvěděl od několika známých, že s Javou a J2EE mají podobný problém – mají J2EE backend, k němu by chtěli J2EE frontend, ale nenašli výhodný hosting a sami si hostovat nechtějí, a tak pro ně bylo cenově výhodnější sáhnout po nouzovém řešení.
Využit kamarádův stroj a znalosti ke zřízení Java hostingu se samo nabízelo. Netrvalo dlouho a stroj se přesunul do server-housingové společnosti a objevila se na něm Java a Tomcat. Zatím na něm běží jen moje J2EE „pokusy“, a stroj lačně čeká na další využití :-)
Pokud byste chtěli na výše zmíněném serveru zkusit hostovat svoji J2EE aplikaci, můžete se ozvat a zprostředkuji kontakt.
Možná by se někomu mohlo po přečtení předchozích odstavců zdát nedůvěryhodné dávat hosting „ke kamarádovi nějakého Ondry Žižky“ – ale tento kamarád pracuje jako správce sítě v organizaci s řádově několika tisíci počítači a programátor systému automatické správy této sítě.
Nemá však zkušenosti s administrací Java hostingu, a proto to momentálně řešíme tak, že mám plný přístup k Tomcatu a spravuji si sám.
Řešení vašeho hostingu by vypadalo podobně – server by se nejspíše rozdělil na virtuální hostingy, ať už na úrovni Linuxu nebo Javy, a svůj virtuální hosting byste si spravovali sami.
Zkouška bude nejspíše zdarma – podle dohody.
Máte-li zájem, ozvěte se na ondra@dynawest.cz, kamarád mě pověřil zpracováním „úvodního kontaktu“ :-)
Přesunuto sem.
Po napsání předchozího článku Výhody a nevýhody PHP se ozval Jakub Vrána a chvíli jsme si mailovali nad některými body článku, což se, jak to bývá, stočilo na srovnání PHP s technologií, kterou já preferuji – tedy s Javou.
V závěru jsme se dostali k tomu, zda je Java nebo PHP podobnější Linuxu nebo Windows. Zde je část z mailu:
Jednu věc nechápu a budu rád, když mi jako (předpokládám) fanda Linuxu vysvětlíš:
Jak je možné, že lidé, kteří preferují Linux před Windows, zároveň preferují PHP před Javou. Protože pokud bychom zobecnili vlastnosti a požadavky na systémy a plaformy, potom právě Java oproti PHP by byla jako Linux oproti Windows – technologicky vyspělejší, vývojově stabilnější, zpětně kompatibilnější, modulárnější, konfigurovatelnější, víceúčelovější, a druhé ideologicky vykrádá první, přičemž to ani nezvládne dotáhnout do konce a zbyde jenom nedotažený hybrid zatížený historií svého vývoje.
PHP se mi zdá jako takový rozjetý mnohakilometrový vlak tažený slabou mašinkou, ke kterému stále napojují další a další vagóny – některé velice moderní, přepychové, a pokud jedete po rovince, vše je ok – ale pak přijde kopeček a mašinka se sotva vleče; a pak i v těch nejpřepychovějších vagónech poznáte, že je něco špatně. (Mašinka zde nepředstavuje výkonnost, ale právě ono „jádro“.)
Co je tedy podle tebe na PHP lepšího? Co tě k němu táhne kromě citové vazby? (Tvoje zásluhy v PHP komunitě zhruba znám a oceňuji, a chápu a znám z vlastní zkušenosti, že z takového rozjetého vlaku se velmi těžko vyskakuje.) Zkoušels někdy proniknout do J2EE? Znáš základní konceptuální rozdíly? Nechci tě nijak shazovat, jen mě zajímá, jestli se dokážeš vžít do mojí situace a pochopit tak, proč PHP tak „haním“.
Zdraví Ondra Žižka
Dovolím si zkopírovat Jakubovo resumé z článku Je PHP jako Linux nebo jako Windows?:
Jakub Vrána:
PHP a Linux – malé jádro, k tomu volitelné jednoúčelové knihovny s jednoduchým rozhraním.
Java a Windows – vše v jednom spravované přes komplexní objektové rozhraní.
Ondřej Žižka:
PHP a Windows (z pohledu programátora WinAPI): Silně proměnlivá technologie, v lecčems zpětně nekompatibilní, počáteční návrh špatný a směřující k lepšímu po vzoru lepších technologií, mnohé významné featury dodělávané ad hoc a nepřirozeně vmontované do návrhu.
Java a Linux: Stabilní technologie stavěná velmi rozvážně podle promyšleného návrhu dlouho laděného a diskutovaného mnoha IT firmami, silná a zaručená zpětná kompatibilita, standardizované API, mnoho různých použití (od embedded zařízení až po clusterované farmy serverů). Nejčastěji používaná rozšíření časem projdou procesem standardizace a začlení se do jádra, resp. JRE.
Jak někdo poznamenal v tamějších komentářích, Jakub posuzuje z pohledu technického, zatímco já se snažím spíše o ideologické srovnání – zkrátka principy, na kterých vývojáři a komunita dané technologie (ne)staví.
A to je z dlouhodobého hlediska mnohem důležitější – jistě chcete vyvíjet bez obav, že by příští major verze opět přinesla další sadu vlastností z jiných jazyků chaoticky splácaných dohromady se stávající verzí.
Aby byla debata co k čemu, měli bychom tato hesla něčím podpořit, případně vyvrátit. Pusťme se do toho :-)
Jak změřit velikost jádra? A co je vůbec jádro? Řekněme, že je to ta část technologie, která je nezbytně nutná pro její běh.
rt.jar
, což je balík, ve kterém
jsou knihovny obsažené ve standardní distribuci. Z toho se dá jako jádro
počítat maximálně část z nich.php6ts.dll
, má cca. 14 MB (standardní distribuce
windows), a tento modul je dále nedělitelný.php5ts.dll
má cca. 5 MB, a spolu s okolními
.dll
má asi 10 MB.Ale velikost dat není nejlepší ukazatel. Vyberme tedy jiné kritérium. Nabízí se možnost miniaturizace jádra technologie a složitost syntaxe, a Jakubem uvedená „komplexnost jádra“.
Co se týká „ne/komplexnosti“ jádra, tak si nejsem zcela jist, jak rozlišit, co v jádru je či není.
Pokud vím, v jádru Javy je jen několik tříd typu Object, String, Throwable, dále nativní metody základních systémových tříd, a tím to hasne; drtivá většina funkcionality JRE je již implementovaná v Javě a je oddělitelná.
V PHP je mnoho knihoven instalovatelných z repozitáře PEAR, a většina
těch, které jsou ve Windows verzi v phpXts.dll, jsou na linuxu volitelné za
cenu vlastní kompilace PHP. Nicméně nevolitelnou součástí jádra jsou
funkce jako money_format()
, apache_note()
nebo
highlight_file()
, na kterých jistě technologie
závislá není.
V tomto je tedy Linuxu podobnější Java, který v jádru obsahuje pouze to nutné (ať už pro funkčnost systému nebo kvůli výkonu).
Že by Java obsahovala vše v jednom je vyvráceno, a za „all-in-one“ technologii se dá považovat spíše PHP.
U té architektury Windows bych řekl, že se Jakub seknul; od verzí NT až po XP (Visty neznám) je systém poměrně modulárni a dá se očesat skoro až na HAL.
Stejně tak předchozí verze Windows – existuje mnoho různých amatérských minidistribucí Windows 98 (bohužel teď je nenajdu).
„spravované přes komplexní objektové rozhraní“ – to nevím, co tím Jakub u Windows myslel. Na WinAPI není objektového nic, to je čisté C.
Až teprve v extrémních podmínkách se ukáže, co vše lze z „jádra“ vypustit, aby technologie stále byla sama sebou.
Takovými podmínkami jsou například mobilní telefony. Java šlape i na telefonech jako jsou několik let staré mobily Nokia. Zde se velikost jádra těžko určí, protože implementace je do jisté míry hardwarová.
Naproti tomu nejmenší mě známý výskyt PHP je verze PHP pro servery Novell, která je osekaná o leccos, a přesto má hlavní knihovna stále několik MB.
Řekl bych, že tím je v tomto bodě jasno – malé jádro a mnoho volitelných knihoven jednoznačně pasuje spíše na Javu.
//Update:// O tom, že Java je skutečně univerzální, se můžete přesvědčit např. na http://www.knihy.cpress.cz/BookDoc.asp?…, kde najdete publikaci pro grafiky, která se věnuje se programování skeneru pomocí Javy.
Syntaxe Java oproti syntaxi PHP:
systémová volání
global
$GLOBALS
, $_GET
, $_POST
,
$_COOKIE
, $_FILES
,
$_ENV
, $_REQUEST
Naopak:
Java syntaxe je jednodušší než syntaxe PHP.
Co se tedy týký připodobnění Javy a PHP k Linuxu a Windows, není mnoho argumentů, proč PHP připodobňovat k Linuxu a Javu k Windows – spíše naopak.
PHP je prostě na ocasu vývoje a s velkými obtížemi adoptuje vymoženosti jiných technologií (OOP, Unicode, výjimky, synchronizaci a sdílení, …) – stejně jako Windows.
Naproti tomu Java je spolu s C# a .NET na špičce vývoje na poli IT, podobně jako Linux na poli OS.
Jako tečku cituji člověka, který má PHP opravdu v malíku (a autora skvělého Texy!) – Davida Grudla:
Programovat v Javě umí kdekdo. O ASP.NET ani nemluvě. Jen v PHP píši skuteční hrdinové. Renesanční bytosti. Fascinující a neskutečně trpěliví lidé. Trpěliví od slova trpět. Třeba jako já.
-- David Grudl, http://latrine.dgx.cz/php-surprise
Hello,
I got over several weeks of stored routines developement, and the most
missed feature was a seamless mechanism for
- calling routines with a resultset in a parameter,
- retrieving a result set coming stored procedure,
- and eventually, for keeping a resultset somewhere without need to create
a table.
All of this would be possible if we could store a resultset in a variable. So I have stated a feature request, not yet submitted to a buglist. First I would like to know others' oppinions and suggestions, because I am not much familiar with other DBMS.
I guess that such functionality would not be easy to implement and is not likely to appear soon. But it would be a giant leap for MySQL's stored procedures programming.
Here is a brief overview:
SELECT * FROM table1 INTO @resultset;
– or – SET @resultset = (SELECT * FROM table1);
CALL StoredProcedure( @resultset );
CALL StoredProcedure() INTO @result; – or – SET @result = (CALL StoredProcedure());
More detailed formatted draft is here: http://ondra.zizka.cz/…ariable.texy
Now – what do you think? Would this ease your SP developement? Is there some better concept?
Thanks for comments.
Když jsem sestavil docela dlouhý, ale přesto neúplný seznam nevýhod PHP, ozvalo se celkem dost lidí s nechápavými dotazy, proč, co a jaktože.
Nevím, jestli má smysl brát PHPčkářům jejich modlu. Někdo by se skoro mohl divit, proč se vlastně do PHPka tak pouštím. Inu, není to proto, že bych ho z duše nenáviděl, či tak něco… Prostě a jednoduše jsem čuchnul k lepšímu a od té doby –mě PHP čim dál více– vidím na PHP čím dál více chyb. A proč tedy píšu tyhle „remcy“, „hemzy“ a „ranty“? Nejspíš abych si ujasnil, zda je na tom PHP opravdu tak špatně.
Učit se novou technologii dá docela práci a chce to svůj čas. Jedním z mých oblíbených citátů z oblasti IT je:
Entrance to the world of Java is a cultural conversion, not a choice of one simple programming language over another.
Vlastně se mi ten citát líbí tak moc, že jej musím uvést v širším kontextu (byť není pro mou oblíbenou Javu nikterak příznivý):
Java Server Pages (link to Jakarta project) is reminiscent in nature of the Microsoft ASP framework, but intended from the ground up for enthusiasts of Java, Enterprise Beans and the whole industry that has grown up around them. A detractor of the juggernaut might describe it as being for people with more money than sense but we try to remain agnostic.
Choosing to use the panoply of tools and techniques engrossed by this world is not a tactical or pragmatic choice of how to get something built but is likely to based more on a strategic perception of how you believe the industry will develop. If all you want is an active website with a database backend, this is going to be overkill unless you already have the range of skills in-house. Entrance to this world is a cultural conversion, not a choice of one simple programming language over another.
– Active Web Sites and Comparison of Scripting Languages (autor neznámý)
Já mám teď poslední prázdniny, a tak jsem se rozhodl využít poslední příležitost k této kulturní konverzi a dělám první vlastní komerční projekt v Javě a Java EE – a musím říci, že zatím ke vší spokojenosti a rozhodně nelituji. V PHP bych to už vzdal.
No a tím se dostáváme k praktickým symptomům nevýhod PHP, uvedených v onom článku. Mám velikou chuť rozebrat je opravdu všechny a dokázat, že k většině tvrzení mám pádný důvod a že se skutečně jedná o nevýhody; za to ale od nikoho na chleba nedostanu, leda by mě zaměstnal marketing Sunu, popřípadě RedHatu, IBM, BEA a dalších velkých hráčů na poli Javy :-)
Pokud chcete rovnou na konec, tedy k hotovému zmrvenému produktu, čtěte Výsledek nasazení PHP v praxi aneb navrch huj, uvnitř fuj.
Ale vezměme to podle seznamu…
PHP: The work-around language
Tohle byl asi hlavní důvod mého postupného rozčarování z PHP.
Když jsem se jako mladý učil PHP z čerstvě vydané knihy Jiřího Koska, PHP mě samozřejmě ohromilo: Psát dynamické webové stránky bylo najednou tak jednoduché. Prostě jste zkopírovali kód z ukázky, poupravili, a jelo to!
Rasmus Lerdorf o historii PHP
PHP se vyvinulo tak, že Rasmus Lerdorf ke své sadě nástrojů Personal Home Page Tools přidával stále další funkce, které uživatelé vyžadovali. Vypráví o tom takto:
„Nevím jak to zastavit, nikdy jsem nezamýšlel vytvořit programovací jazyk […] Nemám ani ponětí o tom, jak se píší programovací jazyky. Prostě jsem vždy jen přidával další logický krok v pořadí.“
Celý rozhovor s Rasmusem Lerdorfem najdete na server ITConversations: http://itc.conversationsnetwork.org/…etail58.html.
A přesně ve stejném duchu vývoj PHP pokračuje dodnes – That's the PHP way.
Jak se postupem času vyvíjíte, začnou vám některé věci dost vadit. Při psaní prvního „svého frameworku“ objevíte nepříjemné chyby v návrhu OOP a při použítí referencí se objevují záhadné chyby. Zejména pokud paralelně programujete v nějakém vyspělém jazyce s dobrým návrhem (Java, C#, JavaScript), časem se vám ztratí úsměv z tváře, čím dál častěji kroutíte hlavou a nakonec vzteky bušíte do stolu a kontrolujete blogy vývojářů PHP, jestli už se náhodou nechystají tu kterou pitomost z jazyka odstranit – a zase vás zklamou:
FALSE
(vypadá
to na zásadní nepochopení ze strany autorů, k čemu jsou výjimky)integer
se bude chovat stále stejně pitoměNaštěstí si ještě zachovali dost rozumu na to, aby neimplementovali úplné hovadiny, pravděpodobně proto, že se chystají i nadále jít cestou Javy a zavést deklarace.
If something isn't done soon, then more and more coders using PHP will move on to Ruby and Python and PHP will become the new Perl. I can hear it now, „What ever happen to PHP?“ or „Pfft, no one programs in PHP anymore!“ or „Man, I had to maintain legacy PHP application!“
-- Jacob Santos, PHP is turning into the Classic ASP
„That's the PHP way.“
A co některé, rovnou si je vyjmenujme:
Spoustu PHP skriptařů si nemůže vynachválit, jak moc je
Array()
univerzální – můžete jej použít jako pole, jako
hash, jako frontu, jako zásobník, můžete s ním vybudovat vícerozměrné
pole, ale i strom nebo obecný graf.
Jenže k čemu to je? Kdo potřebuje datový typ, který je zároveň fronta a zároveň strom? Kdo potřebuje indexovat v jedné struktuře jak podle pole, tak podle čísel? Jenom programátorská prasata. (But that's the PHP way).
Slušný programátor, který má ohled na ty, co budou kód po něm číst (včetně jeho samotného), po provedení analýzy a vytvoření návrhu pro každou třídu „entit reálného světa“ vyskytující se v návrhu vytvoří v programovém modelu odpovídající třídu a zachytí jejich vzájemné vztahy.
Ne tak programátoři v PHP. Zde je slušností co nejvíce poctít svátost
boha Array
e a pokud je to byť jen trochu možné, pak jej
použít, nejlépe hned v několika významech. Co na tom, že chceme
reprezentovat strom obsahující objekty, které mají identifikátor a kolekci
čísel? Jednoduše uděláme schizofrenní „Array()“, který má pod
indexem ["id"]
identifikátor, pod indexem ["numbers"]
další Array
s čísly a pod číselnými indexy ukryjeme potomky
uzlu. Nebo obráceně? To je jedno… That's the PHP way!
FALSE
– taktní, diskrétní a nevtíravé
(ne)oznámení chyby.Pokud existuje sebemenší šance, že dojde k chybě, slušný programátor vyhodí výjimku, kterou při pozdějším volání metody prostě nelze opomenout a musíte ji ošetřit – jinak se vám kód nepřeloží.
PHP skriptař však po vzoru nativních PHP funkcí vrací
NULL
,1, 2, 3, 4
nebo opačnou hodnotu některého parametru,FALSE
,TRUE
.Z těchto možností vybere náhodně. That's the PHP way!
Snad nikdo nepoužívá trigger_error(...)
– jednak je to
víc písmenek než return FALSE;
a jednak by se pak někde musel
mořit se set_error_handler()
, a to je kopice psaní… radši
vrátíme ten fóls
. O tom, že později se na kontrolu chybové
návratové hodnoty vykašle, nemusíte ani chvilku pochybovat; a pokud přeci
jen, tak nejspíše vyplodí nějaký bug kvůli typové konverzi.
Ti opravdoví PHP experti (řekněme PHP-developer senior) však využijí pokročilou funkci jazyka, a to jsou reference! Jednoduše narvou návratové hodnoty do parametrů, a programátore, hledej:
If the value returned in errno is 0 and the function returned FALSE, it is an indication that the error occurred before the connect() call. This is most likely due to a problem initializing the socket.
Kde já jsem tohle viděl? Á, už vím! Einstein kdysi vymyslel takovou logickou hru:
Je pět pět parametrů, každý nese hodnotu nějakého typu. Když návratová hodnota boolean a v prostřední hodnotě je nula, potom včelař nebydlí v modrém domě. Nastal chybový stav?
Skutečně by nebylo lepší toto?
try{ fsockopen(...); } catch( IOException ex ){ ... }
Programátor v objektově orientovaném jazyce, pokud potřebuje z funkce více informací, než stačí pokrýt skalární hodnota jednoho typu, vytvoří si pro přenos informace třídu a vrací si objekt daného typu. Konec konců, když už se mu takový objekt odněkud vrací, pravděpodobně se jedná o třídu entit z reálného světa a tedy ji využije i jinde v modelu aplikace.
Lepič PHP kódu však má k dispozici mnoho úžasných vlastností jazyka PHP, jako třeba dynamickou typovost, a tak třeba jednou vrací string a jindy integer.
A pokud by nestačily ani všechny typy, co jich PHP má, tedy skalární
hodnoty různých typů v kombinaci s FALSE
a null
,
použije se prostě Array
jako hash a do něj se pod nějaké
indexy (někdy
stringy, někdy
divoké stringy, někdy
čísla – to je fuk) narveme, co chceme.
That's the PHP way.
V jednom nejmenovaném velkém českém portálu jedou doteď na PHP 4. „Ježiši!“, říkáte si. A máte pravdu! Jsou tam snad masochisti? Proč??
Odpověď je snadná:
Protože kdysi jakýsi manažer učinil rozhodnutí, že pojedou na PHP. Rok po tomhle rozhodnutí ho vyhodili a dodnes jeho volby litují, když při pohovoru musí uchazeče zkoušet z PHP 4 a jeho chyb v návrhu (vlastností, chcete-li) a místo přepisu do PHP 5, který zoušeli, ale stálo by je to několik měsíců přepisování (s výhledem dalšího přepisu do PHP 6, 7, 8… se již raději poohlížejí po technologii, kde zpětná kompatibilita není jen prázdná fráze.
Takových příkladů by se jistě dalo najít víc, ale asi to nemá smysl vypočítávat, protože zase můžete kontrovat Wikipedií a dalšími úspěšnými weby, které zůstávají u PHP (aspoň u prezenční vrstvy).
Obvyklá odpověď PHPčkářů je, že pokud by člověk nepsal jako prase, tak kód bez problémů běží i na nové verzi. To je samozřejmě naprostý nesmysl, který může pronést jen někdo, kdo se v používání PHP nedostal dál než k lepení ukázek zkopírovaných z manuálu PHP. Už jen změny v objektovém modelu a práci s referencemi činí ze starého kódu odpad, který je natolik nekompatibilní, že spíš než refaktorizace se vyplatí redesign a nová implementace.
Zde je to celkem jasné, každý lepší skriptař PHP už se potýkal
s otázkou zapnuté / vypnuté direktivy magic_quotes_gpc
. Vstup
se zpracovává ještě před spuštěním skriptu, tudíž direktivu lze
ovlivnit pouze mimo kód PHP, a ne vždy tu možnost máte.
U lepších technologií je dán standardní způsob distribuce projektu, který definuje prostředí, do kterého aplikaci vkládáte, a jeho součástí je i možnost nastavit prakticky cokoliv v rámci zdrojových souborů projektu.
Ano, existuje sice jakási extenze „BPEL“, a přiznávám, že jsem ji nezkoušel. Ale po mých zkušenostech s takovýmito hračkami bych jako vždy došel zklamání, protože by to jednak nepodporovaly hostingy, a jednak bych to nerozjel na své vývojové platformě.
Tohle je opravdu obrovská ostuda PHP a jeden z bodů, který dokazuje, že PHP je několik let vývoje za ostatními technologiemi.
Další obrovská ostuda a důkaz zaostalosti PHP; fakt nechápu, že to nezabudovali již do verze PHP 3.
Velice často zmiňovaná vada, vadí i těm nejzamilovanějším PHPčkárům (a snad i Jakubovi Vránovi :-)
Zkrátka chybí objekty pro reprezentaci tříd, pokud vím. Nemůžu tedy udělat např.:
public createObjectOfClass( Class cls, HashMap params ){ cls.construct( params ); }
Odkazování se na třídu pomocí stringů je jen work-around („That's the PHP way“) a při práci v IDE je dost napřekážku.
Pokud chci předat nějaký objekt a jeho metodu (ve smyslu delegáta z C#), v PHP se to dělá takto:
...MyFunc( Array( $myObject, "thatObjectMethod" ) );
Tahat do mechanismu volání metod Array
je opravdu škaredý
work-around („That's the PHP way“™) a ukazuje na nedospělost OOP
syntaxe PHP.
Je pravda, že oproti katastrofálnímu stavu z PHP 4 je v PHP 5 situace mnohem lepší; stále však zůstávají nečekané a o to zákeřnější seky. Asi před půl rokem jsem jeden řešil s kamarádem na IM, když to najdu, přidám.
Týkalo se to předávání pole. Jak jistě víte, pole není objekt, proto pokud jej chcete ve funkci měnit nebo chcete zamezit (mělkému) kopírování, je třeba jej předat referencí. Stejně tak jej musíte referencí propagovat do dalších kroků zpracování. Jenže reference stále fungují stejně jako v PHP 4, tedy tak, že v tabulce proměnných vzniká nový alias pro stejnou proměnnou. Tento alias zůstává v tabulce i po opuštění funkce, a po jejím opětovném volání a přiřazení reference proměnné se pole zpracovávané v předchozím volání přepíše tím, které zpracováváte nyní.
To je tak nechutná chyba, že tohle byl jeden z posledních hřebíčků do rakve PHP. Není to jediná chyba, a pokud jste někdy v PHP zkoušeli vyvinout něco složitějšího, jistě jste narazili na podobnou.
Vzhledem k tomu, že ani v PHP 6 nebude Array
normální
objekt a opět budou přítomny reference, vede mě to k závěru, že stejné
chyby budou i v této verzi („Because that's the PHP way.“)
Výsledkem je mimojiné toto:
strtoupper(str_replace("!!",".",str_replace("ahoj","nazdar",strtolower(trim(" Ahoj lidi!! "))));
oproti:
" Ahoj lidi!! ".trim().toLowerCase().replaceAll("ahoj","nazdar").replaceAll("!!",".").toUpperCase();
Je to asi jako v přirozeném jazyce říkat:
Chci zvětšit písmena v tom, co vznikne, když nahradím dva vykřičníky za tečku v tom, co vznikne, když nahradím „ahoj“ za „nazdar“ v tom, co vznikne, když převedu na malá písmena to, co vznikne, když odeberu netisknutelné znaky z okrajů " Ahoj lidi!! " '
místo
Vezmu " Ahoj lidi!! „, z okrajů odeberu netisknutelné znaky, převedu to na malá písmena, "ahoj“ nahradím „nazdar“, dva vykřičníky nahradím tečkou a převedu to na malá písmena, a to je výsledek.
U abstraktních datových typů Javy (zahrnující seznam, množinu, mapu, atd…) spatřuji hlavní výhodu v minimalizaci rozhraní daného abstraktního typu a v tom, že jsou definované jako rozhraní, nikoliv jako jediná implementace, protože to značně ulehčuje práci programátorovi různých knihoven.
Nedávno jsem si například během asi půl hodiny naprogramoval Mapu, která má jako backend tabulku v transakční databázi, a můžu jí používat všude, kde někdo očekává jako parametr Mapu.
To by v PHP s Array
udělat nešlo – jedině na úrovni C
implementace PHP. Šlo by to také naprogramovat jako třídu – ale potom to
zas nebude kompatibilní s Array
a nepůjde na to použít např.
ksort()
.
Má vůbec cenu, abych pokračoval?
Možná stačí už jen předat slovo…
Zde najdete divokou směsici nápadů a myšlenek, od všednich přes
technické po ryze filozofické, od vážných po naprosté bludy.
Vše bez záruky.
Most used passwords from igigi's web.
A simple test performed on SSD disk Corsair X32.
Nemůžu si pomoct, ale v Českých Budějovicích mají radní opravdu zvláštní priority.
Nedávno rozhodli, že obyvatelé města ze všeho nejvíce potřebují splavnit úsek řeky Vltavy od centra města k Hluboké nad Vltavou. Nechali tedy za desítky miliónů vybagrovat bahno ze dna. Potom přišla povodeň, která vybagrované haldy opět spláchla do řeky.
A nyní, když se v rozpočtu nedostává peněz na „důležité“ věci jako je městská policie (o které se dozvíte na stránkách mestskapolicie.unas.cz), radní zruší všechny dva noční autobusy.
Opravdu geniální!
Ještě štěstí, že už v tom kocourkově nežiju.
Prosím všechny novináře, zejména ty, kteří píšou úvodní hlášky ke zprávám, aby se vzdělali v pojmech levice a pravice.
Pravice, to jsou lidé, kteří požadují menší zásahy státu a větší svobodu jednotlivce. Krajní pravice jsou anarchisti.
Levice, to jsou lidé, kteří se o sebe nedokážou sami postarat, nezvládají samostatně myslet a hospodařit s vlastním majetkem, a potřebují nadiktovat, co je dobré a co špatné. Krajní levice jsou komunisté. Když se k tomu přidá krajní nacionalismus, jde o nacisty.
Zejména Česká televize soustavně uráží všechny svobodomyslné lidi, když ultralevičáky – tedy nacisty – řadí k jejich – zcela opačnému – názorovému proudu.
Nedá mi to nereagovat na výsledek krajských a senátních voleb. A vzhledem k tomu, že se jedná o osobní web, můžu si zde dovolit silná slova.
Každý, kdo volí ČSSD, je buď hodně hloupý a věří slibům této mafiánské strany, nebo je líný, nechce se mu pracovat a věří, že ČSSD zde zakonzervuje zbytky socialismu, nebo je součástí kolotoče a veze se v tom s nimi.
ČSSD je prostě strana, jejímž programem je zneužít ty méně inteligentní voliče jako výtah k penězům všech. Bohužel zde asi pláču na špatném hrobě, protože nepředpokládám, že kdokoliv dost inteligentní na to, aby používal internet a zajímalo ho programování, by volil ČSSD. Nicméně všechny voliče ČSSD varuji, že jestli zvolí ČSSD i do parlamentu, nastane další vlna odchodu inteligence národa do zahraničí, a pro dementy, kteří volí ČSSD, tu opět zbyde méně lidí, kteří na ně budou pracovat.
yoimgz.com
Uživatelům MSN protokolu dnes chodí URL na server yoimgz.com
.
Na nic neklikejte, jedná se o phishing.
Today, users of MSN communicator receive links to server
yoimgz.com
. Don't click it and do not enter anything – it's a
phishing.
Kdo si má pořád pamatovat, jak se to šmodrchá? Já si pro jistotu dal návod na uvázání kravaty na web.
Své dojmy z přechodu na Linux v podobě Ubuntu 8 popisuji zde.
Jabber plugin for Miranda seems not to work with 64-bit version of Windows
XP.
However, Jabber addon in the developement branch, Miranda 0.8, works fine.
The same for Linux x64 and Wine, which supports only 32-bit applications
(AFAIK). Download here: Miranda
IM developement version
I'm looking for the music used in ATI demo application „Rendering With Natural Light (RNL)“ (a real-time implementation of Paul Debevec's 1998 Siggraph paper), available at http://ati.amd.com/…s/r9700.html.
Can anyone identify the tune?
Křesťané (a kdoví kdo ještě) mají jako součást svojí víry dogma, že nastane soudný den, při kterém přijedou čtyři jezdci apokalypsy, činy každého jednotlivce budou sečteny a ty hodné čeká věčný život.
Jako i ostatní věci velmi obrazně popsané v Bibli se i tato dá vysvětlit všelijak. Často se v historii potvrdilo, že mnoho „proroctví“ vzniklo buď špatným překladem, nebo pokřivením a antidatováním (ať už mylným či záměrným) popisu skutečných událostí.
Dovedu si docela dobře představit, význam soudného dne, sečtění činů a věčný život ve skutečnosti reprezentují osudný den, sečtení činů ve smyslu dosavadního vývoje lidstva a jeho aktuálního stavu, a věčný život je ve skutečnosti naděje na udržitelný rozvoj civilizace.
Mnoho textů v Bibli pochází od židovských i jiných filozofů, kteří se jistě zabývali i otázkou, v jakých kolejích se má lidstvo ubírat, aby nezahubilo samo sebe. A tak vznikla myšlenka, že může nastat situace kritická pro celé lidstvo, osudný den, kdy každý čin ve prospěch lidstva může mít vliv na další vývoj. A proto by každý měl konat s vědomím, že jen dobré činy umožní civilizaci v onen osudný den přežít, a tedy věčný život bude umožněn jen těm lidem (= takové společnosti), kteří budou jednat v její celkový prospěch.
Nejsem ani amatérský teolog, ani záhadolog, jen mi s blížícími se
státnicemi přišla na mysl apokalypsa :-)
Pokud vás toto téma zaujalo, dobrý článek, potažmo web najdete zde: http://www.myty.info/view.php?…
Google umožňuje vyhledat frázi uzavřením do uvozovek. Fráze znamená, že se slova v dokumentu vyskytují ve stejném pořadí, jako v uvozovkách. Bohužel Google při tom ignoruje výskyt čehokoliv jiného, třeba interpunkčních znamének.
Chtěl jsem vyhledat Pavla Hejtmana, odborného asistenta
z Jihočeské Univerzity. Co čert nechtěl, hejtmanem Karlovarského kraje je
jakýsi Josef Pavel, a web je proto plný výskytů posloupností slov
typu „…řekl Josef Pavel, hejtman Karlovarského kraje.“ Když potom do
Google zadáte "Pavel Hejtman"
,
veškeré výsledky (kam až jsem vydržel proklikávat) odkazují právě na
takovéto texty, a Pavel Hejtman jako by neexistoval. Naštěstí Pavel Hejtman
je odborný
asistent s akademickým titulem, proto je možné jej vyhledat aspoň
pomocí Pavel
Hejtman PhDr.
Hnutí Nenásilí informovalo o podpoře amerického astronauta v boji proti radaru v Brdech. NASA údajně uskutečníla mimořádný neplánovaný let na Měsíc, aby zde Neil Armstrong s dvěma členy vesmírného výboru hnutí Nenásilí mohli vyvěsit Bílou vlajku, symbolizující odpor proti imperialismu a proti závodům ve zbrojení se strany států pod vedením pitomců a v budování obranných systémů na straně zemí řídících se zdravým rozumem.
Více informací najdete na adrese http://www.nenasili.cz/…-radaru.html.
Vždy po koupi nového počítače si říkám, že je škoda, aby taková mašina běžela jen tak. Pustím tedy SETI at home. Navíc mi to v zimě docela pěkně vytopí pokoj.
Po nějaké době mašina zastará a já si říkám, zda přínos projektu SETI ospravedlní energetickou (a tedy i ekologickou) zátěž. Jaký je vlastně přínos projektu SETI?
Co se týká samotného primárního účelu SETI@home, tedy hledání mimozemské inteligence, zatím kde nic, tu nic. Zatím tedy nevíme nic – ani, zda mimozemská inteligence existuje, nebo zda neexistuje. V tomto směru tedy zatím výsledky žádné. (Je také otázka, co skutečně projekt zpracovává – podle konspirační teorie mého kamaráda luští odposlechy systému –ECHOLON– ECHELON.)
Ospravedlňují tedy dosavadní výsledky mojich cca 200 W? Osobně jsem v tomto hodnocení trochu náladový. Nedávno jsem od SETI@home přešel na prokejt Rosetta@home. Po pár měsících mi ale provozovatelé SETI@home poslali mail, že nedávno jsem z projektu odešel, ale teď na přijímači v Areceibo pořídili zcela nový dekodér či co, který je schopný nahrávat až ze sedmi lokací na obloze najednou, a proto potřebují každý TerraFLOP. No budiž, znělo to tak přesvědčivě a prosebně, že jsem se nechal „ukecat“ :-)
Takže momentálně mám SETI@home puštěné 24 hodin denně, snad to k něčemu bude. Projekt Rosetta mě moc nepřesvědčil; SETI sice nemá žádné výsledky, ale aspoň o tom pravidelně a na poměrně slušné úrovni informují. Rosetta nemá žádné výsledky, ale to jen usuzuji z toho, že na webu projektu nejsou informace o tom, zda něco objevili, či nikoliv. Proto je pro mě projekt SETI@home důvěryhodnější a „výpočtuhodnější“.
Prvně, omlouvám se několika promile lidí, kteří operu používají, například Zdeněk Roule, Satan a jejich přizpůsobivé okolí (konečně jsem je oba dostal na internet :-) )
Nicméně, z perspektivy tohoto grafu Operu skutečně nikdo nepoužívá.
Velmi krátce jsem se zamyslel, proč jsem ji kdysi nezačal používat i já, ještě v době, kdy Mozilla suite nebyla tak dokonalá, a Opera již byla zadarmo.
Takže, důvod 1) padl, důvod 2) se drží a možná padne, důvod 3) will probably prevail forever. Nicméně pokud má Opera aspoň nahradit MSIE (libovolnou existující verzi – všechny jsou špatné), potom jí držím palce. Snad se někdy dostane aspoň na rozlišovací úroveň onoho grafu :-)
//Update:// Neoblíbenost Opery je tématem na http://www.lupa.cz/…zase-na-nic/.
//Update:// Také tématem na http://pixy.cz/…ivate-operu/
a na http://www.misantrop.info/586891-pera.php.
Před časem jsem seznal, že projekt SETI@home již funguje dost dlouho na to, aby přinesl aspoň „nějaké“ výsledky. Zatím však kde nic, tu nic. Ačkoliv existenci ufonů připouští již i Vatikán, projekt SETI@home zatím církvi radost nedělá – žádní ufoni (přesto že Jiří Paroubek nabídl marťanům koaliční dohodu), žádná komunikace s blízkými hvězdami, ba ani prachsprosté podezřelé pípnutí nebylo identifikováno. Rozhodl jsem se tedy, že nebudu nadále plýtvat cca 120 W na bezvýsledné výpočty a projekt opustím.
Jenže, po pár měsících mi napsali opravdu dojemný dopis, no posuďte sami:
Dear Astar Seran:
We'd like to invite you to reconnect with SETI@home. Our records show that you've been with SETI@home since 09 February 2008, but it's been 104 days since you last returned a work unit. We want you back, and here's why:
These are exciting times for SETI@home. Last year we implemented a new SETI@home data recorder at the Arecibo radio telescope in Puerto Rico. This recorder is attached to a state-of-the-art multibeam receiver, so we can now measure signals from 7 positions on the sky at once, with greater sensitivity to weak signals compared to the data from the flat feed antenna we've used since 1999. We've greatly increased the sensitivity of our data analysis, and the likelihood that we'll find the first signs of extraterrestrial life. We're also close to releasing a second application, Astropulse, which will look for extremely short pulses of astronomical (and possibly intelligent) origin.
With these new developments comes an increase in required computing power, for which we depend on people like you. We hope you will consider signing back on with SETI@home, and help in this wonderful scientific venture.
…
Jistě uznáte, že když nainstalovali tak skvělý přijímač, musím jim dát ještě šanci. Zvlášť jako osoba spjatá s masovým rozšířením SETI@home v ČR :-)
Kdo si vzpomene, kde byla tato ikonka vystavená a přilákala kolem 20 000 návštěvníků?
Je s podivem, že při vší té obsáhlosti webu, potažmo internetu, na Google stále nenajdete některé (zcela nezbytné) fráze.
Již se mi stalo několikrát, že jsem zadal frázi, u které jsem se bál spíše velkého počtu odkazů, ale rozhodně by mě nenapadlo, že se v indexu Google (který má nejobsáhlejší index ze všech vyhledávačů) vůbec nevyskytují.
Tak například:
Zajímalo mě, proč ředkvičky pálí. Jediný trochu relevantní odkaz vede na otázku diskutérky –
„Proč pálí ředkvičky jak sviňa? Já myslela, že to pálí proto, že jsou nerovnoměrně zalité. ale to já nemám. Nuže?“
Takže vím, že ředkvičky nepálí proto, že by Tigra neuměla zalévat zahradu.
Napadlo mě, že by to mohlo být omezeností českého internetu, kde najdete gigabajty diskuzí o tom, jestli je Paroubek blbec nebo velký blbec, ale o ředkvičky se nezajímá. Zkusil jsem tedy do Google zadat radish burns, radishes burn, why radishes burn. Bez výsledku.
Potom jsem si vzpomněl, že na otázky by se měl specializovat server Ask Jeeves. Zkusil jsem se ho tedy optat: Please, Why radishes burn? A ejhle, pod zadávacím polem mám nápovědu – mám se zeptat, Why Are Radishes Hot. Jenže na tento dotaz opět dostávám odkazy na stránky, které otázku stavějí takto:
Q. What causes my radishes to be „hot“?
A. The „hotness“ of radishes results from the length of time they have grown rather than from their size. The radishes either grew too slowly or are too old.
Nebo:
Q: What makes radishes hot? My radishes this year are almost too hot to eat.
A: Radishes get hot for a number of reasons. If they are too old they are hotter, and if they were grown under low fertility or if they got too dry, and their growth was not as fast as it should have been, then they turn hot.
Takže jsme zase tam, kde jsme byli. Já chci vědět, která látka v ředkvičkách pálí. Vite někdo, proč ředkvičky pálí?
Update: Tak výsledky vyhledávání se lehce změnily a do popředí se dostala odpověď Emeritního profesora Zahradnické fakulty Mendelovy zemědělské a lesnické univerzity Karla Kopce z Lidových novin:
Ředkvičky při krájení nebo rozkousání uvolňují látky, které jim dávají typickou vůni a chuť i větší či menší štiplavost (pálivost). Ředkvičky totiž obsahují glukozionoláty, z nichž se v porušených buňkách uvolňují aromaticky i chuťově výrazné složky – izothiokyanáty. Je jich řada a kromě chuťových vlastností mají také antimikrobiální účinky a výrazný vliv na lidské zdraví. Přispívají ke zlepšení imunity, omezují riziko některých chorob, podporují stravitelnost ostatních pokrmů. Právě proto se doporučuje zvýšit konzumaci ředkviček a ředkví až na jeden kg ročně.
Tak super, už to vím a universum se opět dostává blíže k rovnováze.
Další věcí, která mě zajímala, je výhřevnost vosku. V domě nám už netopí, okna profukují, a tak se stane, že mám na pokoji 17 stupňů i při neustále puštěném počítači. Kamarád mi poradil, že když nechá na pokoji hořet čajovou svíčku, tak během zhruba čtyř hodin, po které svíčka vydrží, vzroste teplota v pokoji tak, že musí větrat. Jenže jeho pokoj má 16 m2. Já jsem zapálil pole 6×6 čajových svíček, ale teplota vzrostla jen o půl stupně za hodinu. Proto jsem si chtěl ověřit, jak by se měla teplota vyvíjet teoreticky. Bohužel, výhřevnost vosku jsem na internetu nenašel. Stačila by mi jen orientační… nevite? :-)
V teorii formálních jazyků se vyskytuje pojem „Vícerozměrné jazyky“. Pokud si ale tento termín v češtině zadáte do Google, mlčí.
Je třeba zadat „multidimensional language“ a dozvídáme se, že vícerozměrný jazyk je takový, jehož výrazy jsou tvořeny ve více rozměrech. Nic víc jsem ale nenašel – google dává pořád dokola tuto stejnou slovníkovou definici. (Kandidát na pojem ve wikipedii, nechcete se toho někdo ujmout a vytvořit wiki článek?)
Až do zaindexování tohoto článku se na Google vyskytuje jediná stránka na tato dvě slova a žádné stránky pro celou frázi. Muška košovka je moucha octomilka (viz Octomilka na Wikipedii).
Další nenalezené vyhledávané fráze možná přibudou časem. Teď mě jen zajímá, kolik lidí na světě je kdy bude vyhledávat.
Ještěři z pekel hledají programátora na pozici analytik-programátor.
Hledáme: Nekreativního otrockého programátora, nejlépe s čipem v těle.
Nabízíme: Jídlo, šaty a vzduch.
Popis pozice:
Více informací na www.vesmirni-lide.cz.
Opět se blíží doba, kdy si diplomanti musejí nechat svázat diplomovou práci. Chtěl bych tedy všechny studenty varovat:
Nedávejte si diplomku svázat k firmě ZDECO!
Nejsem sám, kdo měl s touto firmou, sídlíci Na Sadech, potíže. Vazbu jedné DP zkazili (nevložili zadání), druhou zase svázali tak, že papíry pár minut po převzetí vyjely z desek. Tím se pochopitelně papíry zmačkaly a diplomka zničila. Chtěl jsem tedy vrátit peníze a uhradit škodu. Byli proti, jediné jejich přípustné řešení bylo, že mi do stejných desek znovu secvaknou nové listy. Nefér firma, sdružení obrany spotřebitelů na ně.
Klíčová slova: svázání, vazba, diplomová práce, diplomka, České Budějovice, desky, Jihočeská univerzita, ZDECO, Na Sadech.
Zajímavé. Spammeři procházejí literárním vývojem.
Mnozí si pamatují, že na začátku spamu, kdy jsme ještě maily stíhali třídit ručně bez použití filtrů, chodily suché výzvy typu „Enlarge your penis“. To nemohlo zaujmout snad nikoho kromě debilů, na které ale asi kampaň mířila, takže vpořádku.
Později první nastala vlna obrany proti spamu, založená na primitivní metodě „předmět / odesilatel / zpráva obsahuje slovo …“ → letí do koše. Krásné, jednoduché, ale fungovalo nanejvýš pár měsíců.
Protože poté začali spameři nahrazovat různé znaky kombinacemi jiných,
které je připomínají. Nejprve blízce
(„EnIarge your penis
“), potom vzdáleně („Buy cheap
V|agra“). Potom se spameři rozdělili na dvě větve – ti
sofistikovanější, pro něž je spam výnosným obchodem, začali používat
pokrokové metody. Ti méně pokrokoví zůstali u staré metody, jen ji
dotahovali do krajností: Bai C|-|34-p Uu|aaaaagg RRRaaa!
,
C|a L|S
, kde ještě tušíte, že si máte nutně koupit levnou
ViiaaggRRuu nebo Cialis, ale když mi pak příjde výzva,
uh Buoy Cheap See - Alice
, už je to skoro jazykový hlavolam.
Takový spam už přece není pro blbce :-)
Ovšem i na takové se později bayesovské filtry a antispam algoritmy naučily, a tak těm lepším spammerům opět nezbylo, než sáhnout k jinému kroku: Omezit kvantitu a zvýšit kvalitu.
A tak mi již denně nechodí dvacetkrát
Unrecognizable Rolex replica
, ale mám ve schránce první
nesmělý náznak literárního útvaru:
Release your inner dragon with the help of bluepill!
Mmm… představil jsem si sám sebe jako mužskou verzi té žluté ninja-holky z Kill Billa, jak ve stylu Jamese Bonda zachráním nějakou šikmookou kočku a pak na ni vypustím svého „vnitřního draka“ :D Plný očekávání dalšího kvalitního obsahu jsem mail otevřel… ale zklamal mě. Nedočkal jsem se ničeho víc než
If you cannot act the way you want, take some blue-coloured pills!
Tak to je, pánové, trochu slabé. Až mi napíšete aspoň desetistránkovou motivační povídku, můžeme začít vyjednávat o nějaké té cheap částce – třeba dva centy za příběh. Do té doby vydělávejte nadále na blbcích, co koupí a sní „modré pilulky“ z pochybných zdrojů.
Problémem mezihvězdného cestování je nutnost těleso urychlit na rychlost přijatelnou k dostatečně rychlému přesunu, a potom jej zase zabrzdit. Co kdybychom ovšem využili princip kolotoče?
Mohli bychom v jednom bodě (třeba i našeho prostoru) „upoutat“ „lano“, na konec lana připoutat těleso, které má cestovat, přemístit jej (stále v našem prostoru) na vzdálenost lana, a potom ho začít roztáčet. To by znamenalo udělit mu takovou energii směrem do jiného prostoru, která by stačila k jeho přemístění do výchozího bodu opisované „kružnice“. Po jeho opětovném objevení v našem prostoru ve výchozím místě bychom mu udělili další impulz, a takto jej postupně urychlovali.
Po dosažení určité rychlosti oběhu by už byl problém jenom
„nastoupit“ a „vystoupit“. Jsou dvě možnosti:
Jednak postavit obíhajícímu „dopravnímu prostředku“ náklad do cesty.
Vypadalo by to asi tak, jako kdyby bagr jel nadzvukovou rychlostí a někde
cestou nabral písek. To by jistě nákladu příliš neprospívalo.
Druhou možností je před nástupem náklad urychlit ve směru zbylého
rozměru na rychlost dopravního prostředku. Energetická náročnost by ale
byla asi stejná, jako na zrychlení a ubrždění nákladu při přímé cestě
naším prostorem. Je celá tato teorie tedy k něčemu?
„Dopravní prostředek“ by naším prostorem procházel jen velmi krátkou dobu. Problém urychlení nájkadu by tedy bylo vyvinout dostatek energie v krátkém čase. Co ale udělat další takové kolečko, tentokrát menší, a jen za účelem naložení nákladu? Jako oběžný bod by mohla sloužit nějaká těžká hvězda.
Celé to pochopitelně počítá s rozvinutým dalším rozměrem, nikoliv smrsknutým, jako teorie superstrun.
A teď hlavní otázky:
Motiv zápisu tohoto s největší pravděpodobností blábolu hledejte v teorii myšlenkonů Terryho Prachetta :-)
Hledám řešení této otázky:
Máme N-rozměrný prostor. Kolik (N-1)-rozměrných prostorů rozdělí onen prostor na X N-rozměrných podprostorů?
Nevím, kde hledat odpověď. Víte (ji) někdo?
//Update:// Mám řešení. Dík patří Karlovi Kyrianovi za pomoc. Řešení jsem zpracoval ve svojí diplomce.
V jednorozměrném prostoru dělí každá nadrovina (bod) prostor přímky tak, že přibude další jeden podprostor. Ve dvourozměrném prostoru vzniká s každou přidanou přímkou vždy o jeden prostor více než s předchozí. Ve trojrozměrném prostoru potom vzniká s n-tou přidanou rovinou o tolik více podprostorů, kolik podprostorů vzniklo ve dvourozměrném prostoru při přidání n-té přímky. Obecně potom pro N-rozměrný prostor platí, že přidáním n-té nerovnoběžné nadroviny přibude tolik podprostorů, kolik celkem jich přibylo rozdělením N-1-rozměrného prostoru n nerovnoběžnými nadrovinami. Rekurentní výpočet by potom mohl vypadat takto:
Případně přímý výpočet vypadá takto:
Potřebujeme ovšem znát opačný výpočet – známe dimenzionalitu prostoru, víme, kolik chceme výsledných podprostorů, a chceme vědět, kolik nadrovin jej takto rozdělí, resp. kolik máme použít neuronů na první vrstvě. Výpočtem se zde nebudeme podrobně zabývat, stačí nám jeho odhad. Výše uvedený výpočet se dá odhadnout jako
Vyjádření n potom vypadá takto:
kde (pro připomenutí) n je počet nadrovin, N je dimenzionalita prostoru, p je počet podprostorů a e je Eulerova konstanta.
Ve výpočtech zacházíme s dimenzionalitou prostoru. Ta je rovna počtu vstupů sítě.
Chodí nový ICQ phishing: New ICQ phishing appeared:
Hello,Your NEW ICQ password is: A4T4jXMh
Remember – your ICQ password is case sensitive.
After you login to your ICQ number, you might want to consider changing your password to a more complex one.
Your new password must contain 6–8 characters. It should include English upper and lower case letters and numbers.
Try to select a random password that will be hard for others to guess. (Example: …)
Here's how you change your password: In ICQ 5: Click the Main Menu button > Preferences and Security → Password. In ICQ Pro versions 2000a through 2003b: Click the ICQ/Main button->Security & Privacy Permissions->Password. In ICQ 6: Click the Main menu button > select ‚Options‘ > under ‚Privacy & Security‘, select ‚Privacy‘ > click ‚Change my password‘.
Heslo si pochopitelně neměňte, buď je to kachna, nebo podvod. Of course, do not change the password – it's either a fraud or an hoax.
V sekci Programování najdete texty, které vyprodukuji na toto téma. To zahrnuje nejen jazyky a technologie jako PHP, Java a J2EE, C# a .NET, XSLT, SQL, ale i různá paradigmata (OOP, AOP) a oblasti výzkumu (neuronové sítě).
alternatives
and Gentoo's
eselect
)# Will clear all the fs cache. Do a ’sync’ before to flush more caches. echo 1 > /proc/sys/vm/drop_caches
http://mtj.wordpress.com/…-read-cache/
.java
zdrojáku na .class
a
jeho spuštění.<!--
-->
md5()
etc.Všechen SQL kód potřebný ke vytvoření databáze je v adresáři sql/ v těchto souborech:
JR - Procedury a funkce pro DP.sql
JR - Tabulky s importovanými daty pro DP.sql
JR - Tabulky s převedenými daty pro DP.sql
NN - Procedury a funkce pro DP.sql
NN - Tabulky s daty.sql
Soubory s předponou NN
obsahují SQL pro rekonstrukci
implementace neuronových sítí. Soubory s předponou JR
obsahují SQL pro vytvoření databáze jízdních řádů a příslušných
uložených procedur.
Další dva soubory obsahují ukázkové naučené neuronové sítě:
JR NN - Naučená síť pro zastávku 5.sql
NN - Naučená síť XOR.sql
Nejprve je třeba nainstalovat standardní distribuci MySQL 5.0 nebo vyšší (stahujte zde).
Poté je třeba vytvořit dvě databáze a nastavit uživatelská práva pro
uživatele, který je bude používat. Následující kód vytvoří databáze
neural_network
a jizdnirady_cb
a nastaví veškerá
práva k nim uživateli OndrejZizka
, který se může připojit
odkudkoliv (‚%‘):
CREATE DATABASE neural_network; CREATE DATABASE jizdnirady_cb; GRANT ALL ON neural_network.* TO OndrejZizka@'%' IDENTIFIED BY 'BezpecneHeslo'; GRANT ALL ON jizdnirady_cb.* TO OndrejZizka@'%' IDENTIFIED BY 'BezpecneHeslo';
Tyto úkony lze pohodlně provést v GUI nástroji MySQL Administrator, případně vykonat SQL příkazy v nástroji MySQL Query Browser, viz níže.
SQL skripty jsou vytvořené nástrojem MySQL Administator, oficiálním nástrojem pro administraci databázového systému MySQL (stahujte zde).
Nejsnazší cesta, jak z nich vytvořit svoji kopii databáze, je použít právě tento nástroj. Nezkoušejte načíst procedury v nástroji phpMyAdmin – ten je plný chyb a nezvládne skripty správně přeparsovat.
Pozor! Pokud se vaše databáze pro neuronové sítě
nejmenuje neural_network
, je nutné ručně upravit SQL
skript ukládaných procedur pro databázi jízdní řády! Toto se
bohužel nedá v současné verzi MySQL nijak obejít.
Úpravu proveďte takto:
JR - Procedury a funkce pro DP.sql
v editoru,
který zvládá kódování UTF-8 bez signatury (pro Windows např. Visual
Studio nebo PSpad).neural_network.
názvem
vaší databáze a tečkou.Poté upravenou verzi skriptu načtěte do MySQL místo původní verze.
Výše jmenovaný balík GUI nástrojů zahrnuje také MySQL Query Browser, šikovný nástroj pro práci s databázovým systémem MySQL.
Výčet jeho vlastností a dovedností je dlouhý. My se pro účely demonstrace kódu této diplomové práce omezíme na podstatné.
Po spuštění stiskněte F11
– to zvětší konzoli pro SQL
příkazy.
Nejprve předznamenejme, že MySQL používá koncept „aktuálně vybrané databáze“. Pokud voláte nějakou proceduru nebo pracujete s tabulkou, ujistěte se, že buď používáte plně kvalifikované jméno, nebo se daný objekt nachází ve vybrané databázi.
SQL příkazy vykonáváte tak, že na něj najedete kurzorem (nikoliv ukazatelem myši) a stisknete Ctrl + Enter. Výsledek (resultset) se zobrazí v dolní části
Můžete prozkoumat obsah tabulek jízdních řádů těmito SQL příkazy:
SELECT * FROM mhd_jizdy LIMIT 100; SELECT * FROM mhd_jizdy_stani LIMIT 100; SELECT * FROM mhd_linky; SELECT * FROM mhd_kody; SELECT * FROM mhd_trasy LIMIT 100; SELECT * FROM mhd_trasy_uzly LIMIT 100; SELECT * FROM mhd_zast LIMIT 100;
Zde je například výpis zastávek a jejich geografických pozic:
Po importu dat z výše uvedených souborů obsahují tabulky všechna data jízdních řádů, na kterých jsme kód testovali.
Z tabulek je možné vhodnými SELECTy získat jakékoliv informace, které chceme znát – například:
Zde je ukázka výpisu všech linek projíždějících zastávkou Žižkova:
Tabulky neuronových sítí prozkoumáte takto:
SELECT * FROM neural_network.nn_networks; SELECT * FROM neural_network.nn_net_neurons; SELECT * FROM neural_network.nn_net_synapses;
Po importu obsahují tabulky několik testovacích neuronových sítí.
Ladící zprávy pro algoritmy jízdních řádů, resp. neuronových sítí,
najdete v tabulkách neural_network.lib_logg
, resp.
jizdnirady_cb.lib_logg
:
SELECT * FROM neural_network.lib_logg; SELECT * FROM jizdnirady_cb.lib_logg;
Jak se konkrétní procedury používají je popsáno jednak v technické zprávě diplomové práce, jednak v komentářích v kódu jednotlivých procedur, a také na webu autora – jízdní řády, neuronové sítě.
Proto zde jen několik příkladů, jak SQL příkazy používat.
Standardně Query Browser po každém dotazu uzavře spojení s DB. Proto
nejprve spusťte transakci – dočasné tabulky tak zůstanou k dispozici po
volání procedury. Transakci spustíte buď příkazem
START TRANSACTION;
(a stisknutím Ctrl+Enter
) nebo
tlačítkem Transaction v horním pruhu programu. Vedle něj se po
spustění transakce objeví tlačítka pro potvrzení nebo zrušení transakce.
Stejného efektu lze docílit provedením příkazů COMMIT;
nebo
ROLLBACK;
.
-- Vyhledání spoje ze zastávky 115 do zastávky 465, maximálně 2 přestupy. CALL mhd_VyhledejSpoje(115, 465, NOW(), 3); SELECT * FROM mhd_VyhledejSpoje ORDER BY pos;
Zde je ukázka vyhledání spojů mezi zastávkami Žižkova – Budvar – U pily – Nemocnice – U chromých:
Se sítěmi lze provádět v podstatě tři operace: Vytvářet je, provést jejich výpočet, a učit je.
Na následujícím obrázku jsou zachycené první dva kroky.
Nejprve vytváříme neuronovou síť s architekturou 2,2,1
(vhodná pro řešení XOR):
-- Vytvoření neuronové sítě CALL nn_CreatePerceptron('2,2,1','XOR', 0.10, 0.5, @out_NetID);
Pro vzniklou síť provádíme její výpočet a uchováváme hodnoty vnitřních neuronů:
-- Výpočet neuronové sítě CALL nn_ComputeNet(1, '-1, 1', TRUE); -- Zjistění výsledků výpočtu SELECT * FROM nn_ComputeNet; -- Výstupní hodnoty všech neuronů SELECT * FROM nn_ComputeNet_InternalValues;
Výsledkem jsou tyto struktury:
id_neuron | val |
---|---|
5 | 0.984122623404696 |
id_neuron | val |
---|---|
1 | –1 |
2 | 1 |
3 | 0.0166427942550775 |
4 | 0.972952595778587 |
5 | 0.984122623404696 |
Na základě vzniklých hodnot můžeme provést jeden krok učení:
-- Učení neuronové sítě ALTER TABLE nn_ComputeNet RENAME TO nn_CorrectWeights; ALTER TABLE nn_ComputeNet_InternalValues RENAME TO nn_CorrectWeights_InternalValues; CALL nn_CorrectWeights(iNetID, '1', @dLearn, @out_dErrorSum);
Po provedení procedury (a případně potvrzení transakce) jsou váhy sítě upravené algoritmem backpropagation podle předchozího stavu sítě, dočasně uložených výstupních hodnot všech neuronů sítě a požadovaných hodnot výstupní vrstvy.
Pro pohodlné vyzkoušení učení neuronové sítě je k dispozici procedra
nn_TeachXOR_Dynamic( //ID//, //cílová úroveň chyby//, //maximum kroků//)
.
Kód v následující ukázce učí síť vytvořenou výše uvedeným postupem
na cílovou úroveň chyby 0,0001 v maximálním počtu 10 000 kroků:
-- Učení neuronové sítě pro XOR CALL nn_TeachXOR_Dynamic(3, 0.0001, 10000);
V diplomové práci používáme neuronové sítě k určení vhodné trasy
pro dosažení cílové zastávky v nejlepším čase.
Zde je kód pro vytvoření a učení neuronové sítě pro zastávku 5:
-- Vytvoření sítě pro zastávku 5 se třiceti neurony v jedné skryté vrstvě: CALL mhd_nn_CreateNetForStation(5, '30'); -- Učení právě vzniklé sítě pro zastávku 5 do cílové -- úrovně chyby 0.0001, maximálně po 40 000 kol učení: CALL mhd_nn_TeachStationNet(5, LAST_INSERT_ID(), 0.0001, 40000);
Všechny procesy se v naší implementaci zaznamenávají do logu. To je
užitečné zejména pokud něco nepracuje podle očekávání. Většinou je
chyba na straně uživatele a v logu je zapsán její příčina (ve sloupci
level
je hodnota error
nebo warning
).
Zde je ukázka záznamů z učení neuronové sítě zastávky s ID 530:
Další vysvětlení najdete ve výše jmenovaných zdrojích – v diplomové prácí, ve zdrojových kódech jednotlivých procedur a na webu autora.
Případné dotazy směřujte na mail ondra@dynawest.cz nebo
JabberID ondra.zizka@jabber.cz
.
Nabízím byt 3+1 v panelovém domě v klidné části českých Budějovic – sídliště Vltava.
Byt se nachází na severním konci sídliště vltava. V okolí:
Družstevní vlastnictví někteří lidé iracionálně považují za cosi méněcenného a špatného. Oproti osobnímu vlastnictví má ale mnoho výhod:
Jinak je družstevní vlastnicví stejně cenné jako osobní – byt není „někoho jiného“. Veškeré peníze, které platíte, jdou do oprav domu či investic do domu.
Někdo má dojem, že družstvo jej může „nutit“ platit na rekonstrukci, o kterou nemá zájem, kdežto s bytem v osobním vlastnictví si může dělat, co chce. To ale není pravda: V domech s více než 5 byty je ze zákona povinnost ustanovit sdružení vlastníků bytových jednotek, které bude spravovat dům podobně jako družstvo, a nájemníci jsou povinni se podřídit hlasování sdružení vlastníků.
Navíc pro společenství vlastníků banky obvykle neposkytují hypotéky:
Pro sdružení/společenství vlastníků bytových jednotek hypoteční úvěr neposkytujeme. Je však možné na obchodním místě banky individuálně projednat tzv. investiční úvěr poskytovaný pro oblast SME (úvěry pro společnosti a osoby samostatně výdělečně činné). Tento typ úvěru je ale skutečně nutné individuálně projednat, a to včetně podmínek. Marek Richter, vedoucí týmu hypotečních úvěrů Raiffeisenbank
Při koupi bytu v osobním vlastnictví v polorozpadlém paneláku tedy kupujete časovanou bombu a je pravděpodobné, že rekonstrukce domu neproběhne v dohledné době.
Každopádně, tento byt je v rekonstruovaném domě, žádné další společné investice se nechystají, a výše příspěvků do fondu oprav jsou pevně nastavené. Spolupráce s družstvem je dlouhodobě dobrá a k plné spokojenosti obyvatel.
Prodej bytu nijak nespěchá, proto dokud vidíte tuto nabídku, je platná.
Využijte možnosti koupit byt bez zbytečných poplatků realitní kanceláři.
Pište na některý z kontaktů na stránce kontakty.
Update: V návaznosti na tento článek vznikl další – Je Java jako Linux nebo jako Windows?
Update: Abych nezůstal u teorie a subjektivních hodnocení PHP, přidám ukázku jednoho webu napsaného v PHP – a to hned web zabývající se programováním.
Update: V posledním (aspoň doufám) článku na toto téma vysvětluji jednotlivé body ze seznamu nevýhod.
Na webu je mnoho flejmů, zda je PHP lepší / horší než Java a .NET atd. Ostatně, nejjednodušší způsob, jak rozpoutat flejm, je zajít na hodně čtený blog nějakého PHPčkáře a zeptat se místních, že jste nováček a jestli je PHP lepší než Java. Mimojiné se na tom otestuje složení čtenářů – tj. nakolik jsou zastoupeni čistokrevní PHPčkáři s klapkami na očích, kteří nemají šajna o MVC, O/R a kolikrát ani pořádném OOP návrhu.
Nicméně nenašel jsem (pravda, zas tolik jsem nehledal) nějakou pořádnou moderovanou diskusi, případně článek, o výhodách a nevýhodách PHP.
//Update:// Našel jsem celkem dobrý článek na http://spyced.blogspot.com/…p-sucks.html. Sice je poněkud starší, ale jádro pudla zůstává. Je o dost ostřejší a než tento můj článek, takže PHPčkáři – bacha! :-) A všimněte si, že J2EE autor označuje za neelegantní stejně jako PHP.
Trochu se porozhlížím, kamže půjdu pracovat na fulltime. Do toho mě oslovil bývalý spolužák, že prý si mě všimnul na přednáškách Seznam.cz a že jejich firma naléhavě hledá programátory PHP a jestli bych k nim nešel. Já na to, jestli dělají v Javě, a že prý ano, ale hledají PHP programátory. Slíbil jsem, že se tedy ozvu jeho šéfovi a pokecáme. Pak jsem na to ale pozapomněl a šéf se ozval sám (asi hledají opravdu naléhavě :-)
Popravdě jsem mu vyložil, že PHP umím dobře, prakticky do detailů, no což to budu opisovat – zde je má odpověď:
Dobrý den,
Vaše nabídka mě zaujala. Shrnu svoji situaci:
V PHP vyvíjím (komerčně) už několik let. Možná právě proto mě to ale velice silně táhne k Javě a J2EE […]. Dále mám zkušenosti s [… … …] .
Kolega XY mi už také psal, zvažoval jsem, že se ozvu, ale říkal, že váš J2EE tým je asi spíše plný.
Mohl bych tedy pracovat jak jako vývojář PHP, tak J2EE, nicméne druhé o mnoho raději […]. Nabídku pracovního místa už mám, proto by mě zajímaly další podmínky – můžeme je případně probrat po telefonu.
V příloze posílám své CV, pokud by bylo třeba.
S pozdravem Ing. Ondřej Žižka
Asi půl hodinu na to se mi šéfík ozval po telefonu a domluvili jsme si schůzku. Na té jsem se dozvěděl, že získali kontrakt od firmy ABC, jíž dělají pokladní systém v J2EE a registrační web v PHP. A že na PHPkové weby mají svůj PHP framework (a v tu chvíli jsem si říkal – ajejej, další „svůj PHP framework…“) a že jej chtějí rozvinout. Ptal jsem se, co umí, jak funguje a oč jej chtějí rozvinout. A dozvěděl jsem se, že:
Potom se stočila řeč na to, jestli bych mohl dělat Java juniora, a později, proč bych nemohl, respektive proč chtějí vyvíjet v PHP a poč vyvíjet framework pro PHP, který:
a nakonec – a to především –
No diskuse to byla těžká, protože šéfík (nic proti němu, zdál se jako moc fajn chlap) je programátor – teoretik z Masarykovy univerzity, který zná PHP i J2EE „z manažerského pohledu“, a třetí účastník – jejich PHP senior – neví o Javě a J2EE nic (také nic proti němu, fajn kluk :-)
Zkrátka jejich postoj je takový, že PHP je skvělá technologie na jednodušší věci, jako je frontend pro Javovský backend, resp. nad databází. Inu dobrá, já jim to neberu, ale během celého rozhovoru mi hlavou běhaly vzpomínky na nejrůznější veselé příhody (dalo by se přeložit jako „gay incidents“ :) s PHP:
mysql_*
Prostě při pomyšlení, že bych měl jít vyvíjet framework v PHP, se mě jímaly úzkostné pocity. Jasně, potenciální PHP-fanatik mi bude oponovat, že kdybych psal rovnou dobrý kód, tak jsem v pohodě. Ale není to pravda, a to hned několikrát:
if
y jen kvůli ošetření chyby je pravěká metoda táhnoucí se
snad ještě z dob Alana Turinga.Naproti tomu, když programuji v Javě, dobrý kód vzniká skoro sám (už se neubráním srovnání):
interface List
a implementaci ArrayList
java.util
a java.lang
mysql_*
a PDO
)Prostě při prvním komerčním projektu v Javě moje srdénko jen zaplesalo nad tím, jak neuvěřitelně hladce to jde od ruky.
A ještě ke složitosti J2EE.
Když srovnám PHP a JSP, tak to jsou zhruba srovnatelné technologie:
Jenže tam, kde PHP končí, tam J2EE teprve začíná. Pokud skutečně rezignujete na leta vývoje a nechcete se učit tagy ze Struts nebo anotace z JPA / Hibernate, prosím – můžete vše poctivě datlovat jako v PHP, psát si SQL dotazy (jednoduchost přístupu k výsledkům dotazu v PHP přes pole zajistí iBatis) a třeba si i prasit kód rovnou do HTML souborů.
Jenže v J2EE máte možnost jít dál. Co máte v PHP? Ano, je zde pár povedených věcí… Smarty, Zend Framework, CakePHP. Ale ty stejně jedou nad shnilým jádrem.
Pokud někdo říká, že PHP se naučíte rychleji než J2EE, tak já říkám ano, protože v PHP skoro není co se učit.
Když jsem s J2EE začínal, také jsem se zalekl té neuvěřitelné haldy nových pojmů, specifikací, zkratek, XML konfiguračních souborů a postupů; dále nutnosti použít IDE nebo aspoň buildovací nástroj (Ant), naučit se spravovat něco jiného než Apache HTTPD…
Ono totiž PHP je jen taková lehká nadstavba nad CGI – nad něj dává jen relativně jednoduchou syntaxi a spoustu knihoven použitelných z této syntaxe. Jenže když jde do tuhého a úroveň vašich projektů se vznese nad příklady z manuálu PHP, stejně musite začít řešit (hodně na přeskáčku):
atd.
A zatímco J2EE vás těmito „nesmysly“ zavalí hned zpočátku, protože postupy jsou standardizované a často se věci rovnou řeší „složitě“ s výhledem na budoucí rozvoj, PHP vás nechá, ať si děláte co chcete – zlepšující se programátoři časem začnou vytvářet „vlastní framework“, vlastní normu pro strukturu aplikace, vlastní knihovnu pro automatické ukládání objektů do DB, a tak dále, zatímco naprostí začátečníci – neprogramátoři mohou třeba takto (viz část „Přiřazení prvků v šabloně“):
Často potřebujeme vybrat data z databáze a následně je předat šabloně. Na začátku je tedy SQL dotaz:
$result = mysql_query("SELECT nazev, titulek, text, cena FROM tabulka WHERE id='$id'");Jak nyní předat data šabloně?
Nejjednodušší řešení je předat rovnou pole:
$smarty->assign('data',mysql_fetch_assoc($result));
Nyní se pokusím oprostit od Javy a zaměřit se čistě na PHP. Kdyby se někde v dalším textu vyskytlo slovo „Java“, klidně mi dejte virtuální facku :)
Zkusím tedy shrnout, jaké má PHP výhody a jaké nevýhody. Zkusím při tom zaujmout pokud možno nezaujatý postoj, i když případného čtenáře o tom po přečtení předchozí kritiky asi nepřesvědčím.
Komentáře nevedu, ale jestli se vám něco v následujícím výčtu nezdá, napište mi mail a já zde provedu veřejné pokání a omluvu sloníkovi elePHPantovi :)
Výhoda a nevýhoda jsou relativní pojmy. Proto navrhuji jako „baseline“ pro srovnání použít ostatní technologie použitelné na podobné účely jako PHP, tedy: ASP.NET, ColdFusion, Java EE, Perl, Python, Ruby (on Rails). Naopak neuvažoval bych kombinace typu C + CGI (příliš složité programování), Apache SSI (příliš omezená funkčnost), Caché Server Pages (příliš nesmyslná technologie), XML + XSLT + JavaScript (principiálně příliš jinde), ASP (zastaralé) a podobně.
Takže – posuďte sami:
Technologie PHP má spoustu výhod, díky které se rychle stalo populárním. Mezi ně patří např.:
null
[]
Na druhou stranu, PHP má také značné nevýhody, pro které jej mnozí kritizují a někdy i opouštějí; mimo jiné tyto:
set_error_handler()
je pouze slabá
náplast)PDO
Array()
Jak je vidět, seznam výhod a nevýhod je trochu nevyvážený. Nyní čekám polemiku :-) ondra@dynawest.cz
//PS:// Ale pořád ještě to není tak strašné, jako s Caché – kdo zkoušel, ví :-)
4. Jaká je perspektiva PHP z Vašeho pohledu?
Jsem PHP skeptik. PHP jakožto jazyk ztratil koncepci, rozšiřování se děje chaoticky. PHP jakožto knihovna se nehodí na tvorbu webových aplikací. Frameworky se to snaží suplovat.
Obrázky přejaty z http://www.nexen.net/…nt/index.php a http://shop.yourphppro.com/elePHPant.html.
(PS: Kdyby někoho zajímalo, proč je tento web v PHP, tak je to kvůli
Texy! ;-)
PS pro Jana Škráška: Porty Texy? Ruby nemám rád, python neumím, .NET
nechci a pro Javu ještě port není.
Welcome to my web page.
This is not a blog – rather a „private publication“ place.
No comments here – I don't want to spend my time deleting dumb post and spam. If you have anything to say or ask, just send me an email.
Vítám vás na své webové nástěnce.
Zas jednou jsem už nevydržel dávat věci dokola někam na FTP a rozhodl se pro potřeby zveřejňování lecčehos zřídit web.
Nečekejte blog. Berte to jako moje soukromé „zveřejniště“.
Za krátkou dobu obnovené existence webu už mi přišel pár mailů, kde se autor ptal, proč nemám u článků komentáře. Důvod je jednoduchý:
Nemám ještě pořádný redakční systém, který by mi je někde pohodlně seštosoval, a možná ani mít nebudu, protože se pravděpodobně od webařiny přesunu k programování.
Jelikož toto není blog, ale prostor pro publikování, literární útvary se zde čas od času mění. Zakládat nový článek místo úpravy dokumentu podle mě není vhodné. Případné komentáře by tedy komentovaly staré verze, a zatímco dokument by se v čase vyvíjel a odrážel aktuální stav věcí, komentáře by se s ním táhly jako Gott a Vondráčková s hudebním průmyslem (fuj, to bylo ale politicky nekorektní).
Zatímco na „blozích“ se to řeší karmami, přihlašováním, hodnocením kvality, banováním a dalšími marnými technikami, já jednoduše komentáře nevedu.
Pokud někdo chcete komentovat, napište mi mail na ondra@dynawest.cz. Efekt to bude mít stejný – nadávky mě hluboce urazí a půjdu trucovat do kouta, zajímavé a relevantní tipy do článků přidám. Akorát spam takto vyfiltruju lépe :-)
Pokud zrovna nepracuji pro JBoss, zkoumám různé technologie:
V mezičase se prokousávám webovými Java technologiemi (J2EE).
This is my lazy way to get anything to a Maven repo. Shown on my mavenization of the Sardine library.
See also: How to add existing project's jar to SVN-based Maven repository
Choose a group name for the library and it's deps.
You should not use the lib's package names, because it could interfere later
with the official artifacts, should it ever be mavenized.
I usually use my project's name with the lib's name appended –
org.jboss.qa.ews.sardine
in this case.
@ECHO off ECHO echo Edit this file before use. Check the -DartifactId and -Dversion params. ECHO return ECHO cmd /C mvn install:install-file -DpomFile=sardine-pom.xml -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\sardine.jar -DartifactId=sardine -Dversion=80 FOR %%f IN ( sardine-80\lib\*.jar) DO ECHO cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=%%f -DartifactId=%%~nf -Dversion=%%~nf
This will create something like this:
echo Edit this file before use. Check the -DartifactId and -Dversion params. return cmd /C mvn install:install-file -DpomFile=sardine-pom.xml -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\sardine.jar -DartifactId=sardine -Dversion=80 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\ant-googlecode-0.0.2.jar -DartifactId=ant-googlecode -Dversion=0.0.2 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\commons-logging-1.1.1.jar -DartifactId=commons-logging -Dversion=1.1.1 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\httpclient-4.0.1.jar -DartifactId=httpclient -Dversion=4.0.1 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\httpcore-4.0.1.jar -DartifactId=httpcore -Dversion=4.0.1 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\junit-4.8.1.jar -DartifactId=junit -Dversion=4.8.1 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\svnkit.jar -DartifactId=svnkit -Dversion=0.0 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\svntask.jar -DartifactId=svntask -Dversion=0.0
pom.xml
file, which will describe the mavenized
library's dependencies.<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.jboss.qa.ews.sardine</groupId> <artifactId>sardine</artifactId> <packaging>jar</packaging> <version>80</version> <name>Sardine mavenized</name> <url>http://www.jboss.org/</url> <dependencies> </dependencies> </project>
Try to find as much as you can (the exact versions!), add them as a
dependency to the pom.xml
, and comment them out from the
script.
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.1</version> </dependency> <dependency> <groupId>org.tmatesoft.svnkit</groupId> <artifactId>svnkit</artifactId> <version>1.3.2-1</version> </dependency> <dependency> <groupId>org.jboss.qa.ews.sardine</groupId> <artifactId>ant-googlecode</artifactId> <version>0.0.2</version> </dependency> <dependency> <groupId>org.jboss.qa.ews.sardine</groupId> <artifactId>svntask</artifactId> <version>0.0</version> </dependency>
cmd /C mvn install:install-file -DpomFile=sardine-pom.xml -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\sardine.jar -DartifactId=sardine -Dversion=80 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\ant-googlecode-0.0.2.jar -DartifactId=ant-googlecode -Dversion=0.0.2 @rem cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\commons-logging-1.1.1.jar -DartifactId=commons-logging -Dversion=1.1.1 @rem cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\httpclient-4.0.1.jar -DartifactId=httpclient -Dversion=4.0.1 @rem cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\httpcore-4.0.1.jar -DartifactId=httpcore -Dversion=4.0.1 @rem cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\junit-4.8.1.jar -DartifactId=junit -Dversion=4.8.1 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\svnkit.jar -DartifactId=svnkit -Dversion=0.0 cmd /C mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\lib\svntask.jar -DartifactId=svntask -Dversion=0.0
svnkit
, svntask
and ant-googlecode
(I just guessed from the names).
These are going to be removed too.
So, perform this:
mvn install:install-file -DpomFile=sardine-pom.xml -Dpackaging=jar -DgeneratePom=true -DgroupId=org.jboss.qa.ews.sardine -Dfile=sardine-80\sardine.jar -DartifactId=sardine -Dversion=80
t:\data\.m2\repository\org\jboss\qa\ews\sardine\sardine
in
my case).
Copy it to some publicly accessible site, where it can be downloaded from using plain HTTP.
I used Google Code SVN.
svn --non-recursive
might help you with this task.
Done.
Postupem času jsem přešel na Linux. Co mě zde ale nepřestává štvát, je Bash.
Bash je jazyk hrůzy. Ne tak hrozný, jako Caché ObjectScript, ale pořád dost hrozný:
# Bohužel jsem momentálně nenašel dostatečně odstrašující příklad :) # V praxi ale narážím na naprosto nečitelný kód, # Využívající těch nejškaredějších syntaktických konstrukcí, # kde už člověk ztrácí přehled o tom, co je syntaxe find-u a kde je do ní vložen bash.
Jasně, chápu… je to jazyk určený hlavně pro práci v prostředí linuxu, a tedy pro práci převážně s GNU programy, které se vyvíjely v symbióze s Bashem. V interaktivním režimu je stále dobře použitelný pro jednořádkové příkazy. Pokud ale mám louskat několikastránkový skript, kde jsou takových jednořádkových příkazů desítky a každý je taková malá hra „hádej kolik syntaxí je zde použito“, házím flintu do žita.
Doba pokročila, a skoro začíná být důležitější podpora novodobých technologií, jako je Java, XML, webové služby, a v neposlední řadě je velmi příjemné, když lze využít výhod IDE – doplňování, refactoring atd.
Jak je patrné z těchto stránek, jsem momentálně fanda Javy – a to
ačkoliv jsem si vědom (někdy až bolestně) všech jejích nevýhod. A jako
každý (programátor), občas chci napsat stručný skript, který provede pár
operací podle několika zadaných parametrů. Jít na takovou záležitost
s Javou je přeci jen poněkud nevhodné – napsat všechnu omáčku,
zkompilovat, evt. zabalit do jarka a spouštět stylem
java -jar Skript.jar
, a to ještě dělat při ladění, to přeci
jen není ono.
Takže jsem začal hledat jazyk, který byl vhodný právě pro takové skripty, případně snad i na konzoli. Měl by tedy splňovat tato kritéria:
* Stručný – jít bez okolků na jádro řešení úlohy (jako bash).
* Jednoduchá syntaxe bez desítek výjimek, různých módů nahrazování, a
speciálních významů kombinací hieroglyfů typu $? atd.
* Přes jednoduchou syntaxi by měl mít dostatek prostředků pro stručný
zápis nejběžnějších operací, např. práce se seznamy.
* Podpora Javy – ideálně by měl umět pracovat s jakoukoliv třídou
Javy, včetně takových jako Thread
, Throwable
atd.
* Pochopitelně by měl umět OOP, výjimky, kontrolu typů.
* Měl by být konzistentní v konceptech.
Jako bonus potom započítávám tyto vlastnosti:
* Nativní podpora XML – nejlépe jako součást nativní podpory práce
se stromovými strukturami.
* Bez nutnosti kompilace.
* Různé vychytávky typu „vše je objekt“, uzávěry (closures),
yield
.
* Možnost uplatnit změny v kódu za běhu programu.
Nyní proberme jazyky a technologie, které připadají v úvahu:
* PHP rovnou diskvalifikuji z Těchto důvodů
* Python, resp. Jython
* Groovy
* Scala
* JavaScript
* JavaFX
* …navrhněte: ondra@dynawest.cz
Tímto zahajuji výběrové řízení a začínám se poohlížet po vlastnostech jednotlivých jazyků. Pokud bude čas, rozepíšu se o tom, proč který jazyk ano či ne.
A very brief intro to JBoss AOP.
This tutorial is a follow-up to the JBoss Microcontainer intro – read that first if you haven't yet.
AOP (Aspect Oriented Programming) is a concept of moving a „programatic envelopes“ away from the methods. What I call a programatic envelope is that kind of annoying code you have to repeat at the end or/and the beginning of many methods.
Usual textbook examples of AOP usage are:
However, AOP is particulary useful for frameworks for their need of generalization. It can help it to put the envelope code around method which it still does not know.
First, you mark some Java constructs (methods, fields, constructors, …) to
be AOP'ed (encapsulated with your envelope code).
Then you need so-called „aspect“ – that is the official name for envelope
code.
Then you need some tool which will bind the aspect to those methods. This is
done by advanced techniques like byte-code instrumentation and class
reflection.
JBoss AOP offers much more then the other AOP frameworks (like Spring AOP).
@Aspect
,
@Interceptor
, @Bind
etc. See Chapter
6. Annotation Bindings.Copied from JBoss AOP reference docs.
We want to catch all calls to methods that affect the fuel in the
Car
. To make this easily achievable with AOP, let's follow a
convention that all changing methods are setters and all fuel-related properties
names end with „Fuel“.
For the purposes of this example, we've changed the Car
class to
have two fuel-related properties:
public class Car { public int litresOfFuel; public int getLitresOfFuel() { return litresOfFuel; } public void setLitresOfFuel( int litresOfFuel ) { this.litresOfFuel = litresOfFuel; } public int reserveFuel; public int getReserveFuel() { return reserveFuel; } public void setReserveFuel( int reserveFuel ) { this.reserveFuel = reserveFuel; } public String toString(){ return "Car \""+this.name+"\" with "+(this.litresOfFuel + this.reserveFuel)+" litres of fuel."; } ... }
Interceptor
(„envelope“)This is a simple interceptor that will just notify us when triggered.
package cz.zizka.ondra.jbmctest; import java.util.logging.Logger; import org.jboss.aop.advice.Interceptor; import org.jboss.aop.instrument.Untransformable; import org.jboss.aop.joinpoint.Invocation; public class FuelInterceptor implements Interceptor, Untransformable { private static final Logger log = Logger.getLogger( FuelInterceptor.class.getName() ); public Object invoke(Invocation invocation) throws Throwable { Object target = invocation.getTargetObject(); if( target instanceof Car ){ log.info("The fuel is being changed for the car '"+((Car)target).getName()+"'."); } return invocation.invokeNext(); } public String getName() { return FuelInterceptor.class.getName(); } }// class FuelInterceptor
For the syntax of AOP pointcuts, see JBoss AOP documentation.
The syntax for our purpose stated above would be:
execution(* cz.zizka.ondra.jbmctest.Car->set*Fuel(..)
The AOP settings go to a special XML file having <aop>
as
it's root element, and conforming to the JBoss AOP XSD.
From what I've found, this file must be either in
META-INF/jboss-aop.xml
of your .jar
, or anywhere on
the filesystem, but you'll have to point to it by the
-Djboss.aop.path
JVM argument – see 10.2.1. Precompiled
instrumentation and 5.2. Resolving
XML.
To let maven put this file to your .jar
, store it in
src/main/resources
(the default path for resources), giving the
resulting path src/main/resources/META-INF/jboss-aop.xml
.
So let's bind this interceptor to some method calls. In this case, we're
binding it to all methods of the Car
class whose name has the
pattern set*Fuel
.
<?xml version="1.0" encoding="UTF-8"?> <aop> <bind pointcut="execution(* cz.zizka.ondra.*->set*Fuel(..))"> <interceptor class="cz.zizka.ondra.jbmctest.FuelInterceptor"/> </bind> </aop>
Alternatively, it should be possible to put the AOP settings to the JBoss Microcontainer XML (but I wasn't able to get it working):
<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0" xmlns:aop="urn:jboss:aop-beans:1.0"> <bean ... /> <!-- Car and garage beans --> <aop:interceptor name="FuelInterceptor" class="cz.zizka.ondra.jbmctest.FuelInterceptor"/> <aop:bind pointcut="execution(* cz.zizka.ondra.jbmctest.Car->set*Fuel(..)"> <aop:interceptor-ref name="FuelInterceptor"/> </aop:bind> </deployment>
After setting Maven to use JBoss repositories (see the JBoss Microcontainer how-to), add these dependencies to your project:
<dependencies> <dependency> <groupId>org.jboss.microcontainer</groupId> <artifactId>jboss-kernel</artifactId> <version>2.0.9.GA</version> </dependency> <dependency> <groupId>org.jboss.aop</groupId> <artifactId>jboss-aop</artifactId> <version>2.1.6.GA</version> </dependency> <dependency> <groupId>org.jboss.microcontainer</groupId> <artifactId>jboss-aop-mc-int</artifactId> <version>2.0.9.GA</version> <scope>runtime</scope> </dependency> </dependencies>
Also, add the JBoss AOP Maven plugin. It binds automatically to the
compile
phase. This will change the classes code to call your
interceptors when a method is being called.
<plugins> <plugin> <groupId>org.jboss.maven.plugins</groupId> <artifactId>maven-jbossaop-plugin</artifactId> <version>2.1.3.GA</version> <executions> <execution> <id>compile</id> <goals> <goal>compile</goal> </goals> <configuration> <includeProjectDependency>true</includeProjectDependency> <aoppaths> <aoppath>src/main/resources/META-INF/jboss-aop.xml</aoppath> </aoppaths> </configuration> </execution> </executions> </plugin> </plugins>
public class JBossAopSampleApp { public static void main( String[] args ) throws Throwable { Car myCar = new Car("Red Devil"); System.out.println( "I have a garage: "+car); // Put some fuel in. myCar.setLitresOfFuel( myCar.getLitresOfFuel() + 1 ); myCar.setReserveFuel( myCar.getReserveFuel() + 1 ); System.out.println( "I have a garage: "+car); } }
Now run the application, and you'll see that the interceptor is really being invoked.
I have a garage: Garage with a car: Car "Red Devil" with 0 litres of fuel. 16.11.2009 11:42:47 FuelInterceptor invoke INFO: The fuel is being changed for the car 'Red Devil'. 16.11.2009 11:42:47 FuelInterceptor invoke INFO: The fuel is being changed for the car 'Red Devil'. I have a garage: Garage with a car: Car "Red Devil" with 2 litres of fuel.
The application created in the examples above can be downloaded here: JBossAOPsample.zip
Máme nabídku nového hostingu… na Gigawebu to občas vypadne (mysql i web), a už není nijak moc pružný…
Installing Trac 12 on Centos 5.5 – requires Python 2.6
Mapovani vzdaleneho portu na vzdalenem stroji na lokalni port:
ssh -L localPort:TargetPC:RemotePort PCsSSHaccountem
Zpristupneni lokalniho portu na zvoleny port vzdaleny:
ssh -R VzdalenyPort:LokalniPC:LokalniPort PCsSSHaccountem
${parameter:-word} # Provide a default if parameter is unset or null. ${variable%pattern} # Trim the shortest match from the end. ${variable##pattern} # Trim the longest match from the beginning. ${variable%%pattern} # Trim the longest match from the end. ${variable#pattern} # Trim the shortest match from the beginning.
scriptPath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")" scriptDir=`dirname "$scriptPath"` JAVA=/mnt/jqa/jdk1.6.0_18-x86_64/bin/java $JAVA -cp $scriptDir/JiraBot-1.1.04.jar:`ls $scriptDir/lib/*.jar | awk '{ORS=":";print}'` org.jboss.jirabot.Main
PS1='${debian_chroot:+($debian_chroot)}\e[1;31m\u@\h:\w\$\e[m '
32 | green |
35 | magenta |
40 | white |
31 | red |
33 | yellow |
34 | blue |
# resolve links - $0 may be a softlink PRG="$0" while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`/"$link" fi done
(from Tomcat's startup.sh)
## Resolve a softlink. function resolve(){ PRG="$1" if [ "" == "$1" ] ; then return "" fi if [ ! -x "$PRG" ] ; then PRGW=`which "$PRG"` if [ ! -x "$PRGW" ] ; then RET="" return -1 fi fi while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`/"$link" fi done RET=$PRG return 0 } ## If called instead of sourced if [ "resolve" == "${0: -7}" ] ; then if [ "" == "$1" ] ; then echo "Usage: resolve <softlink>"; exit fi resolve $1 if [ "" == "$RET" ] ; then echo "$PRG not found." else echo $RET; fi fi
cvs -d:gserver:cvs.devel.redhat.com:/cvs/dist checkout httpd
tcpdump -w snap -s2000 -i eth0
keytool -list -keystore /qa/home/ozizka/opt/jdk1.6.0_18/jre/lib/security/cacerts keytool -import -alias support.stage.redhat.com -keystore /qa/home/ozizka/opt/jdk1.6.0_18/jre/lib/security/cacerts -file stage-cert.pem
# Debian root PS1='\[\e[1m\]\[\e[31m\]\u@\h \[\e[0m\]\[\e[32m\][\[\e[33m\]\t\[\e[32m\]]\[\e[33m\]\[\e[1m\] \w\[\e[32m\]\[\e[0m\] \$ ' # Debian: export PS1='${debian_chroot:+($debian_chroot)}\e[1;34m\u@\h:\e[1;33m\w\e[1;34m\$\e[m ' # Generic: export PS1='\e[1;34m\u@\h:\e[1;33m\w\e[1;34m\$\e[m ' # Plain: export PS1='\u@\h:\w\$ ' export PATH=$JAVA_HOME/bin:$PATH
Úvod píšu pro lidi, kteří (stejně jako dříve já) chtějí proniknout do J2EE, ale ztrácejí se v záplavě pojmů a zkratek. Předpokládám znalost webových standardů typu HTML, XML, HTTP a podobně, a dále znalost technologií Java 5.0+ – tj. jazyk, standardní knihovny J2SE, princip fungování tříd.
Úvod se snažím psát co nejpraktičtěji – popisuji tedy technologie v pořadí, v jakém jsem se s nimi setkal já (nebo v jakém by to aspoň bývalo bylo nejlepší).
Na komerčních knihách mě často štve, že jsou psané jak pro debily – každý detail odrbávají na dvě stránky. Já předpokládám, že jste inteligentní lidé, proto jeden fakt uvádím sice se snahou, aby bylo jeho vysvětlení srozumitelné a pochopitelné, ale uvedu ho jen jednou. Pokud moje vysvětlení nepochopíte, tak se omlouvám :-) a doporučuji Wikipedii, která pamatuje i na to, že člověk nemusí o daném tématu vědět vůbec nic.
Úvod je skutečně velmi povrchní a nenaučí vás žádné konkrétní postupy – je to zkrátka pomůcka pro zorientování se ve světě J2EE. Pokud již základní orientaci máte, potom je pro vás spíše oficiální J2EE tutoriál (v angličtině, rozsahem cca jako 600-stránková kniha).
Fajn, i když trochu starší, je také procvičovací tutoriál pro Eclipse IDE.
Zkratka J2EE (nověji Java EE) označuje skupinu technologií, která se používá pro vývoj tzv. „enterprise aplikací“ (čti entrprajs).
Co je enterprise aplikace není zcela jasně ohraničitelné, ale dá se říci, že to je aplikace, ve které se využívají pokročilé postupy jako clusterování (běží na více serverech / systémech / databázích …), distribuované transakce (transakce napříč clustery), fail-over (při výpadku převezme funkci jiná část systému), vzdálené volání, a další.
Typickými představiteli enterprise aplikací jsou například rozsáhlé podnikové systémy, bankovní aplikace, webové aplikace. Nás bude zajímat podmnožina J2EE používaná pro vývoj webových aplikací.
Na tomto místě je v knihách obvykle podrobný teoretický rozbor J2EE technologií; Avšak jak jsem předeslal, úvod se snažím psát co nejpraktičtěji, proto uvedu jen úplně nejnutnější pojmy a zkratky; zbylé haldy si necháme na později a vrhneme se rovnou na software.
V době rozvoje Javy si její tvůrci a příznivci řekli, že by to mohla být šikovná technologie pro tvorbu dynamických webů – koneckonců jde jen o generování HTML a dalších kódů.
První přístup byl ten, že se vytvoří Java programy, které budou
fungovat podobně jako CGI – dostanou na vstup HTTP požadavek a vrátí kód
stránky. Tak vznikly servlety. Je to krapet složitější – servlet není
přímo program, ale spíše třída, která má určité metody jako
doGet(...)
a doPost(...)
, které se pro každý
požadavek volají. V parametrech dostanou informace o požadavku, o session,
a referenci na objekt odpovědi.
public class HelloServlet extends HttpServlet { public void doGet (HttpServletRequest pozadavek, HttpServletResponse odpoved) throws ServletException, IOException { odpoved.getWriter().println("<html><body>Hello, world!</body></html>"); } }
Pak takovouto třídu zabalíte do JAR archivu spolu s konfigurákem
WEB-INF/web.xml
:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http:/java.sun.com/dtd/web-app_2_3.dtd"> <servlet> <servlet-name>hello</servlet-name> <servlet-class>test.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
Potom už jen archiv „deploynete“ a aplikace jede.
Jak vypadá deploynutí se liší podle serveru. Nejlépe to má udělané JBoss AS / JBoss Web, na kterém JARko prostě nakopírujete do adresáře
deploy
a hotovo. V Tomcatu je třeba jít do manažera aplikací a v něm.jar
nahrát přes formulář.
Pochopitelně konfigurace každého servletu a generování HTML stránek přimo v Java kódu je dost otravné:
PrintWriter vystup = odpoved.getWriter(); vystup.write("<h1>Ahoj " + session.getAttribute("name") +"!</h1>"); vystup.write("<p>Takhle nějak se generuje stránka ze servletu.</p>");
Představte si takhle psát celou stránku. Proto se vývojáři poohlédli, jak se to řeší v jiných technologiích, například ASP nebo PHP (tehdy ještě pravěké verze), a viděli, že daleko lepší přístup je psát HTML stránku a do ní tu a tam vložit nějaký kód, kterého je obvykle spíše menšina. No a tak vznikla technologie JSP.
Servlety mají dodnes svoji nezastupitelnou roli. Je třeba si uvědomit, že webové aplikace negenerují jen HTML stránky. Na generování binárních výstupů nebo XML dokumentů (např. pro webové služby) se stále používá Servlet API.
<h1>Ahoj <%= session.getAttribute("name") %>!</h1>
Rovnou při vzniku měla mnohem více možností, než konkureční způsoby vkládání kódu do HTML (můj názor). A to především díky zvláštním tagům, jejichž interpretaci mají na starosti Java třídy. Takový tag vypadá například takto:
<html:link action="/logout">Odhlásit</html:link>
Zrovna tento tag není úplně dobrý příklad, zrovna mi padnul pod ruku. ***Dát lepší příklad. Lepší by byl třeba tento: (Poznámka pro znalé: Tento kód jsem si z hlavy vymyslel, neodpovídá přesně tagům JSTL knihovny.)
<cache:cache key="vypis_uzivatelu"> <sql:query sql="SELECT * FROM users ORDER BY name" var="resultUsers" /> <table> <c:foreach from="resultUsers" var="i"> <tr><td><c:out value="${resultUsers[i]}"/></td></tr> </c:foreach> </table> </cache:cache>
Ne, nelekejte se – neřeší se celá aplikační logika pomocí XML
elementů (také to tak na mě z některých tutoriálů působilo). Elementy,
které vidíte, jenom představují celkem pohodlné rozhraní ke knihovnám,
které zajišťují jejich funkčnost. Například existuje knihovna pro cache,
díky které stačí kešovaný kousek stránky obklíčit elementem
<cache:cache>
(může se jmenovat libovolně, jméno můžete
sami upravit), a knihovna už sama zajistí buď provedení kódu vevnitř, nebo
vytažení již uloženého výsledku.
V poznámce výše jsem zmínil knihovnu JSTL (JSP Standard Tag Library). Můžete se podívat na jeji stránky http://jakarta.apache.org/…c/intro.html. Ale to jsme pořád na nejnižší úrovni možností těchto elementů. Opravdu pokročilé knihovny (které už jsou obvykle součástí nějakého frameworku a spolupracují s jeho zbylými částmi) obvykle poskytují automatizaci vysoké úrovně typu obsluhy, vyplňování a validace formulářů, AJAXu, správy šablon, atd.
Další pěknou vlastostí JSP je jazyk EL – Expression Language, pomocí kterého můžete do stránky stručně začlenit nějakou dynamickou hodnotu (teď zrovna nevím, jestli to je zrovna takhle, píšu z hlavy):
Ahoj ${session.attributes['name']}
Možnosti jazyka EL samozřejmě nekončí výpisem nějaké hodnoty. Můžete vyjádřit aritmetické operace, různě formátovat, volat statické Java funkce, které si sami naprogramujete, a další. (PHPčkářům by to mohlo připomínat Smarty.)
Pro lidi, kteří znají jen PHP, je pojem „životní cyklus“ trochu
novinkou. PHP má totiž životní cyklus úplně nejjednoduší možný:
Přijde požadavek, apache jej předá PHP, to zjistí, který skript má
načíst, přeparsovat a vykonat, skriptu předá požadavek, pak se řídí
instrukcemi ve skriptu, a nakonec skončí. Tento postup může být různě
optimalizovaný, např. PHP může udržovat přeparsované skripty v paměti,
použít jedno PHP vlákno vícekrát, a podobně.
Oproti tomu J2EE aplikace je opravdu aplikace v pravém slova smyslu:
Na serveru se spustí a běží, dokud ji neukončíte. Jednotlivé požadavky
potom nejsou jejími jednotlivými spuštěními, ale jen voláním metod
jejích tříd. Z toho plynou leckteré velké výhody.
Jako začátečník spatřuji jednu z největších výhod v tom, že stav aplikace nemusím někam ukládat do session či podobně, ale sám přetrvává. Pokud na serveru vytvoříte nějaký objekt a uložíte ho kamsi, tak tam přetrvá, dokud ho neodstraníte. Viditelný může být pro všechny session, pro všechny požadavky. Tuto vlastnost pochopitelně velmi hojně využívají téměř všechny frameworky, různé cache nástroje, správci zdrojů (např. spojení do databáze) atd. Samozřejmě se nejedná o náhradu perzistence; může ji však skvěle doplňovat.
Pokud chcete začít s vývojem webových aplikací s J2EE, přijdete zprvu asi do kontaktu s nějakým serverem, který je umí vykonávat. Takových serverů je mnoho od různých výrobců. Nazývají se kontejnery servletů (servlet containers), někdy je na ně nabaleno několik dalších „bundled“ technologií, a ty se potom honosí názvem aplikační server. U obyčejného kontejneru ale o nic nepřijdete – víceméně všechnu funkčnost si do něj můžete přidat sami, a profesionálové se k tomu u menších projektů dokonce přiklánějí raději.
Zde je seznam neznámějších:
Více najdete na Wikipedii: Comparison of Application Servers.
V tomto úvodu se budu zabývat asi hlavně kontejnerem Tomcat, jelikož jeho správa je nejjednodušší. Průběžně budu upozorňovat na to, co v Tomcatu chybí oproti aplikačním serverům.
Nainstalujte si tedy některý z výše uvedených, doporučuji Apache Tomcat. Zapamatujte si uživatelské jméno a heslo pro administraci a port, na kterém apache poběží – jejich neznalost je častou příčinou delší prodlevy v postupu nováčků. Po instalaci a spuštění se rovnou podívejte na úvodní stránku. Dokumentaci zatím neřešte, je pro vás zatím moc složitá. Podívejte se na administrační část – odkaz „Tomcat Manager“ vpravo nahoře. Zadejte jméno a heslo, které jste si zapamatovali při instalaci. Standardně je to admin / adminadmin. U jednotlivých aplikací (zatím jich tu moc není) vidíte odkazy „Stop, Start, Reload, Undeploy“. Nemačkejte na ně – zrušili byste si možnost správy Tomcatu (bohužel to není blbuvzdorné). Trochu rozvedu, k čemu jsou – čímž se dostáváme k tématu, jak se J2EE aplikace dostávají na server.
J2EE aplikace se obvykle na server umisťují v jednom souboru s příponou
.war
– Web ARchive. Ten má danou strukturu souborů a
adresářů – ta je dost důležitá a budete se s ní setkávat často
(hlavně když něco nepůjde). Například v Tomcat Manageru (ona stránka,
kterou máte asi stále ještě otevřenou) provedete deploy pomocí uploadu WAR
souboru na server. Proces ale nezahrnuje jen zkopírování – kontejner
rovnou aplikaci také rozbalí, prohlédne konfiguraci, podle ní upraví
prostředí pro aplikaci a svoje prostředí (zejména vytvoří zdroje typu
připojení do databáze atd.), aplikaci spustí a zavolá její metodu
init()
.
Aby to zas nevypadalo, že s Javou je svět krásný a ideální, tak musím uvést, že při tomto kroku bývají největší problémy: Na serveru kolidují verze knihoven kvůli hierarchii tzv. class-loaderů – to jsou nástroje pro načítání tříd do JVM a na serveru je jich hned několik. Když stejnou třídu (dokonce i ze stejného souboru) načte více classloaderů, z hlediska JVM jsou to jiné třídy, a pak dostanete třeba takovéto výjimky.
Začátečník (jak si dobře pamatuji) s tím může mít velké probémy, ale není to zas až tak strašné, pokud nastudujete trochu teorie – např. dobrý článek o classloaderech na Dagblogu, a znáte strukturu classloaderů vašeho serveru. Je to už ale trochu pokročilé téma.
Nejčastější chybou je duplikátní výskyt knihoven – jednou ve vaší
aplikaci, jednou třeba v /lib
adresáři serveru. To se často
děje proto, že se snažíte vyřešit problém nekompatibilních verzí
tříd. Proto také doporučuji webové aplikace napřed zkoušet na
kontejnerech, u kterých je toto riziko menší.
Začátečníky často mate spoustu názvů, se kterými se při práci s Tomcatem setkají – bohužel zejména při výpisu chyb, ale částo také při konfiguraci. Proto zde uvedu, co představují jednotlivá jména součástí Tomcatu. Samotné zmíněné technologie probereme dále. ***Možná přesunout dále, až za představení technologií.
Tolik tedy zatím k serverům, a teď se podíváme po něčem, v čem budeme aplikace vyvíjet.
Prostředí pro vývoj J2EE aplikací je opět více. Nejznámější jsou Eclipse a NetBeans. Začátečníkům rozhodně doporučuji NetBeans – na rozdíl od Eclipse obvykle vše funguje „z fleku“.
NetBeans mají přímou podporu Sunu a mají celkem slušnou komunitu. Navíc jde o projekt původem od českého kdysi-studenta; časem projekt koupil Sun a udělal z něj svoje –hlavní– mainstreamové vývojové prostředí – podobně jako má Microsoft svoje Visual Studio.
Stáhněte si tedy NetBeans, balíček Web & Java EE. V něm je zahrnutý i Apache Tomcat. Proč jsem vás tedy nechal stahovat samostatný Tomcat?
K vývojovému prostředí se ještě dostaneme, nyní k samotným technologiím.
Jednou z technologií, které jsou na J2EE nejlákavější, je perzistence objektů, či objektově-relační mapování. Ta slouží k automatickému „rozkládání“ objektů (hlavně) do relační databáze a jejich zpětné načítání. Dále je možné provádět nad objekty hromadné akce a dotazy pomocí jazyka podobného SQL. Objektům (resp. jejich třídám), se kterými v perzistenci pracujeme, se říká entity.
Nejznámějším nástrojem pro perzistenci je Hibernate. Ten používá jazyk HQL. Pro mapování, tedy k popisu, jak se objekty které třídy rozkládají do tabulek v databázi, sloužily dříve XML soubory.
<hibernate-mapping> <class name="ModelPlane" table="model_plane"> <id name="id" column="id_model" type="java.lang.Long"> <generator class="increment"/> </id> <property name="name" column="name" type="java.lang.String" /> </class> </hibernate-mapping>
V poslední době se ale rozmáhá pohodlnější způsob – @anotace.
@Entity public class ModelPlane { private Long id; private String name; @Id @GeneratedValue @Column(name = "id_model") public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Manuál k anotacím najdete zde – ovšem pokud skutečně zrovna začínáte, raději na to vůbec nekoukejte, nebo se rychle ztratíte. ***Odstranit? Spíše si přečtěte nadpisy, ať chytnete slinu na to vše, co Hibernate umí.
Hibernate lze použít i mimo J2EE – konec konců ukázkové aplikace jsou někdy obyčejné konzolové J2EE prográmky.
***Vložit ukázku SQL DML, mapovacího XML a Java kódu – např. faktury.
Detailní popis, jak Hibernate funguje a jak se s ním pracuje, vydá na mnohasetstránkovou knihu (viz Hibernate in Action). Proto vás jen odkážu na www.hibernate.org, kde najdete velmi dobrý tutoriál, ze kterého cca během dne pochopíte, oč jde a jak se to programuje.
Ani perzistence neunikla tendenci ve světě Javy vše standardizovat a vymýšlet společná aplikační rozhraní. Tak vznikl standard JPA, což je v podstatě trochu ořezané Hibernare API, ale také přinesl možnost místo XML souborů používat @anotace, což jsou (pro ty, co neznají) meta-informace zapsané přímo v kódu Java tříd za zavináčem:
@Entity @Table(name="users") public class User { @Id public int id; @Column( name = "jmeno" ) public String krestniJmeno; ... }
Trochu kontraproduktivně to vneslo bordel do názvosloví (vzniklo mnoho „skoro-synonym“), ale na to si zvyknete :-)
Technologie JSP sama o sobě je pořád dost slabá a pro vývoj velkých aplikací nevhodná. Proto se postupem času objevily stovky frameworků, z nichž desítky se opravdu často používají. Slouží nejrůznějším účelům pro různé vrstvy aplikací. O několika z nich si ve stručnosti povíme.
Zpracování požadavku se ve většině frameworků rozděluje na zhruba dvě části: Na akci a renderování stránky.
Akce je jednoduše provedení činností, které případné vyplývají z požadavku (např. vytvoření účtu), a dále příprava dat, které se použijí ve stránce.
Renderování je prostě vygenerování popisného kódu obsahující výsledný dokument – XHTML, WAP, SOAP, ale i binární jako PDF dokument pro tisk či PNG obrázek. Při tomto generování se obvykle použijí data připravená v akci, a k samoznému generování se často používá některý z přehršle šablonovacích systémů.
Největší obliby (podle mého pozorování) došel framework Struts. Ten slouží právě zejména k rozdělení a řízení toku aplikace – kdy provést jakou akci, jaké jí předat parametry, kam pokračovat, atd…
Má dvě hlavní verze:
Verze 1.x.x, která je ve své podstatě celkem jednoduchá a oproti verzi 2 toho moc neumí – čímž ale neříkám, že to málo, co umí, nezvládá dobře nebo že to není důležité. Zejména se totiž stará o aplikační logiku (jakou akci obsluhuje která třída, jaká stránka se má kdy zobrazit, atd.). Dále obsahuje celkem rozsáhlou knihovnu tagů (viz JSP), které plní různé účely.
Později spojením Struts 1 a frameworku WebWorks vznikla verze Struts 2, ve které původní funkčnost Struts 1 tvoří asi 20 %.
Seam framework z dílny JBoss je známý především díky své části určené pro ulehčení spolupráce JSF a EJB (podle čehož ostatně nese své jméno). Obsahuje však mnohem více součástí, a dalo by se říci, že záběrem konkuruje frameworku Spring.
Sun ze všech nejvíce propaguje framework JSF. Ten do značné míry vychází ze Struts 1, má i podobný záběr funkcionality, ale v lecčems se zásadně liší, a pochopitelně s sebou přináší spoustu standardů a více XML.
Když jsem se kamaráda – J2EE juniora – poprvé zeptal, k čemu je Spring, řekl: „Spring je naprosto bomba.“ A pokračoval tím, jak mu to ušetří spoustu psaní kódu.
Dnes, kdy jsem mnoho částí Springu již adoptoval a používám, mu musím dát zapravdu, i když on tehdy mluvil z pohledu vývojáře, který projekt nekonfiguruje, pouze využívá jeho efektů. Spring je však bomba i z pohledu správce projektu (seniora, chcete-li) – konfigurace je velmi snadná a jde jak po másle.
A nyní tedy, k čemuže ten spring je. Ve stručnosti se to moc popsat nedá, leda výčtem názvů jeho částí:
Lidem, kteří s J2EE začínají, takový výpis asi moc k ničemu nebude, proto vás rovnou odkáži na články
Pokud hledáte něco pro konkrétní účel, je obvykle dobré podívat se na projekty, které zastřešují jiné projekty – jako jsou Jakarta, zejména v levé části v sekci „Ex-Jakarta“ jsou projekty, které se osvědčily a přesunuly pod projekt Apache – seznam konkrétních projektů pro Javu je opravdu dlouhý. Z těch nejznámějších sem patří:
java.util.logging
)A mimojiné také server Tomcat, buildovací nástroj Ant, nástroj pro správu projektů Maven, práce se soubory MS Office POI, a další.
Dalším takovým hnizdem projektů je JBoss, nyní spravovaný firmou RedHat, kde je projektů opravdu hodně – asi 35. Mezi ně patří:
Nenechte se ale zahltit – pokud se zanoříte do všech projektů a budete chtít zjistit, co vše umí, bude to čtení na několik dnů. Já doporučuji tento postup: Koukněte se na nějaké Java fórum a hledejte témata s nadpisem typu „Jaký framework používáte pro XYZ a proč?“ V takových se obvykle nespustí flamewar, ale naopak věcná diskuze, kde se velmi stučně dozvíte shrnutí, k čemu který slouží, respektive k čemu jej kdo používá, a často i krátké a výstižné ukázky kódu.
EJB, Enterprise Java Beans : v podstatě jde opět o snahu standardizovat. Rozděluje „Beany“ (java třídy s určitým účelem) na několik kategorií, podle účelu, ke kterému mají sloužit – jestli mají provádět nějaké operace, nebo poskytovat nějakou službu, nebo jestli mají představovat nějakou entitu, a podobně. S tím souvisí pojmy „Stateful“, „stateless“ a další. ***Doplnit
Technologie EJB se týká především aplikačních serverů a enterprise aplikací. Má více verzí, které se docela zásadně liší. V současnosti je aktuální verze 3.0, která je snad první jednoduše použitelná. Ovšem na webu (v době psaní) narazíte povětšinou na materiály o EJB verze 2.0, z nichž leckteré to s klidným svědomím ani neuvedou, takže vy se pak zcela marně snažíte v aplikačním serveru pracujícím na EJB 3.0 aplikovat postupy pro EJB 2.0.
Tuto sekci o EJB uvádím hlavně proto, že na zkratku EJB se dá narazit hodně často. Studium EJB doporučuji odložit na dobu, kdy budete mít v ruce JSP, Struts a Hibernate. ***Dopsat
Zatím vše. Jelikož se s obrovským světem J2EE stále seznamuji, vyhrazuji si právo plácat tu nesmysly, ale snažím se, aby uvedená fakta odpovídala pravdě – konec konců, účelem tohoto dokumentu je velmi rychle seznámit nováčky s J2EE. Do podrobností zde zacházet nechci, těch je na webu velká spousta.
Pokud jste zkušení J2EE harcovníci, uvítám jakékoliv opravy na e-mailu ondra@dynawest.cz.
Napsáno 2007–08, aktualizováno tu a tam, naposledy 2008–10.
A very brief intro to JBoss AOP.
This tutorial is a follow-up to the JBoss Microcontainer intro – read that first if you haven't yet.
AOP (Aspect Oriented Programming) is a concept of moving a „programatic envelopes“ away from the methods. What I call a programatic envelope is that kind of annoying code you have to repeat at the end or/and the beginning of many methods.
Usual textbook examples of AOP usage are:
However, AOP is particulary useful for frameworks for their need of generalization. It can help it to put the envelope code around method which it still does not know.
First, you mark some Java constructs (methods, fields, constructors, …) to
be AOP'ed (encapsulated with your envelope code).
Then you need so-called „aspect“ – that is the official name for envelope
code.
Then you need some tool which will bind the aspect to those methods. This is
done by advanced techniques like byte-code instrumentation and class
reflection.
JBoss AOP offers much more then the other AOP frameworks (like Spring AOP).
@Aspect
,
@Interceptor
, @Bind
etc. See Chapter
6. Annotation Bindings.Copied from JBoss AOP reference docs.
We want to catch all calls to methods that affect the fuel in the
Car
. To make this easily achievable with AOP, let's follow a
convention that all changing methods are setters and all fuel-related properties
names end with „Fuel“.
For the purposes of this example, we've changed the Car
class to
have two fuel-related properties:
public class Car { public int litresOfFuel; public int getLitresOfFuel() { return litresOfFuel; } public void setLitresOfFuel( int litresOfFuel ) { this.litresOfFuel = litresOfFuel; } public int reserveFuel; public int getReserveFuel() { return reserveFuel; } public void setReserveFuel( int reserveFuel ) { this.reserveFuel = reserveFuel; } public String toString(){ return "Car \""+this.name+"\" with "+(this.litresOfFuel + this.reserveFuel)+" litres of fuel."; } ... }
Interceptor
(„envelope“)This is a simple interceptor that will just notify us when triggered.
package cz.zizka.ondra.jbmctest; import java.util.logging.Logger; import org.jboss.aop.advice.Interceptor; import org.jboss.aop.instrument.Untransformable; import org.jboss.aop.joinpoint.Invocation; public class FuelInterceptor implements Interceptor, Untransformable { private static final Logger log = Logger.getLogger( FuelInterceptor.class.getName() ); public Object invoke(Invocation invocation) throws Throwable { Object target = invocation.getTargetObject(); if( target instanceof Car ){ log.info("The fuel is being changed for the car '"+((Car)target).getName()+"'."); } return invocation.invokeNext(); } public String getName() { return FuelInterceptor.class.getName(); } }// class FuelInterceptor
For the syntax of AOP pointcuts, see JBoss AOP documentation.
The syntax for our purpose stated above would be:
execution(* cz.zizka.ondra.jbmctest.Car->set*Fuel(..)
The AOP settings go to a special XML file having <aop>
as
it's root element, and conforming to the JBoss AOP XSD.
From what I've found, this file must be either in
META-INF/jboss-aop.xml
of your .jar
, or anywhere on
the filesystem, but you'll have to point to it by the
-Djboss.aop.path
JVM argument – see 10.2.1. Precompiled
instrumentation and 5.2. Resolving
XML.
To let maven put this file to your .jar
, store it in
src/main/resources
(the default path for resources), giving the
resulting path src/main/resources/META-INF/jboss-aop.xml
.
So let's bind this interceptor to some method calls. In this case, we're
binding it to all methods of the Car
class whose name has the
pattern set*Fuel
.
<?xml version="1.0" encoding="UTF-8"?> <aop> <bind pointcut="execution(* cz.zizka.ondra.*->set*Fuel(..))"> <interceptor class="cz.zizka.ondra.jbmctest.FuelInterceptor"/> </bind> </aop>
Alternatively, it should be possible to put the AOP settings to the JBoss Microcontainer XML (but I wasn't able to get it working):
<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0" xmlns:aop="urn:jboss:aop-beans:1.0"> <bean ... /> <!-- Car and garage beans --> <aop:interceptor name="FuelInterceptor" class="cz.zizka.ondra.jbmctest.FuelInterceptor"/> <aop:bind pointcut="execution(* cz.zizka.ondra.jbmctest.Car->set*Fuel(..)"> <aop:interceptor-ref name="FuelInterceptor"/> </aop:bind> </deployment>
After setting Maven to use JBoss repositories (see the JBoss Microcontainer how-to), add these dependencies to your project:
<dependencies> <dependency> <groupId>org.jboss.microcontainer</groupId> <artifactId>jboss-kernel</artifactId> <version>2.0.9.GA</version> </dependency> <dependency> <groupId>org.jboss.aop</groupId> <artifactId>jboss-aop</artifactId> <version>2.1.6.GA</version> </dependency> <dependency> <groupId>org.jboss.microcontainer</groupId> <artifactId>jboss-aop-mc-int</artifactId> <version>2.0.9.GA</version> <scope>runtime</scope> </dependency> </dependencies>
Also, add the JBoss AOP Maven plugin. It binds automatically to the
compile
phase. This will change the classes code to call your
interceptors when a method is being called.
<plugins> <plugin> <groupId>org.jboss.maven.plugins</groupId> <artifactId>maven-jbossaop-plugin</artifactId> <version>2.1.3.GA</version> <executions> <execution> <id>compile</id> <goals> <goal>compile</goal> </goals> <configuration> <includeProjectDependency>true</includeProjectDependency> <aoppaths> <aoppath>src/main/resources/META-INF/jboss-aop.xml</aoppath> </aoppaths> </configuration> </execution> </executions> </plugin> </plugins>
public class JBossAopSampleApp { public static void main( String[] args ) throws Throwable { Car myCar = new Car("Red Devil"); System.out.println( "I have a garage: "+car); // Put some fuel in. myCar.setLitresOfFuel( myCar.getLitresOfFuel() + 1 ); myCar.setReserveFuel( myCar.getReserveFuel() + 1 ); System.out.println( "I have a garage: "+car); } }
Now run the application, and you'll see that the interceptor is really being invoked.
I have a garage: Garage with a car: Car "Red Devil" with 0 litres of fuel. 16.11.2009 11:42:47 FuelInterceptor invoke INFO: The fuel is being changed for the car 'Red Devil'. 16.11.2009 11:42:47 FuelInterceptor invoke INFO: The fuel is being changed for the car 'Red Devil'. I have a garage: Garage with a car: Car "Red Devil" with 2 litres of fuel.
The application created in the examples above can be downloaded here: JBossAOPsample.zip
jar
to SVN-based Maven repositorySee also: Quick and dirty mavenization of an existing project
# # Creates two files: # # 1) A bash script with mvn install:install-file commands to push the .jar's to a repository. # 2) A POM file with dependencies pointing to .jar's in Maven repo, uploaded by the script. # if [ -z "$1" ] ; then echo "Usage: mavenize.sh <path-to-dir-with-jars> [<groupId:'fake'>]" exit fi LIB_PATH=$1 GROUP=${2:-fake} echo '' > stuffTheRepo.sh echo '<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> ' > pomWithDeps.xml echo " <modelVersion>4.0.0</modelVersion> <groupId>$GROUP</groupId> <artifactId>deps</artifactId> <packaging>pom</packaging> <version>0.0-SNAPSHOT</version> <name>Fake Maven deps from JARs</name> <dependencies> " >> pomWithDeps.xml for JAR_PATH in $LIB_PATH/*.jar ; do JAR=`basename $JAR_PATH` ARTIFACT=${JAR%.jar} echo "mvn install:install-file -Dpackaging=jar -DgeneratePom=true -DgroupId=$GROUP -Dfile=$JAR_PATH -DartifactId=$ARTIFACT -Dversion=0.0" >> stuffTheRepo.sh echo " <dependency><groupId>$GROUP</groupId><artifactId>$ARTIFACT</artifactId><version>0.0</version></dependency>" >> pomWithDeps.xml done echo " </dependencies> </project>" >> pomWithDeps.xml chmod u+x stuffTheRepo.sh
Copied from Sardine project's README.txt.
This is a maven repository of the Sardine project.
To add a new version, do the following:
Note: This is not a copy-paste code – edit it according to
your situation.
Note: The preferred way is to use the Wagon-SCM Maven plugin,
as described on JBoss
wiki.
# First, create the sources and javadoc jar's. zip -9 -b sardine-XX/javadoc/* > sardine-XX/javadoc.jar zip -9 -b sardine-XX/src/* > sardine-XX/sources.jar # Let Maven create the directory structure and all the metadata files in the local repository. mvn install:install-file -DpomFile=sardine-pom.xml -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true -DgroupId=com.googlecode.sardine -Dfile=sardine-XX/sardine.jar -Djavadoc=sardine-XX/javadoc.jar -Dsources=sardine-XX/sources.jar -DartifactId=sardine -Dversion=XX # Check out remote SVN-based Maven repository. -N means non-recursive. svn co -N https://sardine.googlecode.com/svn/maven sardine-mvn --username you@gmail.com # Download the dir you're going to modify (if it exists). svn update com/googlecode/sardine/sardine # Copy the new artifacts to the working copy of the repository. cp -r ~/.m2/repository/com/googlecode/sardine/sardine sardine-mvn/com/googlecode/sardine/sardine # Rename the metadata file holding versions info. mv ~/.m2/repository/com/googlecode/sardine/sardine/maven-metadata-local.xml ~/.m2/repository/com/googlecode/sardine/sardine/maven-metadata.xml # Add everything new and commit. svn add --force * svn commit -m "Maven repo: Added version XX"
~/.m2/repository/
is your local Maven repository.
On windows it is usually
c:\Documents and Settings\user\.m2\repository\
.
pom.xml
is there because it contains dependency
definitions.Jednou z mých oblíbených technologií jsou relační databáze a jazyk SQL. Líbí se mi, jak elegantně se dají některé typy problémů pomocí SQL řešít – zejména grafové úlohy. Například výpočet neuronové sítě v tradičních programovacích jazycích sestává obvykle ze tří vnořených cyklů, v SQL je to cyklus pouze jeden, zbytek vyjádříte v SELECTech. Ale o tom až dále.
Mojí oblíbenou databází je MySQL 5.0. Schválně uvádím verzi, protože jsem si ji oblíl až na základě možnosti psát tzv. Stored procedures.
V průběhu doby jsem při řešení různých projektů vytvořil užitečné procedury a funkce, které usnadňují vývoj procedur pro MySQL a mohly by se kdekomu hodit.
Omlouvám se těm, co nehovoří anglicky, ale zbytek SQL sekce bude většinou právě v angličtině.
Krom toho střádám i své touhy, co by se mohlo (a mělo) v MySQL objevit:
I've made up a list of JavaScript libs for isometric rendering.
canvas
element
selection buffer1.1.2008 spustilo Ministerstvo spravedlnosti na svém serveru justice.cz webovou službu insolvenčního rejsříku , doplněk k informačnímu systému ISIR. S touto službou jsem měl tu čest pracovat a zde bych se rád podělil o zkušenosti v naději, že na tuto stránku narazí i tvůrce služby, firma CCA.
//Update 18.7.2008:// Sepsal jsem Popis dalších nedomyšleností webové služby Insolvenční rejstřík.
//Update 25.7.2008:// Mám první funkční prototypy aplikace pro automatickou kontrolu subjektů v insolvenčním rejstříku.
//Update 8.8.2008:// Přesun projektu: insolvenční rejstřík.
//Update 2.9.2008:// Betaverze aplikace pro automatickou kontrolu insolvenčního rejstříku.
//Update 12.9.2008:// Alfaverze webového rozhraní.
//Update 1.11.2008:// Alfaverze okamžitého upozorňování na události.
Asi jako každý jsem začal prohlédnutím definice webové služby WSDL:https://isir.justice.cz:8443/…s/IsirPub001?wsdl.
Už ta vás trošku zatahá za oči, protože hledáte nějaké názvy funkcí,
které budete volat, a typů, se kterými budete pracovat, ale zde najdete
názvy podobného ražení jako getIsirPub001
,
ns2:IsirPub001Data
, IsirPub001SOAP12port_http
a
tns:IsirPub001SEI_getIsirPub001Response
:
<wsdl:service name="IsirPub001"> <wsdl:port name="IsirPub001Httpport1" binding="tns:IsirPub001HttpBinding"> <http:address location="https://isir.justice.cz:8443/isir_ws/rest/IsirPub001"/> </wsdl:port> <wsdl:port name="IsirPub001SOAP12port_http" binding="tns:IsirPub001SOAP12Binding"> <soap12:address location="https://isir.justice.cz:8443/isir_ws/services/IsirPub001"/> </wsdl:port> <wsdl:port name="IsirPub001SOAP11port_http" binding="tns:IsirPub001SOAP11Binding"> <soap:address location="https://isir.justice.cz:8443/isir_ws/services/IsirPub001"/> </wsdl:port> </wsdl:service>
Nádhera, že? Na první pohled autoři služby ponechali jména prostě taková, jaká jim generátor služby (nástroje z Axis) nabídl. Ale budiž, řeknete si, generátor vytvořil, generátor zpracuje. Ne tak v tomto případě.
Moje oblíbené IDE je NetBeans, vytvořil jsem tedy v NetBeans
6.0.1 projekt a v něm se pokusil vygenerovat klienta podle výše zmíněné
WSDL definice. Bohužel WSDL pravděpodobně neodpovídá plně standardům,
protože už validace WSDL selhává a hlásí, že někde nejsou uvedené
atributy address
a že vygenerované knihovny klienta služby budou
asi nepoužitelné. Což je krásná hláška na začátek, ale pustil jsem se
do toho i přesto.
Knihovny pochopitelně nefungovaly. Vygenerovaný kód je celkem nanic.
Nevím, jestli za to může WSDL nebo generátor klienta (dost možná že
generátor), koneckonců – nejsem odborník na webové služby. Nicméně
poté, co jsem kód přepsal, jak má být, opět klient nefungoval –
vyhazoval výjimku java.lang.ClassCastException
. Chyba byla ovšem
v knihovně SAAJ. NetBeans 6.0.1 sice obsahují číselně (nominálně)
nejnovější verzi 1.3, ta je ale přes dva roky stará. Je tedy nutné
stáhnout nový build SAAJ z adresy https://saaj.dev.java.net/…DocumentList?…
, v adresáři NetBeans najít JAR saaj-impl.jar a nahradit jej novým ze
staženého JARka.
Pak už tedy volání webové služby funguje. Jenom podotknu, že v zoufalosti během dvoudenního řešení nejen výše uvedených problémů jsem zkoušel volat webovou službu ISIR také z PHP. Výsledkem bylo toto:
500 Internal Server Error java.lang.StringIndexOutOfBoundsException: String index out of range: -1 at java.lang.String.substring(String.java:1444) at org.apache.axis2.builder.XFormURLEncodedBuilder.extractParametersFromRequest(XFormURLEncodedBuilder.java:155) at org.apache.axis2.builder.XFormURLEncodedBuilder.processDocument(XFormURLEncodedBuilder.java:112) at org.apache.axis2.transport.TransportUtils.createDocumentElement(TransportUtils.java:160) at org.apache.axis2.transport.TransportUtils.createSOAPMessage(TransportUtils.java:111) at org.apache.axis2.transport.http.util.RESTUtil.processXMLRequest(RESTUtil.java:60) at org.apache.axis2.transport.http.AxisServlet$RestRequestProcessor.processXMLRequest(AxisServlet.java:788) at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:193) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at com.evermind[Oracle Application Server Containers for J2EE 10g (10.1.2.0.2)].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:824) at com.evermind[Oracle Application Server Containers for J2EE 10g (10.1.2.0.2)].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:330) at com.evermind[Oracle Application Server Containers for J2EE 10g (10.1.2.0.2)].server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:830) at com.evermind[Oracle Application Server Containers for J2EE 10g (10.1.2.0.2)].server.http.AJPRequestHandler.run(AJPRequestHandler.java:224) at com.evermind[Oracle Application Server Containers for J2EE 10g (10.1.2.0.2)].server.http.AJPRequestHandler.run(AJPRequestHandler.java:133) at com.evermind[Oracle Application Server Containers for J2EE 10g (10.1.2.0.2)].util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:192) at java.lang.Thread.run(Thread.java:534)
Takže s PHP jsem to raději vzdal úplně.
Vezměme si moji situaci. Klient chce zjistit, zda v daném okamžiku je nějaká fyzická osoba vedena jako dlužník či ne. Zdálo by se to velmi jednoduché, kdyby služba ISIR měla nějakou funkci (třeba s výstižným názvem „getIsirPub0012_2“), která by přebírala rodné číslo ve formátu RRMMDD/AAAA, a vracela true/false. Chápu že to je značně zůžená funkčnost, ale jak už jsem psal, je to asi to, k čemu službu využije polovina uživatelů. Další polovina ji využije stejně, ovšem pro IČ.
Bohužel, to je komfort, o kterém si můžeme nechat zdát. Služba ISIR WS funguje úplně jinak.
Představte si, že vám Ministerstvo životního prostředí zadá úkol vytvořit webovou službu, která umožní široké veřejnosti zjistit teplotu naměřenou v jakékoliv meteorologiké stanici v ČR. Firma CCA (tvůrce ISIR WS) by to nejspíš udělala tak, že by zpřístupnila záznamy změn teplot oproti předchozímu stavu za celou historii existence služby od jejího spuštění. Takže kdo by chtěl aktuální teplotu v Brně, stáhnul by si v dávkách po tisíci řekněme miliardu záznamů v logu včetně záznamů pro tisíce stanic, které ho vůbec nezajímají, aplikoval by změny od začátku zaznamenávání, a nakonec by odečetl aktuální stav stanice Brno ve vlastní databázi.
Tak přesně totiž funguje webová služba insolvenčního rejstříku! Nejedná se o nic jiného než o replikaci databáze pomocí zpracování logu změn. Pod záštitou „maximální dostupnosti služby“ služba jenom zpřístupňuje statické záznamy z logu bez jakékoliv další bussines logiky!
Což by ještě nebylo tak špatné, kdybyste jako programátor klienta věděli, co který úkon znamená. Já se přiznám – nemám právní vzdělání, a proto to nevím. Proto mi polovina záznamů ve výstupu webové služby nedává smysl a nechápu, proč tam jsou. Předveďme si ukázku.
Když se podíváte na výstup webové služby, evidentně se jedná o zaznamenané operace uživatelů informačního systému insolvenčního rejstříku (ISIR). Pokud tedy nějaký soudce v Praze zakládá spis týkající se nějakého dlužníka, nejprve v systému klikne na tlačítko „Nový spis“. Vyplní jeho značku a stiskne „Vytvořit“. Tím se v logu ISIR vytvoří záznam a do výstupu webové služby přibyde:
ID: 2760 Cas: 23.1.2008 9:11:46 Spis: INS 132/2008 Odd: A Poradi: 2, Typ: 185 (Vyhláška o zahájení insolvenčního řízení) Data: <?xml version = '1.0' encoding = 'UTF-8'?> <tns:udalost ... > <idOsobyPuvodce>MSPHAAB</idOsobyPuvodce> <vec> <druhStavRizeni>NEVYRIZENA</druhStavRizeni> </vec> </tns:udalost>
Tím zatím věc končí a soudce se na nějakou dobu odmlčí. Mezitím soudci a úředníci na ostatních soudech pilně pracují a klikají v informačním systému jako o život, takže vznikne dalších 100 záznamů. Zhruba po třech hodinách se pražský soudce opět probere a v informačním systému přejde do sekce „Návrh – přílohy“, čímž nám vznikne tento velice duchaplný a užitečný záznam:
ID: 2853 Cas: 23.1.2008 11:57:20 Spis: INS 132/2008 Odd: A Poradi: 3, Typ: 23 (Návrh - přílohy) Data: <?xml version = '1.0' encoding = 'UTF-8'?> <tns:udalost ...> <idOsobyPuvodce>MSPHAAB</idOsobyPuvodce> <vec> <druhStavRizeni>NEVYRIZENA</druhStavRizeni> </vec> </tns:udalost>
Po dalších pěti hodinách a další stovce záznamů z jiných soudů se soudce vrátí z oběda a v IS klikne na tlačítko „Nový pokyn insolvenčního soudu“, a tím vzniká další velmi užitečný záznam:
ID: 2954 Cas: 23.1.2008 16:48:44 Spis: INS 132/2008 Odd: A Poradi: 4, Typ: 204 (Pokyn insolvenčního soudu) Data: <?xml version = '1.0' encoding = 'UTF-8'?> <tns:udalost ...> <idOsobyPuvodce>MSPHAAB</idOsobyPuvodce> <vec> <druhStavRizeni>NEVYRIZENA</druhStavRizeni> </vec> </tns:udalost>
Tím v této dávce tisíce záznamů informace o tomto spise končí a vy musíte stáhnout další tisícovku.
Služba insolvenčního rejstříku byla spuštěna 1.1.2008. Od té doby do dneška (18.3.2008) log obsahuje CCA. 18 000 položek. Pokud si tedy v roce 2030 založíte firmu a budete chtít o svých klientech zjistit, zda nejsou vedeni jako dlužníci, budete si muset stáhnout odhadem (lineární interpolací) 1 500 000 záznamů a podle nich zreplikovat databázi informačního systému insolvenčního rejstříku!
Ruku na srdce – nezdá se vám nepřiměřené, aby si _každý_, kdo chce
službu jakkoliv využívat, dělal lokální kopii celého logu za celou
historii existence systému, poté nastudoval pracovní postupy pracovníků
soudů z nepřehledné „dokumentace“ Popis_WS.pdf
a na
základě těchto znalostí aktualizoval svoji kopii databáze pro každou
entitu, která v DB existuje, ačkoliv ho 99,999% z nich nezajímá a nikdy
zajímat nebude, ale musí to dělat pro případ, že by náhodou někdy
v budoucnu potřeboval s danou entitou pracovat?
Další krásou, kterou jsem objevil až s tímto projektem, je vkládání XML do XML. Cituji:
Aby byla webová služba co nejobecnější a přitom odolná proti častým změnám rozhraní, obsahuje samotné volání pouze základní údaje pro identifikaci události, které se akce týká. Samotná přenášená data obsahuje poznámka. Data jsou v poznámce strukturována formou XML dokumentu.
Budiž – uznávám, že generovat nové knihovny klienta webové služby při každé změně struktury dat by nebylo příjemné. Jak často a proč se ale má jejich struktura měnit? Je to proto, že webová služba obsahuje data, která vás nezajímají o subjektech, které vás nezajímají. Pokud by Ministerstvo spravedlnosti bylo natolik soudné, aby požadovalo normálně fungující službu, byl by vstupem pro službu nějaký identifikátor a typ subjektu, a vracela by AKTUÁLNÍ data, která se ho týkají. Myslím, že u takové WS by se nutnost změny WSDL omezila na minimum.
„Služba je koncipovaná jako veřejná a je zdarma.“ Z toho také plyne, že tvůrci předem neví, kdy a kolik požadavků přijde. Ovšem že vrácení rovného tisíce položek ze STATICKÉ databáze, tedy logu, trvala až půl až 4 minuty !!, a to v době, kdy službu ještě zdaleka nevyužívá tolik klientů, to je opravdu velmi zarážející. Už jsem se setkal se systémy s desítkami milionů záznamů, které ovšem reagují řádově v sekundách zhruba na dva požadavky za sekundu, a to se jedná o fulltextové vyhledávání. Na čem potom provozují webovou službu ISIR? Na vyřazených noteboocích?
//Update:// Podle odpovědi tvůrců byly prodlevy způsobeny něčím jiným než nedostatečným hardware. Nyní se zdá, že služba již pravidelně odpoví do několika sekund.
Takže, když shrnu svoje výtky vůči IRIS WS:
Na mé námitky vůči kvalitě zpracování služby odpověděla firma CCA Group takto:
Vámi připomínkovaný způsob fungování WS ISIR byl navržen, odsouhlasen a zpracován na základě požadavků MSp. Víme, že některé subjekty by radši používaly sofistikovanější WS s vlastnostmi, které popisujete. Dle sdělení zadavatele – MSp není takto koncipovaná WS ve shodě s jejich záměry dalšího rozvoje aplikace ISIR.
Jinými slovy, ministerstvo (rozumějte – nejspíše laici, kteří ani netuší, co je webová služba) je spokojeno se stavem, kdy se data vůbec nějak mohou k někomu dostat, čímž splnilo požadavek zákona, myje si ruce a víc jej nezajímá.
Jak jsem uváděl výše, většina lidí si pod pojmem „Webová služba Insolvenční rejstřík“, která má zveřejňovat údaje o insolvenčních řízeních, představí něco trochu inteligentnějšího než stahování kopie databáze ISIR. Proto jsem se rozhodl takovouto funkčnost zpřístupnit.
Na adrese http://isir.dynawest.cz/ tedy bude klient Webové služby Insolvenční rejtřík ISIR. Spuštění plánuji na konci července 2008.
Právě jsem úspěšně rozběhal Spring AOP ve stand-alone (newebové) aplikaci, takže si opět postup a poznatky zapíšu na web. Jako vždy si vyhrazuju právo mýlit se, ale snad jsem vše pochopil správně.
AOP je zkratka za Aspect Oriented Programming neboli „aspektově orientované programování“.
AOP zajišťuje ulehčení práce programátora v případech, kdy se při volání metod různých tříd volá vždy stejný nebo podobný kód – typickým příkladem je otevírání a uzavírání transakce, kontrola práv k provedení operace (autorizace), trasování běhu aplikace atd.
Aspekt je (společná) vlastnost či spíše potřeba některých metod – například právě potřeba otevřít a uzavřít transakci nebo ověřit práva.
Spring AOP je jedna z implementací AOP. Dále existují ještě AOP frameworky JBoss AOP (s tím se dostanu brzy do potyčky :-), AspectJ (ten to všechno začal a Spring AOP jej využívá) a AspectWerkz (nic moc).
Spring jde svojí obvyklou cestou co nejjednodušší konfigurace a co
nejstručnějšího zápisu. Můžete využít buď @Anotace ve stylu AspectJ
(@Aspect
, @Before
, @Pointcut
atd.), nebo
konfiguraci v XML souboru. Ukázka XML následuje.
Dříve (před verzí Spring 2.0) se konfigurace AOP prováděla poněkud neohrabaně nastavováním Beans (což popisuji v návodu Úplné začátky se Spring framework).
V současnosti se AOP nastavuje pomocí elementů z namespace
<aop:*>
. Tento jmenný prostor je třeba v XML souboru
zmínit, proto se místo DTD použije definice přes xmlns:aop
.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" > <!-- Před spuštěním metod tříd z balíku "aoptest" zavoláme metodu test() z beany s ID aopTestAdviceBean. --> <aop:config> <aop:pointcut id="aopTestPointcut" expression="execution(* aoptest.*.*(..))"/> <aop:aspect ref="aopTestAdviceBean"> <aop:before pointcut-ref="aopTestPointcut" method="test"/> </aop:aspect> </aop:config> <!-- Metoda této beany (objektu) se bude volat podle výše uvedeného pravidla. --> <bean id="aopTestAdviceBean" class="aoptest.AopTestAdviceBean"> <property name="foo" value="foo value"/> </bean> <!-- Automatické volání metod funguje jen pro objekty vytvořené Springem. --> <bean id="nejakaTrida" class="aoptest.NejakaTrida"> <property name="bar" value="bar value"/> </bean> </beans>
K tomu ještě pár poznámek:
aoptest.NejakaTrida objekt = new aoptest.NejakaTrida(); objekt.metoda(); // <--- ZDE AOP NEZAFUNGUJE!
XMLBeanFactory
použít „full verzi“, tedy třídu
ApplicationContext
.Celý kód pro rozjetí AOP tedy vypadá takto:
ApplicationContext ac = new ClassPathXmlApplicationContext("properties/SpringBeans.xml"); aoptest.NejakaTrida objekt = (aoptest.NejakaTrida) new aoptest.NejakaTrida(); objekt.metoda(); // <--- zde AOP zavolá napřed metodu aoptest.AopTestAdviceBean::test().
A k tomu samozřejmě definice příslušných tříd, myslím, že nemá cenu je zde vypisovat, jsou zcela obyčejné.
Použil jsem:
Konkrétně tyto .JAR soubory:
Tučně zvýrazněné jsou nutné (rozuměj „bez nich mi to nešlo“). U ostatních nevím – je možné, že některé jsou navíc, ale takto mi to funguje a tak neřeším.
Tolik tedy ke Spring AOP. Snad jsem na nic nezapomněl, ale v podstatě je to dost jednoduché.
Cokoliv dalšího nastudujete z velmi obsáhlého referenčního manuálu Springu, zejména oblasti:
I am about to port Texy! to Java.
But that's a long-term plan, therefore this page is here as a placeholder.
Texy! author, David Grudl, created a test suite of several Texy! formatted files, which can be used to validate the implementation.
Available at http://download.texy.info/refs.zip .
I am looking for a Java regexp lib with support for recursion, like:
<a+(?0)>
. See http://www.php.net/…ecursive.php.
I need it for this expression:
(?:mUi)^/--++ *+(.*)(?: *(?<= |^)\\.((?:\\([^)\\n]+\\)|\\[[^\\]\\n]+\\]|\\{[^}\\n]+\\}|<>|>|=|<){1,4}?))?$((?:\\n.*+)*)(?:\\n(?0)|\\n\\\\--.*$|\\z)
JDK does not support it, ORO does neither, nor Stevesoft Pat does.
dev.java.net
is sooooo
slooow…Gone to Google Code: http://code.google.com/p/jtexy/
ORO developement stalled in 2004? Is Jakarta Regexp a successor? Is Jakarta Regexp PERL compatible? ORO claims so, Regexp does not.
// parse loop $matches = array(); $priority = 0; foreach ($this->patterns as $name => $pattern) { preg_match_all( $pattern['pattern'], $text, $ms, PREG_OFFSET_CAPTURE | PREG_SET_ORDER ); foreach ($ms as $m) { $offset = $m[0][1]; foreach ($m as $k => $v) $m[$k] = $v[0]; $matches[] = array($offset, $name, $m, $priority); } $priority++; }
PREG_OFFSET_CAPTURE
– makes the returned multidimensional
array even more multidimensional – stores the string at [0] and the offset at
[1] (well, PHP is really that shitty).
PREG_SET_ORDER
– the matches are ordered so that sub-group is
next to it's parent group or it's sibling (depth-first instead of
breadth-first).
|...|U
makes all quantifiers ungreedy:
You could also make ALL the quantifiers in a regular expression „ungreedy“ by using the U modifier. http://www.skdevelopment.com/…ressions.php
No Java library supports global ungreediness! :-((
* StackOverflow
post:
* Java forums
post:
* Java
forums archive:
* Ales Novak – ales A netbeans.com
* java.util.regex JavaDoc: http://java.sun.com/…Pattern.html
* java.util.regex tester: http://www.regexplanet.com/…e/index.html
* OpenJDK should support LAZY
* There's a PHP port to Java: http://www.java2s.com/…java-doc.htm
* I could hack the JDK code: http://hg.openjdk.java.net/…Pattern.java
* http://hg.openjdk.java.net/…Pattern.java
* 2721 private void addFlag(), 2760 private void subFlag()
preg_match_all()
:Is this the same as multiple calls to preg_match()
?
→ preg_match()
returns the number of times pattern matches. That
will be either 0 times (no match) or 1 time because preg_match()
will stop searching after the first match. preg_match_all()
on the
contrary will continue until it reaches the end of subject.
Is there similar in Java, or do I have to iterate?
Original design is, despite of author's credits,… not perfect.
* The way modules are registered
* and whole callback system
RegExp.Patterns.php
– slash hell – do the slashes belong
to RE or to PHP?
protect() – will I preserve it? Yes.
Is dom4j or jDOM enough for #JTexy? Yet seems so.
modifier.decorate( elmRet ) dosn't need texy reference – it should keep it from it's creation.
Why Texy doesn't keep $handler
, $pattern
,
$name
together in a
class
? function registerLinePattern($handler, $pattern, $name)
WTF, list(, $mParam, $mMod, $mContent) = $matches;
everywhere?
Again, why not put it in a class
?
$pattern . 'Am', // anchored & multiline
→ #JTexy: Is it
the same as prepended ^
?
TexyParser.php @ 169: $priority++;
– later patterns have
higher priority? No, the other way.
What is TexyLineParser.again
good for? Never set to
true
?
Zdravím,
mám pár návrhů na mírný refactoring parseru:
1) Zavést třídu pro patterny; handlery uložit k patternům rovnou jako referenci funkce.
public class RegexpInfo { public String name; public String perlRegexp; public String regexp; public String flags; public String mode; public String htmlElement; // Handler of this pattern - a "callback". public PatternHandler handler; public enum Type { LINE, BLOCK }; public Type type = Type.LINE; }2) V parseru: Výsledky
preg_match_all()
převést na pole objektů, místo pole polí (… polí polí, jak je zvykem v PHP).class ParserMatchInfo implements Comparable<ParserMatchInfo> { public final RegexpInfo pattern; public final List<MatchWithOffset> groups; public final int offset; public final int priority; }Taková třída je taky přirozeným místem pro funkci
cmp()
.3) Při vytváření objektu s informacemi o matchnutí rovnou uložit referenci na použitý patten, místo jeho jména.
Zaprvé se tak ušetří jeden lookup, zadruhé to zpřehlední kód.4) V názvech proměnných zavést pojem
group
pro skupiny matchnutí reg. výrazu. „Match“ ponechat pro celý match.
Aneb:preg_match_all( $pattern['pattern'], $text, $ms, PREG_SET_ORDER ); $matches[0]; // --> First match $matches[0][0]; // --> Group - matched text of the whole first match. $matches[0][1]; // --> First sub-group of the first match.Tak nebude nutné pojmenovávat proměnné $ms, $matches, $m, $mMatches, …
**5) Přesunout TexyParagraphModule.process() do TexyBlockParser
**6) Zavést třídu ParserEvent, dědit od ní a tyto používat pro model událostí.
Jsou to všechno interní věci, takže to nikoho moc netrápí, ale když už je to ten opensource a někdo by to mohl chtít časem hackovat… ;-)
Ondra
PS: Kódy jsou v Javě; nápady na refaktorizaci totiž pocházejí ze vznikajícího JTexy.
Regex: Support for UNGREEDY or (?U) flag
Perl regular expressions have „/…/U“ and „(?U)“. Many of text processing tools based on regexp use this extensively (e.g. Texy).
These tools are done in a way that makes quite hard to add the ungreedy
(reluctant) mode, using .*?
, to all closures – they have many
regular expressions (few dozens to hundreds), and many of them change with each
release.
Regex: „.*foo“ with UNGREEDY flag or „(?U).*foo“ String: „AAAfooBBBfoo“
Desired result:
group(1): AAAfoo
group(2): BBBfoo
Current result:
group(1): AAAfooBBBfoo
String inputStr = „AAAfooBBBfoo“; String patternStr = „.*foo“;
Pattern pattern = Pattern.compile(patternStr); Matcher matcher = pattern.matcher(inputStr);
… etc.
Well, changing all closures to be reluctant. sigh
Texy je bezesporu jeden z pokladů českého opensource. Je škoda, že je zatím jen pro PHP.
Zdravím,nechtěl by někdo čirou náhodou implementovat překladač Texy v Javě?
Mohlo by to být dobré téma projektu / bakalářky… Formální specifikace není, jen podle popisu syntaxe a ukázek použití…
Java komunita by vás jistě oslavovala :-)
Ondra
Autor Texy David Grudl sestavil sadu testovacích souborů, na kterých lze ověřit implementaci překladače. K dispozici na http://download.texy.info/refs.zip
Algou a omegou původní PHP imiplementace jsou PCRE. Knihovna pro Javu, která zvládá PCRE podle Perl 5, je na http://jakarta.apache.org/oro/ .
Ondra Žižka