<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;D0ENQn4yfip7ImA9WhRaE0U.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092</id><updated>2012-02-16T10:48:13.096+01:00</updated><category term="jce" /><category term="instrumentation" /><category term="JPA" /><category term="StAX" /><category term="JSP" /><category term="cluster" /><category term="algoritmus" /><category term="MQ" /><category term="Utils" /><category term="glassfish" /><category term="JAX-RS" /><category term="vizsga" /><category term="Módszertan" /><category term="open source" /><category term="Oracle" /><category term="IDE" /><category term="SOA" /><category term="scjp" /><category term="Swing" /><category term="EJB" /><category term="Community" /><category term="JNDI" /><category term="Tesztelés" /><category term="git" /><category term="JAXB" /><category term="Java SE" /><category term="Naplózás" /><category term="lb" /><category term="JMS" /><category term="EAI" /><category term="JAX-WS" /><category term="jca" /><category term="Spring" /><category term="xhtml" /><category term="biztonság" /><category term="Servlet" /><category term="xml" /><category term="VisualVM" /><category term="Struts" /><category term="szemantikus web" /><category term="JBoss" /><category term="scalability" /><category term="Java EE" /><category term="Subversion" /><category term="security" /><category term="Library" /><category term="monitorozás" /><category term="könyv" /><category term="UML" /><category term="Oktatás" /><category term="jvm" /><category term="NetBeans" /><category term="Tomcat" /><category term="PKI" /><category term="JMX" /><category term="ha" /><category term="infrastruktúra" /><category term="DocBook" /><category term="oo" /><category term="Maven" /><category term="BI" /><category term="Ant" /><category term="hotspot" /><title>JTechLog</title><subtitle type="html">Java blog</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>99</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/JTechLog" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="jtechlog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DUYHSX0_fyp7ImA9WhRUF0U.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-2913251681129038831</id><published>2012-01-28T22:43:00.001+01:00</published><updated>2012-01-28T22:45:38.347+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-28T22:45:38.347+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Community" /><title>Űrlap eredmények, könyvsorsolás</title><content type="html">A &lt;a href="http://jtechlog.blogspot.com/2012/01/visszatekintes-2011-re.html"&gt;Visszatekintés 2011-re&lt;/a&gt; postomban szerepelt egy kérdőív, melyet összesen 26 válaszadó töltött ki. Ezúttal is köszönöm mindenkinek a segítséget, ötleteket, jókívánságokat! A válaszadók között volt végzős egyetemista, junior, de 10-13 éve Java-ban fejlesztő senior, és vezető fejlesztő is. Kb. kétszer annyi senior fejlesztő töltötte ki, mint junior, pár vezető beosztásban dolgozó. Általában mindennel foglalkoznak (backend és frontend is, ismerik és használják a teljes stack-et), számomra meglepő módon csak kevesen írták csak az egyiket. Emellett kitöltötte olyan is, aki mindennapjaiban üzemeltet (is), oktat, tesztel, vagy a build folyamatokkal foglalkozik.&lt;br /&gt;
&lt;br /&gt;
A témák, melyek érdeklik a válaszadókat, és akár konferenciákra is elmennének azzal kapcsolatban, nagyon változatos. Nem volt egyszerű összesíteni, de nem akartam feleletválasztással megkötni a kezeteket, de így is sokan a zárójelbe tett ötletekből csemegéztek. Amiről a válaszadók legszívesebben olvasnának, az magasan a különböző módszertanok, kb. dupla annyian szavaztak rá, mint a második helyezettre. Ahhoz képest, hogy az az elterjedt hit, hogy a fejlesztők nem szeretnek tesztelni, a második helyen a tesztelés/teszt eszközök bemutatása végzett. Számomra meglepő volt, hogy alap JDK-s dolgokról is szívesen szeretnek olvasni, nem kell mindig más technológia után kutakodni. Ezt megerősíti az is, hogy a &lt;a href="http://jtechlog.blogspot.com/2011/12/java-memoriakezeles-szemetgyujto.html"&gt;Java memóriakezelés, szemétgyűjtő algoritmusok&lt;/a&gt; postom is kiemelkedően látogatott. Számomra furcsa, hogy az OSGi-t egy ember említette meg, úgy látszik csökken a népszerűsége. A konferencia fő érdeklődésre számot tartó témái: Java 7 újdonságok, Java EE, cloud, SOA és mobil fejlesztés. Egyrészt nagyon jól csinálják a mostani konferenciák szervezői, mert minden ezekről szól. Másrészt az nagyon érdekes, hogy a válaszadók ezeket a témákat általában nem jelölték meg, hogy a blogomon olvassanak róla. Harmadrészt a JavaFX szinte senkit nem érdekel. A SOA, bár sokan elcsépelt buzzwordnek tartják, mégis előkelő helyen van. A Java jövőjével kapcsolatban általában nincsenek nagy félelmek. A hype ugyan alábbhagyott, de azért mindenki szereti (különben nem olvasnák a blogot), és kivár. Többeknek nem tetszett az Oracle felvásárlás, de szerintük azért talán a Java jövőjét nem fenyegeti.&lt;br /&gt;
&lt;br /&gt;
És akkor kicsit a statisztikáról is. A legtöbb válaszadó nem kizárólag Java-ról akar olvasni. Az olvasók felének jó így a szint, másik fele azt választotta, hogy legyen általános és technikai is. A válaszadók többségének jó így a postok hossza, sokan nem bánnák, ha a hosszúak között lennének rövidebbek is.&lt;br /&gt;
&lt;br /&gt;
És akkor a jövőről. Az űrlap kitöltése alapján azt látom, hogy gyökeres változtatásra nincs szükség. Témák tekintetében a JDK-val és a teljesítményhangolással foglalkozó postokat is igyekszem írni. A válaszadók gyakran való életbeli példákat szeretnétek. Talán nem hangsúlyozom eléggé, de a postok nagy részének alapja egy probléma, amibe a való életben futok bele. A mögé teszek egy kis hátteret is, és a probléma megoldását is megírom. A későbbiekben igyekszem a konkrét környezetet jobban bemutatni. A elvekkel, módszertanokkal, megmondásokkal kapcsolatban van egy kis félelmem. Ugyanis a technológiák, eszközök általában egzakt valamik, amiről viszonylag objektíven lehet írni (mármint egy probléma egy eszközben való megoldásáról, nem magáról az eszközről). Az elvek nem mindig ilyenek, nagyon kevés általánosan elfogadott alapszabály létezik. Gondoljunk bele, hogy pl. a singleton is mennyire megosztja a fejlesztőket, de beszélhetnénk itt a CI-ről, AOP-ről, agilis fejlesztésről, extrém programozásról, TDD-ről, stb. Általában megpróbálok objektív maradni, de így sem mindig sikerül. Ilyen jellegű postokra inkább az év közepétől számíthattok. Másik téma, amiről mindenképpen többet szeretnék írni, az a tesztelés, teszt vezérelt fejlesztés. Amiről biztos, hogy nem fogok írni a közeljövőben, az a JavaFX, OSGi és a JVM-en futó alternatív nyelvek. Tudom, az utóbbi többeknek kedvence, de jelenlegi munkámban még nem látom az alkalmazhatóságukat, nem tartom őket annyira kiforrottnak sem, és a csapat, amelynek tagja vagyok, sem rendelkezik elegendő kompetenciával, hogy be mernénk vetni. Szabadidőm inkább a Java közli technológiáknak szentelem. Egyedül a Jython, ami néha-néha előkerülhet, a többi addig nem, míg megfelelően el nem terjed. A témákat megpróbálom sokszínűen tartani, a szintet sem módosítom. Alapvetően a hosszabb cikkekre fogok továbbra is koncentrálni, de igyekszem rövidebb cikkeket is beszúrni. Köszönöm a javaslatokat, hogy több forráskódot és képet szerepeltessek, ezeket is igyekszem betartani.&lt;br /&gt;
&lt;br /&gt;
A Java 2 útikalauz programozóknak című könyvet i***a@gmail.com e-mail címmel rendelkező válaszadó nyerte, már tud róla, gratulálok!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-2913251681129038831?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/2913251681129038831/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2012/01/urlap-eredmenyek-konyvsorsolas.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/2913251681129038831?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/2913251681129038831?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2012/01/urlap-eredmenyek-konyvsorsolas.html" title="Űrlap eredmények, könyvsorsolás" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEADSH8yeCp7ImA9WhRVGEw.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-340189829288615845</id><published>2012-01-16T00:47:00.002+01:00</published><updated>2012-01-17T16:06:19.190+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-17T16:06:19.190+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Módszertan" /><title>Ki is az a Java architect?</title><content type="html">Manapság Magyarországon is egyre gyakrabban keresnek Java architect-et, de kérdés, hogy ez a pozíció vajon milyen feladatokkal járhat? Egzakt definíciója nincs, az itt leírtak a saját tapasztalataim és véleményem tükrözik. Be kell vallanom, a &lt;a href="http://java.dzone.com/articles/technical-job-interview"&gt;Technical Job Interview Questions for Java EE architects&lt;/a&gt; cikk is nagyon elgondolkodtatott.&lt;br /&gt;
&lt;br /&gt;
Az architect szó a görög arkhitecton szóból származik, ami az arkhi (vezető) és tekton (építész) szóból áll, így nagyjából vezető építészt jelent. A főnököm főkonstruktőrt szokott emlegetni, ami nekem szimpatikus és ráadásul magyar kifejezés. Az informatika ezt a kifejezést is az építészetből vette át, mint pl. blueprint vagy a tervezési minta szavakat.&lt;br /&gt;
&lt;br /&gt;
A szoftverfejlesztés az architect fogalmát kb. az 1990-es évek végén vette át, amikor is a szoftver rendszerek egyre bonyolultabbakká váltak, és a szoftverfejlesztési problémák megoldására elkezdett terjedni az objektumorientált programozás. Már nem egyedülálló, monolitikus, szigetként működő alkalmazásokat kellett fejleszteni, hanem más rendszerekhez illeszkedni tudó, azokkal kommunikáló, komoly üzleti logikát megvalósító szoftver rendszereket. A megoldást a rendszerek kisebb alrendszerekre való szétvágása, illetve az alrendszerek több rétegre való bontása jelentette. Elterjedtek a két, három és n-rétegű architektúrák, lassan minden nagyvállalati (enterprise) lett. A rendszerek közötti kapcsolatok megvalósítását az Enterprise Application Integration-től (EAI) várták, amely nem más, mint olyan architektúrális elvek gyűjteménye, melyek az integrációt hivatottak megoldani. És szükség volt valakire, aki az ilyen bonyolult rendszerekkel kapcsolatban képes volt felmérni az igényeket, azonosítani a kockázatokat, becsülni, magas szinten megtervezni és specifikálni a feladatokat, és ellenőrizni a megvalósítást.&lt;br /&gt;
&lt;br /&gt;
Az előzőekből is kiderül, hogy az architect az üzlet és az informatika között helyezkedik el. Ismeri, megismeri, érti az üzleti területet, valamint a megrendelő által megfogalmazott, a rendszerrel kapcsolatos üzleti elvárásokat, az un. funkcionális követelményeket. Az architect feladata ezen követelmények informatikai vetületeinek feltárása, és az informatika felé ezek közvetítése. Az üzleti problémákra technológiai megoldásokat képes adni.&lt;br /&gt;
&lt;br /&gt;
Vegyük sorba, hogy egy szoftverfejlesztés életciklusát alapul véve, melyik fázisban milyen feladatai lehetnek az architect-nek, és ez alapján azt, hogy milyen képességekkel kell rendelkeznie.&lt;br /&gt;
&lt;br /&gt;
Az architect tehát egy szoftverfejlesztési projekt legelején, már az ajánlatírás fázisában aktívan beszáll a projektbe. Egyrészt megérti a funkcionális követelményeket. Ezen kívül képes felmérni a rendszerrel kapcsolatos nem funkcionális gyakran minőségi követelményeket, melyek azok az elvárások, melyek nem konkrétan egy üzleti használati esethez köthetőek. Ilyen pl. a teljesítmény, magas rendelkezésre állás, hibatűrés, skálázhatóság, biztonság, fenntarthatóság, továbbfejleszthetőség, üzemeltethetőség, tesztelhetőség, használhatóság, felhasználói felülettel kapcsolatos követelmények, stb. Nem funkcionális igényként fontos definiálni az ügyfél oldali megszorításokat is, mint pl. a kötelezően használt platformok, eszközök, valamint a más rendszerekhez való illesztési lehetőségeket és elvárásokat. Meg kell említeni a módszertannal kapcsolatos és dokumentációs követelményeket, jogszabályoknak való megfeleléseket és a szakterületi szabályokat. Ezen igények egy része mérhető bizonyos mérőszámok definiálásával, más követelmények azonban korántsem ennyire egyértelműek. A nem funkcionális követelmények érkezhetnek az üzleti oldal, de a megrendelő informatikai gárdája felől is.&lt;br /&gt;
&lt;br /&gt;
Ugyanígy képes felmérni a szállító oldali lehetőségeket is. Ismeri a fejlesztési csapatot, és annak képességeit, a fejlesztők által használt szabványokat, technológiákat és eszközöket.&lt;br /&gt;
&lt;br /&gt;
Ezáltal már az ajánlati fázisban aktívan szerepet kell vállalnia. A követelmények alapján ugyanis azonosítania kell a technológiai kockázatokat, általánosságban a megvalósíthatóságot. A kockázatokat minél előbb fel kell ismernie, és osztályoznia. Becsülnie kell, egy probléma bekövetkezésének valószínűségét, valamint a bekövetkezése által okozott kárt, az elhárításának erőforrás igényét. Valamint meg kell határoznia, hogy milyen erőforrás szükséges a probléma kialakulásának megakadályozására. Ezek alapján egy rangsort kell felállítania.&lt;br /&gt;
&lt;br /&gt;
Ezek alapján víziót kell alkotnia. Bizonyos helyzetekben lehet, hogy prototípus építésére is szükség lehet. És ez alapján erőforrást is kell becsülnie. Látható tehát, hogy már a projekt elején kiemelt szerepe van, hiszen a projekt alapvető sikeressége függ egy jó architektúrán, egy pontos becslésen, mely kihat az árajánlatra, a projekt költségvetésére is. Nem utolsósorban az architect-nek olyan magas szintű döntéseket kell hoznia, mely a projektben részt vevő összes személyre kihat, hiszen az ő által kidolgozott koncepciót kell megvalósítani az általa megbecsült idő alatt, így rajta is múlhat, mennyire motiváltak a projekt tagok, esetleg mennyi túlórát kell a projektbe fektetni.&lt;br /&gt;
&lt;br /&gt;
A követelmény elemzés és tervezés fázisában szintén nagy részt kell vállalnia. Ki kell választania a problémás használati eseteket, és előre priorizálnia. A szoftverrendszer magas szintű tervezését kell elvégeznie és dokumentálnia. Milyen alrendszerekből álljon, ezek hogyan kommunikáljanak egymással és külső rendszerekkel, valamint hogyan épüljenek fel. Milyen eszközök és technológiák használandóak. Itt lehet szükség bonyolultabb prototípusok építésére is. A prototípusoknak több fajtája lehet, eldobandó, továbbfejleszthető és architektúrális. Az eldobandó csak valaminek a kipróbálására jött létre, a továbbfejleszthető akár a későbbi rendszer alapjául is szolgálhat, és az architektúrális az architektúra elemek helyes együttműködésének tesztelésére szolgál, melyet mintaként használva felépíthető a rendszer. Az architektúrális tervezés és a rendszertervezés között több különbség is van, melyet érdemes tisztázni. Az architektúrális tervezés magasabb absztakciós szinten van, nem olyan részletes. Általában csak rendszer/alrendszer szintig megy, illetve azok rétegeit tárgyalja, de részletesen nem foglalkozik a rétegekben szereplő komponensekkel. Általában a nem funkcionális követelményekre, és a kockázatos funkcionális követelményekre koncentrál. Átnézi az elkészült dokumentációkat.&lt;br /&gt;
&lt;br /&gt;
Az implementáció és tervezés során támogatja és ellenőrzi a fejlesztőcsapatot, az egész fejlesztési folyamat előrehaladását nyomon követi. Kidolgoz belső fejlesztési szabványokat, és folyamatosan figyeli azok betartását. Fejlesztők architektúrális kérdéseit igyekszik megválaszolni, segít az esetleges architektúrális módosítások végrehajtásában. A fejlesztés közben workshop-okat rendez az aktuális fejlesztés közben felmerült problémákról, és moderál úgy. Ezek nem akaszthatják meg a fejlesztést, nem lehet kötelező program. Ismernie kell a fejlesztési metodológiát, a használt eszközöket. Ha kell, felgyűri az ingujját, és akár kódolással segíti egy probléma lokalizálását, megoldását. Otthonosan mozog a build, release, deploy folyamatokban. Ugyanígy magas szintű rálátása van a tesztelési folyamatokra, eszközökre (harness) is, hiszen az architektúrákkal kapcsolatban egyre erősebb igény a minél kényelmesebb tesztelhetőség.&lt;br /&gt;
&lt;br /&gt;
A bevezetés és a támogatás során folyamatosan tartja a kapcsolatot az üzemeltetéssel is, a feltárt hibákat 2nd level support részeként elemzi, kategorizálja, és kommunikálja a fejlesztők felé. Próbálja az üzemeltetés és a fejlesztés közötti gyakran jelentkező szakadékot áthidalni, a feleket egymáshoz közelebb hozni.&lt;br /&gt;
&lt;br /&gt;
Milyen képességekkel kell rendelkeznie egy architect-nek, hogy ezeket a feladatokat el tudja látni? A legfontosabb a megfelelő mennyiségű tapasztalat. Ezt egyrészt megszerezheti tanulás révén, folyamatos képzésekkel, önképzéssel, a trendek figyelésével, tájékozottság fenntartásával. Másrészt rengeteg gyakorlati tapasztalattal kell rendelkeznie. Úgy gondolom, egy cégnél több évig (&amp;gt;5) maradó architect elveszik a napi rutinban, hiszen nem találkozik más problémákkal, emberekkel, megoldásokkal, gondolatokkal. Ezért érdemes vagy váltani, vagy részben máshol is ilyen jellegű tevékenységeket vállalni.&lt;br /&gt;
&lt;br /&gt;
Egy architect-nek rendelkeznie kell menedzsment képességekkel és technikai tudással is. Kockázatokat kell kezelnie. Másrészt becsléseket kell végezni. Ez sajnos nem tanulható, csak tapasztalat segíthet abban, hogy egy probléma megoldása az adott környezetben mennyi erőforrást igényel. Állandóan döntéseket kell hoznia. A döntéseket folyamatosan dokumentálni szükséges, ugyanis nem csak egy döntés, de az ahhoz vezető út is nagyon fontos lehet a projekt szempontjából. Nagyon sok projekt esetében hangzott el a kérdés, mikor a projekt előrehaladása folyamán egy döntés logikátlannak tűnt, hogy vajon az elején miért is ez lett meghozva.&lt;br /&gt;
&lt;br /&gt;
Nagyon jó kommunikációs képességekkel kell rendelkeznie. A projekt során szinte az összes projekttaggal kapcsolatban van. Nagyon fontos a követelmények felmérésénél, a víziójának másokkal való elfogadtatásával. Gondoljunk bele, az ő döntései a csapat minden tagjára kihatnak, nem mindegy, hogy mennyire tudja ezeket a többiekkel elfogadtatni. Nem ülhet elefántcsonttoronyban, és ott olvassa a dokumentációkat, és készíti a specifikációit. A fejlesztés során is végig mentoring tevékenységet kell végeznie.&lt;br /&gt;
&lt;br /&gt;
A jó architect megoszt. Megosztja a tapasztalatait, véleményeit, az érdekességeket, melyekkel találkozik. Megosztja a döntéseihez vezető utak lépéseit, a döntésnél figyelembe vett érveket. Megosztja a specifikációkat, dokumentumokat, a pilot eredményeit. Megosztja a vízióját.&lt;br /&gt;
&lt;br /&gt;
Az architect-nek nem feladata mindennek a felderítése, megtervezése. A kollégáira támaszkodik, az általuk adott specifikus tudásokból állít össze egy architektúrát. Figyelembe veszi infrastruktúrális ügyekben az üzemeltetőket, fejlesztési kérdésekben a programozókat, tesztelési kérdésekben a tesztelőket. De érti mindegyik nyelvét, és az átadottakat tudja az üzlet felé kommunikálni, és fordítva. Darabokból épít egészet.&lt;br /&gt;
&lt;br /&gt;
Nem mehet minden probléma mélyére, tudnia kell, mikor kit kell megkérnie. Ha megtenné, elaprózná az idejét, és újra az elefántcsonttoronyban kötne ki, immár technológiai problémákkal körülvéve. A feladatokat meg kell tudnia osztani.&lt;br /&gt;
&lt;br /&gt;
Gyakori kérdés, hogy jól kódol-e az architect? Nem feltétlenül. Persze nem árt, de a többi dolga mellett erre már kevésbé jut ideje, és valljuk be, ha az ember nem 8 órát kódol folyamatosan, ki lehet menni a gyakorlatból. Nem ismeri az eszközöket és API-kat sem olyan mélységben. De egy adott problémát meg tud valósítani, lehet, hogy nem olyan elegánsan, mint egy fejlesztő, feltehetőleg nem is annyi idő alatt, de hasonló megoldásokkal. Kódot olvasni tud, debugol, optimalizál. Ismeri a legjobb gyakorlatokat és tervezési mintákat. Rengeteg tapasztalata van, hogy egy probléma más rendszerekben hogyan került megoldásra. Valamint dereng még senior vagy vezető programozó korából, hogy akkor hogyan is csinálta. A tudásának ereje nem is a tudásának mélységéből, hanem szélességéből adódik. Tudja mit hol kell keresni. Kódolási képességek nélkül nem fogadják el a fejlesztők.&lt;br /&gt;
&lt;br /&gt;
Jó dokumentálási képességekkel kell rendelkeznie, tudnia kell írnia. Rögzíteni a döntéseket, és azok indokait, valamint a vízióját írásban is át kell tudnia adni a feleknek, akár egy ajánlat, akár egy specifikáció esetén.&lt;br /&gt;
&lt;br /&gt;
Maximális mértékben figyelembe kell vennie a körülményeket, alkalmazkodnia kell. Nem szabad abba a hibába esnie, hogy az önéletrajzának bővítse miatt választ technológiát, nem az adott projekten próbál ki új dolgokat, vagy mert csak ahhoz ért. Figyelembe kell vennie a csapatot. Ahhoz, hogy egy feladatot a leghatékonyabban lehessen elvégezni, a maximális újrafelhasználhatóság szükséges, tudásban is. A csapat tudásának megfelelően kell megoldásokat, módszertanokat, eszközöket, technológiákat, szabványokat választania. Nem választ ki egy programozási nyelvet, mert az menő, vagy alkalmasabb a feladatra, ha a fejlesztők közül egyik sem használta még, akár ő sem. Félre kell tenni a személyes preferenciáit.&lt;br /&gt;
&lt;br /&gt;
Amennyiben egy architect nem csak egy konkrét projekten dolgozik, hanem egy cégnél hosszabb távon alkalmazásban áll, érdemes valamilyen stratégián is dolgoznia. Egyrészt be kell gyűjteni a menedzsment felől érkező, még csak a távolban felvillanó üzleti igényeket, és beszélnie kell a fejlesztést végző csapat minden tagjával, hogy mit éreznek nehéznek, problémásnak. A kettőt egybegyúrva, minden oldallal egyeztetve kell kialakítania egy olyan stratégiát, mely egyre gördülékenyebbé és hatékonyabbá teszi a fejlesztéseket, nem korlátoz, és az új tagok munkába állását is kellően megkönnyíti.&lt;br /&gt;
&lt;br /&gt;
No de evezzünk egy kicsit technikai vizekre, nézzük, miben kell otthonosan mozognia egy ilyen szakembernek. Az elosztott rendszerek térhódításával jelent meg az igény az architect-ekre is. Hiszen minél nagyobb az elosztottság, annál több a kihívás, annál több választási lehetőség van. Egy alrendszer is egyre bonyolultabbá és bonyolultabbá válhat. A problémamegoldás egyik hatékony fegyvere a dekompozíció, komponensekre bontás. A komponensek együttműködnek, köztük interfészek helyezkednek el. Fontos az egységbe zárás (encapsulation). Az interfészek használata megkönnyíti a cserélhetőséget, tesztelhetőséget. A komponenseket megfelelően szét kell tudni választani, mindnek csak a saját feladatát kell tudnia elvégeznie (resposibility). Kialakult az Enterprise Application Integration, valamint a Service Oriented Architecture. Látható, hogy mélyebb szinten, alkalmazáson belül ugyanezeket az elveket kell alkalmazni, és látható, hogy az előbbi fogalmak egy az egyben jelennek meg objektumorientált programozás esetén is. High cohesion, low coupling. Ezeket a komponenseket és a komponensek közötti kapcsolatokat magasabb absztrakciós szintre kell emelni, modellezni kell. A rendszereket különböző nézőpontokból kell megfigyelni, pl. statikus esetben a rendszer felépítését, dinamikus esetben a rendszer működését. Ezeket valahogyan ábrázolni kell, kifejező leíró nyelv erre az UML. Fontos, az architect nem a való világ megfelelő darabját szakítja ki (üzleti terület), mint a tervezők, hanem már rendszer szinten, n agyon magas szintű objektumokban gondolkodik, informatikai fogalmakban. Leghasznosabb eszköze a component, deployment és sequence diagram. Gyakori problémákra gyakori, elterjedt megoldásokat alkalmaz, tehát ismeri a tervezési mintákat és személyre tudja szabni azokat. És itt nem kizárólag a Gang of Four tervezési mintákra kell gondolni, hanem az un. architectural pattern-ekre is. Ide kapcsolódik szorosan a refactoring is.&lt;br /&gt;
&lt;br /&gt;
Be kell vetnem pár bűvös szót is, felsorolásképpen, szigorúan össze-vissza, mely területekkel egy architect-nek már találkoznia kellett a szoftverfejlesztéssel kapcsolatban: webszolgáltatások (SOAP/REST), SOA, cloud, event driven architecture, domain driven design, Behaviour-Driven Development, test driven development, continuous integration, continuous delivery, agile development, dependency injection, inversion of control, AOP, caching.&lt;br /&gt;
&lt;br /&gt;
A Sun, később az Oracle ennél talán behatároltabban kezeli az architect-et. Végighallgattam egy több napos "Architecting and Designing J2EE Applications" képzést. Ennek első fele kb. a fentebb leírtakat ecseteli meglepően kevés technológiai utalással, későbbi részek már a technológiára mennek rá. Ennek megfelelő a &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=326"&gt;Oracle Certified Master, Java EE 5 Enterprise Architect&lt;/a&gt; vizsga is, érdekes, Java EE 6-ra még nem jelent meg. Az említett linken látható, hogy ez nem csak egy teszt kitöltéséből, hanem azon felül egy esszé megírásából és annak megvédéséből áll.&lt;br /&gt;
&lt;br /&gt;
Természetesen az Oracle a saját komponens architektúráját kéri számon, azaz az EJB technológiát, valamint annak környezetét, a Java EE szabványt. Ez utóbbiból megköveteli a JDBC, JPA, JMS, JCA, Servlet, JSP, JSF, JAXB, JAX-WS ismeretét. Kitér a komponensek környezetét biztosító  alkalmazásszerverekre, valamint a Java EE tervezési mintákra is.&lt;br /&gt;
&lt;br /&gt;
Az EJB mellett azonban ne felejtkezzünk el a Spring-ről és az OSGi-ról sem.&lt;br /&gt;
&lt;br /&gt;
Úgy gondolom, az áttekintő tudás hasznos, de nem megkövetelendő a különböző JVM-re épülő nyelvek, mint pl. a Groovy vagy Scala ismerete, valamint a naprakészség olyan modern irányzatokban, mint pl. a NoSQL eszközök.&lt;br /&gt;
&lt;br /&gt;
Ma már az architect-ek is szakosodhatnak. Lehetnek enterprise architect-ek, akik az alkalmazásintegrációt tartják szem előtt. Lehetnek application vagy system architect-ek, akik az alkalmazások belső felépítéséért felelnek. Lehetnek infrastructure architect-ek, akik az infrastruktúráért felelősek, mint hardver, szerver szoftverek, hálózat, adatbázis, és kedvencük a skálázhatóság, fürtözés, terheléselosztás és újabban a virtualizáció.&lt;br /&gt;
&lt;br /&gt;
Megnéztem több állásportált is, száz Java fejlesztői állásra maximum három-öt Java architect jut. Egyrészt nem annyira elterjedt itthon, másrészt szeretik a cégek a saját szakemberüket kinevelni. Meglepő azonban, hogy ez a pár állás viszont elég pontosan írta le a feladatköröket, azaz tudják, kit keresnek.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-340189829288615845?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/340189829288615845/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2012/01/ki-is-az-java-architect.html#comment-form" title="6 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/340189829288615845?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/340189829288615845?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2012/01/ki-is-az-java-architect.html" title="Ki is az a Java architect?" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>6</thr:total></entry><entry gd:etag="W/&quot;CEQERXYzfSp7ImA9WhRVFk8.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-6156167128518622117</id><published>2012-01-14T22:16:00.006+01:00</published><updated>2012-01-15T11:11:44.885+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-15T11:11:44.885+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Community" /><category scheme="http://www.blogger.com/atom/ns#" term="könyv" /><title>Visszatekintés 2011-re</title><content type="html">&lt;p&gt;Így az év elején az ember kicsit visszatekint, és rendszerezi a gondolatait a jövővel kapcsolatban is.&lt;/p&gt;

&lt;p&gt;A 2011-es év folyamán 20 postot írtam. Kicsit próbálkoztam a nem annyira technikai témákkal is, hanem a szoftverfejlesztéssel kapcsolatos általános gondolataimat is próbáltam leírni, pl. a &lt;a href="http://jtechlog.blogspot.com/2011/05/miert-ne-fejlesszunk-sajat.html"&gt;Miért ne fejlesszünk saját keretrendszert?&lt;/a&gt; postban, amihez magasan a legtöbb megjegyzés érkezett, láthatóan titeket is érint a téma. Látható volt az útkeresésem is, ugyanis a Java világ jövője kicsit bizonytalan, nem is ad mindig annyi lelkesedésre okot, és egy kiegészítő eszközt is kerestem, amivel gyakori ismétlődő feladatokat egyszerűen tudok elvégezni, így esett a választásom a Python-ra (&lt;a href="http://jtechlog.blogspot.com/2011/06/masodik-nyelv-python.html"&gt;Második nyelv: Python?&lt;/a&gt;). Természetesen  bejegyzéseim javát így is azok a dolgok tették ki, amivel projektjeim során találkoztam, így került sor a &lt;a href="http://jtechlog.blogspot.com/2011/07/vastag-kliens-java-ban-netbeans.html"&gt;NetBeans Platform&lt;/a&gt; bemutatására, volt egy post sorozat a Subversion, Maven, release témákban, valamint az év végén egy kis &lt;a href="http://jtechlog.blogspot.com/2011/12/java-memoriakezeles-szemetgyujto.html"&gt;Java teljesítményhangolásról&lt;/a&gt; is szó esett.&lt;/p&gt;

&lt;p&gt;Így év elején letisztáztam az egyéb online megjelenéseim is, így látható jobb oldalon az "Elérhetőségek" doboz, melynek első eleme a Google+. A Google Reader az elsődleges hírforrásom, amiben a Google megszüntette a megosztási lehetőséget, a Google+-ba tereli be. Így én is áttértem, így minden érdekes cikket ott fogok megosztani, ha gondoljátok, kövessetek a &lt;a href="https://plus.google.com/115891152269405230539"&gt;Google+-on&lt;/a&gt;. A megosztások itt a blogban is megjelennek a "Google+" dobozban. Még egy változás történt, ezek után a példa kódokat a &lt;a href="https://github.com/vicziani"&gt;GitHub&lt;/a&gt;-on érhetitek el.&lt;/p&gt;

&lt;p&gt;Persze nem maradhatnak el a statisztikák sem. Magasan a legnézettebb post 2011-ben a &lt;a href="http://jtechlog.blogspot.com/2009/10/java-forrasok-tanulashoz.html"&gt;Java források tanuláshoz&lt;/a&gt;, mely egy kezdőknek szóló, 2009-es post. Második a már említett "Miért ne fejlesszünk saját keretrendszert?", és a harmadik a 2010-es &lt;a href="http://jtechlog.blogspot.com/2010/04/maven-kezdolepesek.html"&gt;Maven kezdőlépések&lt;/a&gt;, ami szintén kezdőknek szól. Az idei postok közül a már említett "Vastag kliens Java-ban? NetBeans Platform", és a "Második nyelv: Python?" volt a legnézettebb. Érdekes, hogy annak ellenére, hogy a Java nem a legmegfelelőbb választás vastag kliens fejlesztésére, mégis sokakat érdekelt, míg az utóbbi nem is Java téma.&lt;/p&gt;

&lt;p&gt;A legtöbb látogatót természetesen a Google hozta, a keresési szavak felhőjét mutatja az alábbi kép. Minél nagyobb egy szó, annál többször kerestek rá. Kedvenc keresési kifejezésem a "Honnét lehet rendelni a pom pomt?" Látszik a keresőszavakból, hogy sokan úgy térnek vissza, hogy emlékeznek nagyjából a post címére, és arra keresnek rá. Szomorú azonban, hogy túl sokan akadnak úgy a blogra, hogy könyvet akarnak letölteni. Sláger a Java Útikalauz programozóknak és a J2EE útikalauz java programozóknak című könyv, de sokan keresnek Angstler könyveket és angol nyelvű könyveket is. Úgy gondolom, hogy érdemes ezeket a könyveket megvásárolni, sokszor le lehet ezeket venni a polcról. Egy darabig gyűjtöget az ember, aztán rájön, hogy mire elolvasná, rég elavult, amennyire meg mégis jut idő, annyit meg is lehet vásárolni. A keresőszavakból az is kiderül a számomra, hogy attól függetlenül, hogy kevés Java tartalom van magyar nyelven, az emberek mégis bíznak, hogy magyarul is találnak valamit.&lt;/p&gt;

&lt;a href="http://1.bp.blogspot.com/-Rjb5aSyqFvY/TxHwxVA8WFI/AAAAAAAAHvk/ruqudhTSNTs/s1600/keresoszavak.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 166px;" src="http://1.bp.blogspot.com/-Rjb5aSyqFvY/TxHwxVA8WFI/AAAAAAAAHvk/ruqudhTSNTs/s320/keresoszavak.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5697599733845743698" /&gt;&lt;/a&gt;

&lt;p&gt;A postokban szereplő gyakori szavak a következők: Java, EJB, NetBeans, Maven, Subversion, build, release, branch, merge, szemétgyűjtő algoritmus.&lt;/p&gt;

&lt;p&gt;Legtöbb látogatót a Google után a &lt;a href="http://www.hup.hu"&gt;HUP&lt;/a&gt; hozott, bár csak pár megjegyzésben szerepel a JTechLog-ra link.&lt;/p&gt;

&lt;p&gt;Azért, hogy a blogot még jobbá tegyem, összeállítottam egy kérdőívet, melynek segítségével megpróbálom felmérni az olvasótábor képzettségi szintjét, az érdeklődésre számot tartó témákat, valamint azt, hogy érdemes-e a blogot valamilyen irányba változtatni. Legyen-e több rövidebb tartalom, vagy a postok szintje legyen más. &lt;a href="https://docs.google.com/spreadsheet/viewform?hl=hu&amp;formkey=dG9EV2dBazlqdjFMenFIb21TWTl0U0E6MQ#gid=0"&gt;Kérlek töltsd ki te is, csak kilenc kérdés!&lt;/a&gt; Mindenki véleménye számít. És azért, hogy lássátok, tényleg odafigyelek az olvasókra, a kérdőívet kitöltők között kisorsolom a három kötetes "Java 2 útikalauz programozóknak" könyvem, CD melléklettel. Amennyiben érdekel a könyv, kérlek mindenképp írd a kérdőívbe az e-mail címedet is. Az eredmény január 28-án várható. Érdemes játszani, mivel viszonylag kicsi az olvasótábor, így nagy esély van a nyereményre. Amennyiben nem érdekel, kérlek a kérdőívet akkor is töltsd ki, ezzel is segítve a blogot, hogy számodra is érdekesebb tartalom jelenjen meg a továbbiakban.&lt;/p&gt;

&lt;a href="http://1.bp.blogspot.com/-klEoCvGzt54/TxHw5KEt8aI/AAAAAAAAHvw/A6iyBDtHwR8/s1600/Java-utikalauz-programozoknak.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 224px; height: 320px;" src="http://1.bp.blogspot.com/-klEoCvGzt54/TxHw5KEt8aI/AAAAAAAAHvw/A6iyBDtHwR8/s320/Java-utikalauz-programozoknak.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5697599868347740578" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-6156167128518622117?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/6156167128518622117/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2012/01/visszatekintes-2011-re.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/6156167128518622117?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/6156167128518622117?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2012/01/visszatekintes-2011-re.html" title="Visszatekintés 2011-re" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-Rjb5aSyqFvY/TxHwxVA8WFI/AAAAAAAAHvk/ruqudhTSNTs/s72-c/keresoszavak.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEYHQ3gyfip7ImA9WhRVEUk.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-8365011667058151286</id><published>2011-12-30T02:10:00.018+01:00</published><updated>2012-01-09T22:55:32.696+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-09T22:55:32.696+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="hotspot" /><category scheme="http://www.blogger.com/atom/ns#" term="jvm" /><title>Java memóriakezelés, szemétgyűjtő algoritmusok</title><content type="html">&lt;p&gt;Technológiák: Java Development Kit 1.6&lt;/p&gt;

&lt;p&gt;A Java tervezésekor egyik legfőbb szempont a biztonság volt. Ez egyrészt megnyilvánul abban, hogy a felhasználó tudja kontrollálni egy nem megbízható forrásból szerzett program hozzáféréseit, másrészt támogatja a programozókat abban, hogy minél kevesebb hibát vétsenek.&lt;/p&gt;

&lt;p&gt;Ez utóbbi egy szelete az, hogy nem explicit kell memóriát lefoglalnunk, és felszabadítanunk, hanem a virtuális gép megteszi ezt helyettünk. Pontosabban a szemétgyűjtő mechanizmus (garbage collector - GC), melynek feladata a nem használt objektumok eltakarítása a memóriaterületről. Így sokkal kisebb a hibalehetőség, cserébe egy automatizmus szabadítja fel a memóriát, aminek külön erőforrásra van szüksége, ami kiélezett helyzetekben (magas terhelés esetén) akár az alkalmazás teljesítményére is hatással lehet. A hibajelenség, amitől megszabadulunk, az a memóriaszivárgás (memory leak). Ez gyakorlatilag akkor történik, mikor már nincs szükségünk egy objektumra, nincs rá referencia, de a memóriaterületet nem szabadítottuk fel. Szerencsére a szemétgyűjtő mechanizmus megteszi ezt helyettünk.&lt;/p&gt;

&lt;p&gt;(Zárójelben jegyzem meg, hogy Java esetén is szoktak memóriaszivárgásról beszélni, azonban ennek kicsit más a jelentése. Ez a leggyakrabban kollekciók használatakor szokott felmerülni. Képzeljük el, hogy egy dinamikus méretű listát egy tömbbel ábrázolunk. Mivel a tömb mérete fix, egy változó jelzi, hogy a tömb épp hány elemét használjuk ki. Amennyiben töröljük az utolsó elemet, a működés szempontjából elegendő csak ennek a változónak az értékét csökkenteni. Ekkor azonban a tömb változón felüli eleme még tart referenciát az adott objektumra, ezért a szemétgyűjtő nem tudja kidobni. Emiatt kell null-ra állítanunk a tömb megfelelő elemét. Tipikus hiba még az eseménykezelők nem használatos objektumon tartása.)&lt;/p&gt;

&lt;p&gt;Fontos megkülönböztetni két memóriaterület, a heap és a stack fogalmát. A példányváltozók és az az összes példányosított objektum a heap-en helyezkedik el. A metódusban definiált, úgynevezett lokális változók vannak a stack-en (, ide tartoznak a metódushívás aktuális paraméterei is). Vigyázzunk, amennyiben a stack-en szereplő lokális változó típusa osztály, az osztály példánya már a heap-en helyezkedik el, a stack-en kizárólag az erre mutató referencia.&lt;/p&gt;

&lt;p&gt;Ezzel kapcsolatban párszor már találkoztam azzal a tévhittel, hogy a Java szemétgyűjtő mechanizmusa referenciaszámláló alapján működik. Azaz nézi, hogy egy objektumra hány hivatkozás van, és amennyiben ez nullára csökken, az objektum eldobható a memóriából. Ez nem így van. Képzeljük el, hogy A objektum hivatkozik B objektumra, és vissza. Amennyiben más hivatkozás nincs rájuk, mindkettő eltávolítható, de a referenciaszámlálója mindegyiknek egy. Ehelyett a JVM a következőképpen működik. Az élő szálak stack-jeiből elérhető objektumokat járja végig. Ez azt jelenti, hogy végigmegy a referenciákon, azaz az objektumokból elérhető objektumokon is. Ezeket megjelöli. (Ezen szabály alkalmazásán kívül még végigmegy a betöltött és még nem kidobott osztályok statikus tagjain, valamint a JNI-ből bejegyzett objektumokon is.) Eztán a nem megjelölt objektumokat kidobja. Azaz kidobja az összes olyan objektumot mely nem érhető el referenciákon keresztül egy élő szálból sem.&lt;/p&gt;

&lt;p&gt;A szemétgyűjtő mechanizmus megvalósítása nem a szabvány része, ezért különböző gyártók különbözőképpen implementálhatják azokat. Én most a legelterjedtebb, Sun (már Oracle) által gyártott, a Java 2 Platform, Standard Edition JDK-ban megtalálható Java HotSpot virtuális gépről fogok írni, továbbiakban JVM. Jó referencia a &lt;a href="http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf"&gt;Memory Management in Java HotSpot Virtual Machine&lt;/a&gt; dokumentum. A JVM-nek három fő része van: runtime, JIT, és a memóriakezelést végző szemétgyűjtő mechanizmus.&lt;/p&gt;

&lt;p&gt;A szemétgyűjtő mechanizmus un. weak generational hypothesis-re épül. Megfigyelték az alkalmazások működését, és a következő szabályokat vették észre:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Az objektumok nagy része rövid életű&lt;/li&gt;
&lt;li&gt;Régi objektumból új objektumra viszonylag kevés hivatkozás van&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ezen megfigyelések az alkalmazások nagy részére igazak, persze lehetnek kivételek. Azaz a legtöbb alkalmazás úgy működik, hogy üzemelése közben gyakorta nagyon rövid életű, temporális objektumot gyárt, mely igazából csak az algoritmusok lefutásáig, a felhasználó kiszolgálásáig kellenek, utána el is dobhatóak. Csak viszonylag kevés objektum kell hosszú távon, és ezek utána hosszú életűek, és általában ritkán hivatkoznak újabb objektumokra. Ezen hipotézis alapján építették fel a szemétgyűjtő mechanizmust, és ezen szabályokkal szembe menni akár a szemétgyűjtő működését is megzavarhatják. (Tipikus példa erre az objektum cache, mely tipikusan a legrégebbi objektum, melybe újabb és újabb objektumok kerülhetnek. Ezeket a szemétgyűjtő kevésbé szereti.)&lt;/p&gt;

&lt;p&gt;A Sun mérnökei a JVM-be ráadásul nem csak egy, hanem több szemétgyűjtő mechanizmust is építettek. Ezek közül a JVM automatikusan képes választani, de akár explicit is megmondhatjuk, hogy melyiket használja. Bizonyos szemétgyűjtő algoritmusok más-más alkalmazások esetén, más-más architektúrákon különbözőképpen teljesíthetnek, így nincs mindenre jó megoldás, nekünk kell vagy a JVM-re hagyatkozni, vagy kiválasztani, hogy melyik a legmegfelelőbb. A választásnál a következőket kell figyelembe venni:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Áteresztőképesség (throughput): a futási idő hány százalékát tölti a CPU az alkalmazásunk futtatásakor nem a szemétgyűjtő futtatásával (persze megfelelő nagy időszeletre nézve)&lt;/li&gt;
&lt;li&gt;GC pluszmunka (overhead): az előző inverze, mennyi időt tölt a CPU a GC futtatásával az összes időhöz képest&lt;/li&gt;
&lt;li&gt;Állási idő (pause time): mennyi ideig áll az alkalmazás, míg a GC fut&lt;/li&gt;
&lt;li&gt;Szeméggyűjtő mechanizmus futtatásának gyakorisága (frequency): milyen gyakran fut a GC&lt;/li&gt;
&lt;li&gt;Memóriaigény (footprint): az alkalmazás memóriaigénye, pl. a heap mérete&lt;/li&gt;
&lt;li&gt;Reakcióidő (promptness): az idő aközött, amikor az objektum begyűjthetővé válik, és aközött, hogy a memória újra felhasználhatóvá válik&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ráadásul ezen mérőszámok egyikének javításakor a másik mérőszám rosszabb lesz, hiszen ellentmondanak egymásnak. Pl. amennyiben azt akarjuk, hogy kevesebbet álljon az alkalmazás, pl. a szemétgyűjtő több szálon dolgozzon, akkor a szálak adminisztrációja megnövekedett erőforrásidénnyel (mind CPU, mind memória) jár.&lt;/p&gt;

&lt;p&gt;Ahhoz, hogy megértsük a szemétgyűjtők működését, először meg kell értenünk a JVM memóriamodelljét. Talán legjobb vizuálisan szemléltetni. Az alábbi ábrára klikkelve bejön egy VisualVM-ben futó Visual GC plugin alapján készített GIF animáció, melyen egy JBoss alkalmazásszervert látunk futni. A VisualVM a JDK-ban megtalálható, a jvisualvm paranccsal indítható. A VisualGC plugin a Tools/Plugins menüpontból indítva külön letölthető. Mindkettő ingyenes, nyílt forráskódú eszköz.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://dl.dropbox.com/u/7683931/jtechlog/visualgc_gifanim.gif" rel="lightbox"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 299px;" src="http://4.bp.blogspot.com/-Hgkvfe-YRjA/Tv0QOVMrD1I/AAAAAAAAHrc/M0vJrloT35I/s320/visualgc_gifanim.gif" border="0" alt="Visual GC plugin egy JBoss futtatása közben" id="BLOGGER_PHOTO_ID_5691723342460686162" /&gt;&lt;/a&gt;

&lt;p&gt;A Spaces ablakban a JVM heap-je látható, ami három részre van felosztva: permanent generation (permgen), young és old. A permgen memóriaterületen helyezkednek el a betöltött osztályok definíciói, valamint a String pool (un. Interned Strings). A young területen (un. generation) helyezkednek el a fiatal objektumok, és az old területen helyezkednek el az idősebb objektumok (az előbb említett hipotézis miatt van ez a megbontás). A szemétgyűjtő mechanizmus mindkét területen lefut, de meg kell különböztetni ezeket. Tehát gyakran lefut az un. minor szemétgyűjtő, mely csak az young generation-ön dolgozik, és ritkábban a major/full szemétgyűjtő, ami az old generation-ön is lefut. Ez ritkábban fut, hiszen lassabban nő, és tovább tarthat, hiszen nagyobb területet kell átvizsgálnia a szemétgyűjtőnek.&lt;/p&gt;

&lt;p&gt;A young generation három részből áll: eden, survivor 0, survivor 1. A frissen példányosított objektumok először az eden-re kerülnek, amikor lefut rajtuk a szemétgyűjtő mechanizmus, és túlélnek (nem kerülnek eldobásra, élő objektumok), akkor kerülnek a survivor (túlélő) egyikére. Egyszerre mindig csak az egyik használt a survivor-ök közül. Amikor lefut a szemétgyűjtő, az a használt survivor-ön is lefut, és a túlélő objektumok átkerülnek a másik survivor területre. Az előző survivor tehát teljesen üres marad. Utána a szemétgyűjtő ismételt lefutásakor a fordított irányban vándorolnak a túlélő objektumok a survivor-ök között. Amennyiben az objektum túlélése elért egy megfelelő számot, átkerül az old generation-be.&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://www.devx.com/Java/Article/21977/1954"&gt;Garbage Collection in the Java HotSpot Virtual Machine&lt;/a&gt; cikk ábráit használva a következő lépésekből áll tehát a young generation-ön a szemétgyűjtés. Az eden és az egyik survivor területen is gyűltek az objektumok.&lt;/p&gt;

&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 400px; height: 203px;" src="http://1.bp.blogspot.com/-pxm2DRTqypQ/Tv0RPi6bNpI/AAAAAAAAHr0/xKb7L8oFg6g/s400/yg_1.png" border="0" alt="Mark-sweep-compact algoritmus első lépése" id="BLOGGER_PHOTO_ID_5691724462833743506" /&gt;

&lt;p&gt;A túlélő objektumok az eden-ből és az egyik survivor-ből is a másik survivor területre kerülnek, valamint az egyik survivor-ből a bizonyos kort megélt objektumok az old generation-be kerülnek.&lt;/p&gt;

&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 400px; height: 304px;" src="http://4.bp.blogspot.com/-P05oLdHGVQM/Tv0RUwSJQ0I/AAAAAAAAHsA/j653Ofy-d3s/s400/yg_2.png" border="0" alt="Mark-sweep-compact algoritmus második lépése" id="BLOGGER_PHOTO_ID_5691724552322237250" /&gt;

&lt;p&gt;A szemétgyűjtés után mind az eden, mind az egyik survivor teljesen kiürül.&lt;/p&gt;

&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 400px; height: 304px;" src="http://3.bp.blogspot.com/-QHLWVHlrIvo/Tv0RYcEuD-I/AAAAAAAAHsM/pxCi8Iw0528/s400/yg_3.png" border="0" alt="Mark-sweep-compact algoritmus harmadik lépése" id="BLOGGER_PHOTO_ID_5691724615616696290" /&gt;

&lt;p&gt;Ha megnézünk egy más parancssori paraméterekkel indított JVM-et (a JDK demo\jfc\Java2D\ könyvtárában a Java2D-t demonstráló példaprogramot a &lt;code&gt;java -jar Java2Demo.jar&lt;/code&gt; paranccsal elindítva) kicsit más karakterisztikát láthatunk, de a működés alapvetően hasonlít. Itt megjelent egy Histogram nevezetű ablak, mely százalékosan mutatja a young generation objektumait, hogy hány százaléka hány szemétgyűjtést élt túl. Az ábrán a Tenuring threshold azt jelenti, hogy 15 szemétgyűjtés túlélése után kerül az objektum az old generation-be.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-YzLzSTOkHKI/Tv0Q_JqbAfI/AAAAAAAAHro/6ZIyvELJiHE/s1600/gc1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 230px;" src="http://3.bp.blogspot.com/-YzLzSTOkHKI/Tv0Q_JqbAfI/AAAAAAAAHro/6ZIyvELJiHE/s320/gc1.png" border="0" alt="Visual GC a Java2Demo futtatása közben" id="BLOGGER_PHOTO_ID_5691724181177827826" /&gt;&lt;/a&gt;

&lt;p&gt;Vizsgáljuk meg az első ábrát, az talán látványosabb. Egyrészt kevésbé észrevehető, hogy a Spaces ablakban a háttér világosabb és sötétebb szürke négyzetekkel van behálózva. A sötétszürke a ténylegesen lefoglalt memóriát (utilized, commited), míg a világosabb szürke a JVM által lefoglalható, de még nem lefoglalt memóriát jelzi (uncommited). A konkrét értékek látszanak a Graphs ablakban is. Látható, hogy a young generation esetén az eden-ben lévő objektumok összmérete folyamatosan nő, mígnem a GC grafikonon látjuk, hogy lefut egy szemétgyűjtés (zöld tüske), és ekkor az eden kiürül. Ezzel egy időben azt is látjuk, hogy a túlélő objektumok az egyik survivor-ből átkerülnek a másikba, nagyon szépen látható a narancs grafikonon, hogy egyszerre csak az egyik használt, és mérete nem változik, csak a szemétgyűjtés lefutásakor. Egy normál működésű szerver alkalmazásnál ha ilyen szép fűrészfoggal találkozunk, akkor megnyugodhatunk. Amennyiben a fogak túl sűrűek, ott baj lehet, hiszen a GC-nek gyakran kell futnia, ez egyrészt gyakrabban állítja le az alkalmazást, másrészt több erőforrást is igényel. Amennyiben a szemétgyűjtő lefutása után nem esik vissza a memóriahasználat, akkor is baj van, mert akkor valószínű, hogy memóriaszivárgásunk van. A permgen mérete általában állandó, vagy nagyon lassan növekszik. Ha az telik be, akkor találkozhatunk a java.lang.OutOfMemoryError: PermGen space hibával. Ez általában akkor van, amikor újratelepítgetünk egy alkalmazást az alkalmazásszerveren, és valami osztálybetöltő probléma miatt az előző alkalmazásunkat a konténer nem tudja kidobni, így annak class-ai is a permgen-en maradnak. Ami egy idő után, bizonyos számú telepítés után elfogyhat.&lt;/p&gt;

&lt;p&gt;Amennyiben az egyik survivor betelne, az ide kerülendő objektumok automatikusan az old generation-be kerülnek átmásolásra. Ezt a hibajelenséget premature promotion-nek nevezik. Amennyiben emiatt betelik az old generation is, és le kell futtatni a GC-t, promotion failure-nek nevezik.&lt;/p&gt;

&lt;p&gt;Amennyiben elfogy a memória, az OutOfMemoryError-t kapjuk. Jegyezzük meg azonban, hogy a JVM garantálja, hogy csak akkor dobja, ha a GC lefutott, és ezután nincs szabad memória. Azaz a szemétgyűjtőt mindenképpen meghívja. Emiatt sem érdemes kezelni catch ágban az OutOfMemoryError-t. És azért sem, mert ilyenkor már arra sem lesz memória, hogy kezeljük.&lt;/p&gt;

&lt;p&gt;A memóriakezelésben találunk még egyéb finomságokat, amiket érdemes megjegyezni. Egyrészt úgy kéne kiválogatni a young generation-ből azokat az objektumokat (mark), melyek használtak, hogy ne kelljen az egész old generation-t átvizsgálni, hogy nincs-e visszafele hivatkozás. Ehhez a garbage collector egy card table-t tart nyilván. Az old generation-t 512-es darabokra bontja (chunks), és mindegyikhez egy flag-et társít. Amennyiben az old gen-ben egy objektum referálni kezd egy young gen-ben lévő objektumra, a beállító művelet a hozzá tartozó flag-et is (egy un. write barrier-en keresztül) átbillenti. A végén csak a billentett flag-gel rendelkező old gen-ben lévő objektumokkal kell törődni.&lt;/p&gt;

&lt;p&gt;Másik érdekes technika a gyors memóriafoglaláshoz szükséges. A JVM egy bump-the-pointer mechanizmust alkalmaz, ami egy mutatót használ annak a memóriahelynek a megjelölésére, ahova az új objektumot el lehet tenni. Elteszi az objektumot, majd feljebb emeli a pointer-t. Azonban többszálas környezetben ez macerás lehet, hiszen szinkronizálni kéne erre a mutatóra, és ott szűk keresztmetszet lehet. Ezért a JVM un. Thread-Local Allocation Buffer-eket (TLAB-ok) tart fenn szálanként. Ezek gyakorlatilag szálanként különböző memóriaterületek, így nincs szükség lock-ra.&lt;/p&gt;

&lt;p&gt;Ahhoz, hogy megértsük, mikor melyik szemétgyűjtő fut, valamint hogyan lehet bekapcsolni őket, beszélni kell a parancssori kapcsolókról, valamint az ergonomics-ról.&lt;/p&gt;

&lt;p&gt;A parancssori kapcsolóknak három fajtája van. A standard, non-standard (-X kapcsolóval kezdődnek) és a developer (-XX: kapcsolóval kezdődnek). A szabványos kapcsolókat a Java Virtual Machine Specification definiálja. Az utóbbi két kapcsoló nem szabványos, JVM-enként mások lehetnek. Minden további nélkül változhat a működésük különböző JDK verziók között, tehát mindig érdemes figyelni a release notes-okat. A developer kapcsolók felépítése a következő. Minden paraméternek van egy típusa, általában boolean vagy int. Amennyiben boolean, a paraméter neve előtt + vagy - karakterrel lehet be vagy kikapcsolni (pl. -XX:+UseSerialGC a serial collector bekapcsolására). Amennyiben int, a paraméter neve után kell írni, egyenlőségjellel elválasztva, és gyakran egy mértékegységet is írhatunk utána (pl. -XX:NewSize=64m, amivel az új generáció kezdeti és minimális méretét állítjuk 64 megára). A paraméterek rendelkeznek valamilyen default értékkel. A developer paraméterek egy listája a &lt;a href="http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html"&gt;Java HotSpot VM Options&lt;/a&gt; címmel található az Oracle oldalán.&lt;/p&gt;

&lt;p&gt;A JDK az 1.5 verziótól kezdve felismeri az alatta lévő architektúrát, és két osztály egyikébe sorolja, vagy kliens osztályú, vagy szerver osztályú gépek csoportjába. A JDK 6-ban a detektálásról JDK dokumentációjának &lt;a href="http://docs.oracle.com/javase/6/docs/technotes/guides/vm/server-class.html"&gt;Server-Class Machine Detection&lt;/a&gt; fejezete ír. Alapvetően a legalább 2 CPU-val (maggal) és legalább 2 GB memóriával rendelkező nem Windows-os gépeket soroljuk ide. Az osztályt explicit is meg lehet adni a -client vagy -server parancssori kapcsolók megadásával. Az ergonomics másik része, hogy a egyrészt az osztály alapján választ szemétgyűjtő mechanizmust, valamint a megadott paraméterek alapján automatikusan finomhangolja a heap memóriaterületek méretét, nem nekünk kell megadni azokat. Erről a JDK dokumentációjának &lt;a href="http://docs.oracle.com/javase/6/docs/technotes/guides/vm/gc-ergonomics.html"&gt;Garbage Collector Ergonomics&lt;/a&gt; fejezete ír. Ha egyéb kapcsolót nem adunk meg, kliens osztályú gép esetén client JVM fut, serial collector (lsd. később), 4 mega kezdeti heap méret, és 64 mega maximum heap méret. Szerver esetén a kezdeti heap méret a fizikai memória hatvannegyede, minimum 32 mega, maximum 1 giga. Maximum heap méret a fizikai memória egynegyede, maximum 1 giga.&lt;/p&gt;

&lt;p&gt;És akkor következzenek a szemétgyűjtő mechanizmusok, a következő sorrendben:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serial Collector&lt;/li&gt;
&lt;li&gt;Parallel/Throughput Collector&lt;/li&gt;
&lt;li&gt;Parallel Compacting Collector&lt;/li&gt;
&lt;li&gt;Concurrent Mark-Sweep (CMS) Collector&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Serial Collector&lt;/h4&gt;

&lt;p&gt;A serial collector esetén a young és az old terület szemétgyűjtése is egy szálon történik, un. stop-the-world módon. Ez azt jelenti, hogy a JVM az alkalmazást teljesen leállítja, amíg a szemétgyűjtés folyik. Ez valójában úgy történik, hogy az összes Java szálat leállítja (un. safepoint), hogy ne változzon a heap, sem a szálhoz tartozó stack. Érezhető, hogy ez a megállás gyakorlatilag a szemétgyűjtéses megközelítés legnagyobb hátránya. Ez normális működés esetén észrevehetetlen, de nagy terhelés, intenzív memóriahasználat, sok párhuzamos felhasználó esetén már nagyban ronthatja az alkalmazásunk teljesítményét. A young generation szemétgyűjtése a fentebb leírt módon történik, azaz a túlélő objektumok a survivor-re, majd az old generation területre kerülnek. Az old generation és permanent generation szemétgyűjtése un. mark-sweep-compact algoritmussal történik. Mark fázisban a szemétgyűjtő megjelöli az élő objektumokat, a sweep fázisban kitakarítja a nem élő objektumokat, és a compact fázisban az élő objektumokat a megfelelő memóriaterület elejére tolja. Így a memóriaterületen nem lesznek lyukak, az elején lesznek az élő objektumok, a végén az üres hely. Így használható a fentebb említett bump-the-pointer mechanizmus. Ezt használva nem jelentkezik a memória töredezettsége, melyet később részletezek.&lt;/p&gt;

&lt;p&gt;A serial collector általában remek választás kliens oldali alkalmazások esetén, akár egy 64 megás heap esetén is viszonylag ritka és rövid (&lt; 0,5 mp) leállásokkal jár. Ez felhasználói felületekkel rendelkező, egy felhasználót kiszolgáló alkalmazások esetén megfelelő. Akkor is jól jöhet, ha több JVM osztozik egy processzoron, hiszen ekkor úgysem tud párhuzamosan futni a szemétgyűjtés a processzorok kihasználtsága miatt, ugyanis a többi algoritmus valahogy párhuzamosítani próbál. A serial collector az alapértelmezett a nem szerver-osztályú gépek esetén. Egyéb esetben a &lt;code&gt;-XX:+UseSerialGC&lt;/code&gt; parancssori kapcsolóval lehet bekapcsolni.&lt;/p&gt;

&lt;h4&gt;Parallel/Throughput Collector&lt;/h4&gt;

&lt;p&gt;A parallel/throughput collector annyival másabb, mint a serial collector, hogy a young generation szemétgyűjtése nem egy szálon, hanem több szálon fut. De ugyanúgy megállítja a többi szálat, és másolja az objektumokat a memóriaterületek között. Az old generation szemétgyűjtése megegyezik a serial collector szemétgyűjtésével, ami a mark-sweep-compact algoritmus. Ennek a szemétgyűjtőnek használatát több processzor(mag) kihasználására tervezték, és ott érdemes alkalmazni, ahol nem baj, ha az old generation meg is akasztja az alkalmazás futását. A young generation szemétgyűjtése tehát rövidebb megállást eredményez, de több processzoridőt és memóriát igényel a szálak karbantartása miatt. Hasznos lehet pl. nagytömegű batch feldolgozások, számlázás, tudományos számítások, stb. Automatikusan kiválasztásra kerül szerver osztályú gépeken, egyéb esetben a &lt;code&gt;-XX:+UseParallelGC&lt;/code&gt; parancssori kapcsolóval lehet bekapcsolni.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-tBvK_ai1xjc/Tv0Ru1kfiUI/AAAAAAAAHsk/Ol1AlFrE52A/s1600/serial_parallel.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 224px;" src="http://2.bp.blogspot.com/-tBvK_ai1xjc/Tv0Ru1kfiUI/AAAAAAAAHsk/Ol1AlFrE52A/s320/serial_parallel.png" border="0" alt="Serial és parallel collector összehasonlítása" id="BLOGGER_PHOTO_ID_5691725000417970498" /&gt;&lt;/a&gt;

&lt;h4&gt;Parallel Compacting Collector&lt;/h4&gt;

&lt;p&gt;Ez a szemétgyűjtő algoritmus a J2SE 5.0 update 6-ban került bevezetésre. A young generation szemétgyűjtése megegyezik az előző, parallel/throughput collector működésével. A különbség csak az old generation szemétgyűjtésénél van, konkrétan ez is több szálon képes futni. Ez a szemétgyűjtés három fázisból áll: marking, summary, compaction. A marking fázisban a memória régiókra kerül felosztásra. Az alkalmazásból közvetlenül elérhető objektumokat a szálak szétosztják egymás között, és elkezdenek végigmenni a referenciákon, és megjelölik a használt objektumokat. A második, summary fázis már nem objektumokon, hanem régiókon dolgozik. A szemétgyűjtő működésének eredményeképpen egy olyan állapot jön létre, hogy a memóriaterület elején sűrűbb rész van, a végén ritkább. A sűrűbb azt jelenti, hogy onnan viszonylag ritkán kell objektumokat kidobálni. A szemétgyűjtő az elejétől a végéig végigmegy a régiókon, és kitalálja, hogy melyik régiótól kezdve éri meg kidobálni az objektumokat. Ezen pont előtt lévő terület a dense prefix, ezt a szemétgyűjtő nem bántja. A compaction fázisban történik a lyukak feltöltése a ritkább területen. Tehát ennek a szemétgyűjtésnek is a végén a memóriaterület eleje összefüggő, teli, míg a vége üres.&lt;/p&gt;

&lt;p&gt;Ez a szemétygyűjtő akkor lehet megfelelő, ha a szemétgyűjtő által okozott állási idő igenis fájdalmas, így ezt kell csökkenteni, párhuzamossággal. A &lt;code&gt;-XX:+UseParallelOldGC&lt;/code&gt; parancssori kapcsolóval lehet bekapcsolni.&lt;/p&gt;

&lt;h4&gt;Concurrent Mark-Sweep (CMS) Collector&lt;/h4&gt;

&lt;p&gt;A CMS collector-t olyan alkalmazások számára fejlesztették ki, ahol igen fontos a válaszidő, pl. webes alkalmazásoknál. Mivel a young generation szemétgyűjtése annak kis méretéből adódóan igen gyors, az ugyanúgy működik, mint a Parallel/Throughput Collector esetében. A változás itt is az old generation szemétgyűjtésében van. A szemétgyűjtés itt négy fázisból áll: initial mark, concurrent marking phase/pre-cleaning, remarking, concurrent sweeping. Az első, initial mark fázisban a szemétgyűjtő megjelöli az alkalmazásból közvetlenül elérhető objektumokat. Ekkor stop the world van, azaz az alkalmazás szálai leállnak. Majd a concurrent marking phase fázisban az alkalmazás futásával egyidőben (és ettől konkurens) bejelöli a tranzitíven elérhető objektumokat. A remark fázisban ismét stop the world, a szemétgyűjtő bejárja az előző fázis közben módosult objektumokat, ezzel véglegesíti az élő objektumok bejelölését. Ez már több szálon történik. A concurrent sweep fázis eltávolítja a szemetet. Látható, hogy egyrészt több munkával jár, másrészt lehetnek olyan nem használt objektumok, amik nem takarodnak ki az első szemétgyűjtéskor (ez az un. floating garbage). Ez az ára a rövidebb válaszidőnek. Látható, hogy a CMS collector un. non-compacting szemétgyűjtő, azaz a memóriaterületen nem egybefüggően lesznek az objektumok, hanem lyukak lesznek közöttük. Ez egyrészt megnehezíti a kezelést, hiszen nem egy pointer-t kell nyilvántartani, hanem egy listában kell nyilvántartani a szabad területeket. Másrészt fregmentálódáshoz is vezet, azaz nem egyszerű betenni sem egy újonnan példányosított objektumot. A többi szemétgyűjtővel ellentétben a CMS collector nem akkor fut le, mikor betelik a memóriaterület, hanem hamarabb, hogy még képes legyen lefutni. Ha ez nem sikerül, akkor mindenképpen a jól ismert mark-sweep-compact algoritmus fut le, mely az előző szemétgyűjtőknél is.&lt;/p&gt;

&lt;p&gt;A CMS collector jól alkalmazható ott, ahol fontos a gyors válaszidő, és több processzor tud a szemétgyűjtő munkájában részt venni, valamint viszonylag sok hosszúéletű objektum van. Ilyenek tipikusan a többprocesszoros gépeken futó webes alkalmazások. A &lt;code&gt;-XX:+UseConcMarkSweepGC&lt;/code&gt; parancssori kapcsolóval lehet bekapcsolni.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-11k03z2nctk/Tv0RpKPz9-I/AAAAAAAAHsY/cIXDUtKZI-4/s1600/serial_cms.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 202px;" src="http://3.bp.blogspot.com/-11k03z2nctk/Tv0RpKPz9-I/AAAAAAAAHsY/cIXDUtKZI-4/s320/serial_cms.png" border="0" alt="Serial és CMS collector összehasonlítása" id="BLOGGER_PHOTO_ID_5691724902889158626" /&gt;&lt;/a&gt;

&lt;p&gt;Összefoglalva a következőket lehet megállapítani, a szemétgyűjtőket a következő tulajdonságok alapján lehet vizsgálni:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;A serial szemétgyűjtés jó egy processzoros gépen, de a parallel szemétgyűjtés, amennyiben több processzor tud részt venni, rövidebb ideig tarthat, de több erőforrás szükséges hozzá.&lt;/li&gt;
 &lt;li&gt;A stop the world megközelítés biztosítja, hogy nem módosul a stack/heap, de cserébe leállással jár. A concurrent szemétgyűjtés az alkalmazás mellett fut, így több processzor szükséges, és több erőforrás is szükséges hozzá. Nincs teljesen concurrent szemétgyűjtő, kizárólag olyan, melynek valamely fázisa concurrent.&lt;/li&gt;
 &lt;li&gt;A compacting lassabb ugyan, mert objektumokat kell másolgatni, de egy pointer-rel elintézhető a szabad hely nyilvántartása. Non compacting esetben az adminisztráció is bonyolultabb, valamint töredezettség léphet fel.&lt;/li&gt;
&lt;/ul&gt; 

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-Qgi9Ta1Z2UU/Tv0TcIRlNKI/AAAAAAAAHsw/VKq_a23Nsj4/s1600/tablazat.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 130px;" src="http://1.bp.blogspot.com/-Qgi9Ta1Z2UU/Tv0TcIRlNKI/AAAAAAAAHsw/VKq_a23Nsj4/s400/tablazat.png" border="0" alt="Szemétgyűjtő algoritmusok összehasonlítása" id="BLOGGER_PHOTO_ID_5691724902889158626" /&gt;&lt;/a&gt;

&lt;p&gt;&lt;a href="http://blogs.oracle.com/jonthecollector/entry/our_collectors"&gt;Our Collectors&lt;/a&gt; címmel egy elég jó cikket és grafikát találunk a young és old generation szemétgyűjtő algoritmusainak, valamint parancssori paramétereinek kapcsolatáról.&lt;/p&gt;

&lt;p&gt;A Java 6 update 20-ban megjelent, és a 7-es sorozatban is megtalálható a Garbage First Collector, vagy röviden G1. Ez teljesen más megközelítést használ, viszont kevesebb tapasztalat van vele, ezért erről sem írni nem tudok, és mindenkit óvatosságra intenék ezzel kapcsolatban.&lt;/p&gt;

&lt;p&gt;Mivel nézzük, hogy hogyan működik a szemétgyűjtő? Az első, legegyszerűbb eszköz a JVM &lt;code&gt;-verbose:gc&lt;/code&gt; vagy &lt;code&gt;-XX:PrintGCDetails&lt;/code&gt; paraméterrel való futtatása. Nézzünk szét a JVM developer paraméterei között, rengeteg statisztikát ki lehet nyerni. A másik megoldás, ha a fentebb említett VisualVM Visual GC plugin-ját használjuk.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-GjlUS3xFW4s/Tv2aJr_SwWI/AAAAAAAAHs8/8TuO1vZaPcc/s1600/gc_details.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 245px;" src="http://4.bp.blogspot.com/-GjlUS3xFW4s/Tv2aJr_SwWI/AAAAAAAAHs8/8TuO1vZaPcc/s320/gc_details.png" border="0" alt="A JVM -XX:PrintGCDetails paraméterrel indítva" id="BLOGGER_PHOTO_ID_5691874995283870050" /&gt;&lt;/a&gt;

&lt;p&gt;Nem szorosan ide tartozik, de nagyon hasznos lehet a JVM un. Fatal Error Handling tulajdonsága. Amennyiben olyan hiba keletkezik, melyet nem tudunk kódból lekezelni, pl. OutOfMemoryError, megadhatunk a JVM-nek olyan kapcsolókat, melyeket használva mégis előrébb vagyunk. Pl. &lt;code&gt;-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=&amp;lt;path&gt;&lt;/code&gt; paraméterekkel megmondhatjuk, hogy a JVM készítsen egy heap dump-ot. Amit akár VisualVM-be is betölthetünk, és grafikusan elemezhetünk. A &lt;code&gt;-XX:OnOutOfMemoryError=&amp;lt;parancs(ok)&gt;&lt;/code&gt; paraméterekkel operációsrendszerbeli parancsokat adhatunk meg, melyeket lefuttat a JVM hiba esetén (bármilyen script-et hívhatunk itt). A &lt;code&gt;-XX:+ShowMessageBoxOnError&lt;/code&gt; parancssori kapcsoló hatására feldob egy dialógusablakot. Ez azért jó, mert ekkor még nem áll le a JVM, így akár egy profiler-rel is neki tudunk menni.&lt;/p&gt;

&lt;p&gt;Ez alapján el lehet kezdeni a GC tuning-olását, mely egy külön tudomány. Jó kiindulási alap lehet az Oracle &lt;a href="http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html"&gt;Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning&lt;/a&gt; cikke.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-8365011667058151286?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/8365011667058151286/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/12/java-memoriakezeles-szemetgyujto.html#comment-form" title="14 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/8365011667058151286?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/8365011667058151286?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/12/java-memoriakezeles-szemetgyujto.html" title="Java memóriakezelés, szemétgyűjtő algoritmusok" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-Hgkvfe-YRjA/Tv0QOVMrD1I/AAAAAAAAHrc/M0vJrloT35I/s72-c/visualgc_gifanim.gif" height="72" width="72" /><thr:total>14</thr:total></entry><entry gd:etag="W/&quot;CkQAQnY_eCp7ImA9WhRWEUs.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-43432132572840305</id><published>2011-12-13T00:45:00.005+01:00</published><updated>2011-12-29T13:05:43.840+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-29T13:05:43.840+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="instrumentation" /><category scheme="http://www.blogger.com/atom/ns#" term="Java SE" /><category scheme="http://www.blogger.com/atom/ns#" term="JMX" /><title>Instrumentation Javassist-tal</title><content type="html">&lt;p&gt;Technológiák: Javassist 3.15&lt;/p&gt;

&lt;p&gt;Belefutottam egy olyan &lt;a href="http://stackoverflow.com/questions/7096121/profile-entire-java-program-execution-in-visualvm"&gt;problémába&lt;/a&gt;, hogy egy alkalmazást szeretnék monitorozni VisualVM-mel (régebben már írtam &lt;a href="http://jtechlog.blogspot.com/2011/04/visualvm-glassfish-monitorozas.html"&gt;róla&lt;/a&gt;), azonban az alkalmazás számomra szignifikáns része már lefut, mielőtt hozzá tudnák csatlakozni a virtuális géphez. A VisualVM egy monitoring és menedzsment eszköz, nagyon mélyen lehet a virtuális gép működését megfigyelni, és a JDK része. A &lt;code&gt;-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y&lt;/code&gt; parancssori kapcsoló használata nem segít, ugyanis ebben az esetben a megállt alkalmazást csak olyan profiler képes továbblökni, mely beszéli a Java Debug Wire Protocol (JDWP) protokollt, a VisualVM viszont nem ilyen. (Míg a Eclipse TPTP vagy a Netbeans Profiler igen. Más kérdés ugyan, hogy a VisualVM is tartalmaz profiler-t, ráadásul ugyanaz, ami a NetBeans-ben is van, ez utóbbi csak annyival több, hogy a forráskódhoz tud pozícionálni.)&lt;/p&gt;

&lt;p&gt;A problémára több megoldási javaslatot is lehet kapni a neten, pl. más profiler (előbb említetteken kívül még sok van, pl. a JDK részeként szállított parancssori HPROF, vagy a kereskedelmi YourKit vagy JProfiler), debug módban indítás IDE-ből, valamint az alkalmazásban várakozás elhelyezése (sleep, Console input).&lt;/p&gt;

&lt;p&gt;Gondoltam, ez egy megfelelő alkalom az instrumentation és a Javassist kipróbálására. Így készítettem egy egyszerű példaprogramot, mely elérhető a &lt;a href="https://github.com/vicziani/jtechlog-wait4signal"&gt;GitHub&lt;/a&gt;-on. A program egy Java agent, melynek segítségével egy Java alkalmazás adott szálának futása a megadott metódusnál felfüggeszthető, és vagy konzolon bevitt, vagy JMX-en feladott jelre vár. Mindezt az alkalmazás forráskódjának módosítása nélkül.&lt;/p&gt;

&lt;p&gt;Maven-nel build-elhető, és a letöltést követően a 'mvn package assembly:single' parancs kiadásával a target könyvtárban létrejön egy jtechlog-wait4signal-1.0-SNAPSHOT-bin.zip és egy
jtechlog-wait4signal-1.0-SNAPSHOT-tar.gz állomány. Valamelyik lib könyvtárában lévő két jar fájlt kell felhasználni.&lt;/p&gt;

&lt;p&gt;A következő parancs kiadásával lehet az agent-et aktiválni:&lt;/p&gt;

&lt;pre&gt;java -javaagent:jtechlog-wait4signal-1.0-SNAPSHOT.jar=entryPoint=java2d.Java2Demo.main -jar Java2Demo.jar&lt;/pre&gt;

&lt;p&gt;Ekkor a konzolon vár egy Enter lenyomásáig, vagy 5 másodperc múlva mindenképp lefuttatja az alkalmazást.&lt;/p&gt;

&lt;p&gt;A következő parancs kiadásával lehet JMX-en értesítést aktiválni:&lt;/p&gt;

&lt;pre&gt;java -javaagent:jtechlog-wait4signal-1.0-SNAPSHOT.jar=entryPoint=java2d.Java2Demo.main,mode=JMX,timeout=30 -jar Java2Demo.jar&lt;/pre&gt;

&lt;p&gt;Ekkor a &lt;code&gt;jtechlog/SignalMBean signal()&lt;/code&gt; operációjával lehet a futtatást továbbengedni, vagy 30
másodperc múltán timeout.&lt;/p&gt;

&lt;p&gt;Régebben &lt;a href="http://jtechlog.blogspot.com/2009/05/hibernate-eclipselink-atallas.html"&gt;már írtam arról&lt;/a&gt;, hogy az instrumentációt, azaz a bytecode módosítását futásidőben, osztálybetöltéskor a &lt;a href="http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html"&gt;java.lang.instrument&lt;/a&gt; csomag felhasználásával lehet megvalósítani. Az agent fő osztálya a &lt;code&gt;jtechlog.wait4signal.Wait4SignalMain&lt;/code&gt; osztály, melynek &lt;code&gt;premain&lt;/code&gt; metódusa fut le a saját alkalmazásunk main metódusa előtt. Ahhoz, hogy a -javaagent megadásakor ehhez az osztályhoz kerüljön a vezérlés, a anifest.mf fájlban a Agent-Class bejegyzésnek rá kell hivatkoznia.&lt;/p&gt;

&lt;pre class="brush: java"&gt;public static void premain(String agentArgs, Instrumentation inst) {
 System.out.println("Initializing Wait4Signal Java agent.");
 Wait4SignalMain wait4SignalMain = new Wait4SignalMain();
 wait4SignalMain.doInstrumentation(agentArgs, inst);
}
&lt;/pre&gt;

&lt;p&gt;A &lt;code&gt;doInstrumentation&lt;/code&gt; metódus feldolgozza a parancssori paramétereket (a JAR neve és egy egyenlőségjel után megadott String), ezek konvenció szerint név és érték párok, köztük egyenlőségjel, vesszővel elválasztva. Lehetséges paraméterek: entryPoint (kötelező megadni, osztály és metódus neve, mely előtt meg kell állítani a program futását), mode (ha nincs megadva CONSOLE mód, azaz konzolon vár Enter billenytű megnyomását, vagy JMX), és timeout (másodpercben, alapértelmezett értéke 5). Majd a következő utasítás megadásával egy új &lt;code&gt;ClassFileTransformer&lt;/code&gt; implementációt regisztrál:&lt;/p&gt;

&lt;pre class="brush: java"&gt;inst.addTransformer(new WaitTransformer(entryPoint, waiting));
&lt;/pre&gt;

&lt;p&gt;Egy ötlet volt az is, hogy a &lt;code&gt;premain&lt;/code&gt; metódusban állítom meg a program futását, azonban ez nem volt megfelelő, hiszen a JVM ilyenkor olyannyira nem inicializálta magát, hogy a VisualVM sem tudott hozzá kapcsolódni életciklusának ezen pontján.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;WaitTransformer&lt;/code&gt; a &lt;code&gt;transform&lt;/code&gt; metódust definiálja felül, és vizsgálja, hogy az osztály neve megegyezik-e a parancssori kapcsolóként megadottal.&lt;/p&gt;

&lt;pre class="brush: java"&gt;public byte[] transform(ClassLoader loader, String className, 
 Class&amp;lt;?&amp;gt; classBeingRedefined, ProtectionDomain protectionDomain, 
 byte[] classfileBuffer) throws IllegalClassFormatException
&lt;/pre&gt;

&lt;p&gt;A transform metódus számunkra érdekes paraméterei az osztály osztálybetöltője (null, ha bootstrap osztálybetöltő), az osztály neve (vigyázat, pontok helyett perjelekkel), valamint az osztály bytecode-jának byte tömbjét. Ezt szabadon módosíthatjuk, és ezt kell visszaadni a metódus visszatérési értékeként. Vigyázat, az ebből a metódusból kilépő kivételeket a JVM elnyeli.&lt;/p&gt;

&lt;p&gt;Persze nem kell a byte tömböt közvetlenül módosítani, itt jöhet segítségünkre a &lt;a href="http://www.javassist.org/"&gt;Javassist&lt;/a&gt; (Java Programming Assistant), mely egy Java bytecode futásidejű manipulálását megkönnyítő programkönyvtár. Két szintű API-t ad a kezünkbe. A forráskód szintű API segítségével Java utasításokat, mint String-eket szúrhatunk be, ezeket a Javassist on-the-fly fogja átfordítani bytecode-dá. Ekkor persze nem szükséges ismernünk a class fájl szerkezetét. Vagy manipulálhatjuk alacsonyabb szinten is, közvetlen a bytecode-ot. Ezen lehetőségek rendkívül alkalmassá teszik a Javassist-ot AOP keretrendszerek fejlesztésére. Remek &lt;a href="http://www.csg.is.titech.ac.jp/%7Echiba/javassist/tutorial/tutorial.html"&gt;tutorial&lt;/a&gt; is van hozzá.&lt;/p&gt;

&lt;p&gt;A következő részben a Javassist érdekesebb kódrészleteit emelem ki, melyek a bytecode-ot módosítják.&lt;/p&gt;

&lt;pre class="brush: java"&gt;
ClassPool pool = ClassPool.getDefault();
CtClass cl = pool.makeClass(new java.io.ByteArrayInputStream(classfileBuffer));

if (cl.isInterface() == false) {
 CtBehavior[] methods = cl.getDeclaredBehaviors();

 for (int i = 0; i &lt; methods.length; i++) {
  if (entryPoint.endsWith(methods[i].getName())) {
   ctBehavior.insertBefore(waiting.insertBeforeMethod());
  }
 }
 classfileBuffer = cl.toBytecode();
}
cl.detach();
&lt;/pre&gt;

&lt;p&gt;A fenti kódrészlet először lekér egy ClassPool-t, ez a Javassist-ban lévő osztályok tárolására szolgáló konténer. Ebbe definiál egy CtClass (compile-time class) példányt, mely az osztály absztrakt reprezentációja. Ennek forrása az instrumentálás során átadott byte tömb. Amennyiben ez egy interfész, lekéri ennek metódusait a &lt;code&gt;getDeclaredBehaviors()&lt;/code&gt; metódushívással. Ezeken végigiterál, és ha a metódus neve megfelelő, akkor beszúr kódrészletet az &lt;code&gt;insertBefore&lt;/code&gt; metódushívással. Ennek érdekessége, hogy egy String-et vár, tehát bármilyen Java forráskódot be lehet illeszteni, mintha csak a .java forrásfájlba tettük volna ezt.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;waiting.insertBeforeMethod()&lt;/code&gt; a mode parancssori kapcsoló függvényében más és más String-et ad vissza. Pl. CONSOLE mode esetén példányosít egy &lt;code&gt;ConsoleWaiting&lt;/code&gt; objektumot, majd beállítja a timeout property-jét, majd meghívja a &lt;code&gt;wait4signal()&lt;/code&gt; metódusát.&lt;/p&gt;

&lt;pre class="brush: java"&gt;public String insertBeforeMethod() {
 StringBuilder sb = new StringBuilder();
 sb.append("jtechlog.wait4signal.Waiting waiting = new jtechlog.wait4signal.ConsoleWaiting();");
 sb.append(String.format("waiting.setTimeout(%s);", timeout));
 sb.append("waiting.wait4signal();");
 return sb.toString();
}

&lt;/pre&gt;

&lt;p&gt;Érdekessége, hogy a wait4signal() metódus a &lt;code&gt;ConsoleInput&lt;/code&gt; és &lt;code&gt;ConsoleInputReadTask&lt;/code&gt; osztályokat használja a konzolról való beolvasásra, és a Java 5-ben megjelent ExecutorService-t használja a külön szálon való bekérésre. Erre azért van szükség, hogy itt is működjön a timeout (&lt;a href="http://www.javaspecialists.eu/archive/Issue153.html"&gt;The Java Specialists' Newsletter&lt;/a&gt; cikke alapján).&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;JmxWaiting&lt;/code&gt; osztály ezzel szemben egy BlockingQueue-t használ, és abba vár egy üzenetet. A &lt;code&gt;BlockingQueue.poll(int, TimeUnit)&lt;/code&gt; metódusával vár egy üzenetre, timeout esetén null a visszatérési értéke. A BlockingQueue a &lt;code&gt;SignalMBean&lt;/code&gt; MBean-nek is átadásra kerül. Amennyiben a felhasználó meghívja a &lt;code&gt;signal()&lt;/code&gt; operációját, egy üzenetet tesz a Queue-ba. A &lt;code&gt;JmxWaiting&lt;/code&gt; ekkor beszünteti a várakozást, és fut tovább. A JMX-ről egy &lt;a href="http://jtechlog.blogspot.com/2009/09/java-monitorozas-es-menedzsment.html"&gt;korábbi postban&lt;/a&gt; tettem említést.&lt;/p&gt;

&lt;p&gt;Az agent-nek szüksége van tehát a Javassist JAR fájlra is, ehhez a manifest.mf fájlba fel kell venni a Boot-Class-Path bejegyzésbe a JAR fájl nevét. Abszolút (perjel) nélkül adtam meg, így a jtechlog-wait4signal-1.0-SNAPSHOT.jar állománnyal egy könyvtárban fogja keresni (függetlenül a JVM indítási könyvtárától).&lt;/p&gt;

&lt;p&gt;Látható, hogy a JVM induláskor, az osztálybetöltés során a Java class fájlok manipulálása korántsem akkora varázslat, mint első látásra hinnénk. Több nyílt forráskódú alternatíva is létezik bytecode manipulálásra, többek között a &lt;a href="http://cglib.sourceforge.net/"&gt;cglib&lt;/a&gt;, &lt;a href="http://commons.apache.org/bcel/index.html"&gt;Apache Commons BCEL&lt;/a&gt;, &lt;a href="http://asm.ow2.org/"&gt;ASM&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-43432132572840305?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/43432132572840305/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/12/instrumentation-javassist-tal.html#comment-form" title="2 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/43432132572840305?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/43432132572840305?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/12/instrumentation-javassist-tal.html" title="Instrumentation Javassist-tal" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;Ak8NRn4_cCp7ImA9WhRRFE4.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-912143685418710554</id><published>2011-11-28T01:06:00.001+01:00</published><updated>2011-11-28T01:08:17.048+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-28T01:08:17.048+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><category scheme="http://www.blogger.com/atom/ns#" term="DocBook" /><title>Szabad navigáció okozta problémák webes környezetben</title><content type="html">&lt;p&gt;Technológiák: Servlet 3.0/JSP 2.2, DocBook 4.5, Docbkx Tools, Docbkx Maven Plugin, Maven 3&lt;/p&gt;

&lt;p&gt;Legrégebb óta írt cikkem kerül most publikálásra, melynek címe "Szabad navigáció okozta problémák webes környezetben".&lt;/p&gt;

&lt;p&gt;Ez a cikk azon problémával foglalkozik, mely a legtöbb webes alkalmazás fejlesztésekor felmerül, ugyanis nem biztosítható az, hogy a felhasználó olyan sorrendben nézze meg az oldalakat, ahogy azt az alkalmazás fejlesztője eltervezi. Használhatja a Vissza és Tovább műveleteket is navigációra, valamint újratöltheti az oldalt a Frissítés művelettel. Ezen műveletek elérhetők a böngésző szokásos gombjai között, billentyűkombinációval, de jobb kattintásra felugró menüben is. Sokan megszokásból, esetleg türelmetlenség (, a lassú válaszidő) miatt duplán kattintanak egy adott hivatkozásra. A felhasználó kézzel is beírhat egy url-t, vagy a Kedvencek közül is választhat egyet, ami szintén hibás működéshez vezethet, ha erre nem készülünk fel, és bízunk, hogy csak a felületi elemeket (űrlap elemek – gomb, legördülő menü, stb., hivatkozások) fogja használni. A böngészők és tűzfalak gyorsítótár beállításai is megzavarhatják az előre tervezett munkafolyamatot. A probléma a webes technológia, a http(s) protokoll, valamint a böngészők adta lehetőségek miatt jelentkezik.&lt;/p&gt;

&lt;p&gt;A cikk egy jtechlog-repost példa projektre hivatkozik, mely &lt;a href="https://github.com/vicziani/jtechlog-repost"&gt;letölthető a GitHub-ról&lt;/a&gt;. Egyszerű webes alkalmazás, servlet 
controller és JSP view réteggel. Maven-nel build-elhető, és a letöltést követően a 'mvn jetty:run' paranccsal futtatható.&lt;/p&gt;

&lt;p&gt;Példaprogrammal, szekvencia diagramokkal és forráskódokkal szemlélteti a webes alkalmazásokban gyakran felmerülő problémákat, melyek a szabad navigációból erednek. Ha te is találkoztál, vagy írtál olyan alkalmazást, ahol problémát okozott, ha a felhasználó véletlenszerűen használta a Vissza/Előre gombokat, ha a többszöri kattintás felesleges terhelést okozott a szerveren, ha Frissít gomb megnyomásakor a böngésző hibaüzenetet dobott fel, akkor a cikk neked való. Nem csak a problémákat, de a rá adott szabványos megoldásokat is ismerteti, mint a Redirect After Post, vagy a Synchronizer Token. Olyan ide kapcsolódó témákat is érint, mint a hosszú, aszinkron folyamatok kezelése, vagy a problémák megoldása AJAX környezetben.&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;a href="http://delfin.unideb.hu/~vicziani/pdf/repost.pdf"&gt;Szabad navigáció okozta problémák webes környezetben cikk letöltése&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A dokumentáció érdekessége, hogy &lt;a href="http://www.docbook.org/"&gt;DocBook-ban&lt;/a&gt; íródott, mely egy XML formátum könyvek, cikkek publikálására. Ugyanis meguntam a Word ezirányú képességeit, hogy hosszabb dokumentációnál elveszti a kontrollt, bizonyos dolgokat sokszor körülményes vele megcsinálni. Mivel az XML egy szöveges állomány, ilyen nem fordulhat elő a megfelelő tag-ek ismeretében. A DocBook XML állományból a Maven &lt;a href="http://docbkx-tools.sourceforge.net/"&gt;Docbkx Tools&lt;/a&gt; fordít PDF állományt. A háttérben először egy XSL-FO állomány generálódik le, majd azt fordítja az &lt;a href="http://xmlgraphics.apache.org/fop/"&gt;Apache FOP&lt;/a&gt; PDF-fé.&lt;/p&gt;

&lt;p&gt;A DocBook forrást tartalmazó, és a PDF-fé build-elést elvégző Maven projekt szintén &lt;a href="https://github.com/vicziani/jtechlog-repost-doc"&gt;elérhető a GitHub-on&lt;/a&gt; jtechlog-repost-doc néven.&lt;/p&gt;

&lt;p&gt;Ezzel kapcsolatban csak egy probléma merült fel, méghozzá az ékezetes karakterek problémája. Egy PDF megjelenítő ugyanis alapban 14 betűtípust ismer (&lt;a href="http://en.wikipedia.org/wiki/Portable_Document_Format"&gt;"base fourteen fonts"&lt;/a&gt;), és ebben nincsenek ékezetes karakterek. Ezért, ha ilyeneket akarunk, akkor azokat be kell építenünk (embedded font) a PDF állományba. Az Apache FOP ezt azonban bizonyos verziónál csak úgy tudja megtenni, ha a beépítendő betűtípus mellett egy metrics állomány is szerepel, mely egy XML és leírja a betűtípus tulajdonságait. Szerencsére a betűtípusból ilyent generálni is lehet a következő paranccsal: &lt;code&gt;java org.apache.fop.fonts.apps.TTFReader -fn sanf-serif micross.ttf micross-fcm.xml&lt;/code&gt;, persze a megfelelő FOP CLASSPATH beállításával. Szerencsére ilyent nem kellett Maven-ből hívni, ugyanis a Docbkx Tools tartalmaz eszközt erre is, csak a következő részeket kellett a pom.xml-be beilleszteni (fontos a false ansi property).&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;com.agilejava.docbkx&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;docbkx-fop-support&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;2.0.13&amp;lt;/version&amp;gt;
 &amp;lt;executions&amp;gt;
  &amp;lt;execution&amp;gt;
   &amp;lt;phase&amp;gt;generate-resources&amp;lt;/phase&amp;gt;
   &amp;lt;goals&amp;gt;
    &amp;lt;goal&amp;gt;generate&amp;lt;/goal&amp;gt;
   &amp;lt;/goals&amp;gt;
   &amp;lt;configuration&amp;gt;
    &amp;lt;ansi&amp;gt;false&amp;lt;/ansi&amp;gt;
   &amp;lt;/configuration&amp;gt;
  &amp;lt;/execution&amp;gt;
 &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;

&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;com.agilejava.docbkx&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;docbkx-maven-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;2.0.13&amp;lt;/version&amp;gt;
 
 &amp;lt;!-- ... --&amp;gt;
 
 &amp;lt;configuration&amp;gt;
  &amp;lt;bodyFontFamily&amp;gt;TimesNewRoman&amp;lt;/bodyFontFamily&amp;gt;
  &amp;lt;monospaceFontFamily&amp;gt;Courier&amp;lt;/monospaceFontFamily&amp;gt;
  &amp;lt;titleFontFamily&amp;gt;ArialBold&amp;lt;/titleFontFamily&amp;gt;
  &amp;lt;fonts&amp;gt;
   &amp;lt;font&amp;gt;
    &amp;lt;name&amp;gt;Arial&amp;lt;/name&amp;gt;
    &amp;lt;style&amp;gt;normal&amp;lt;/style&amp;gt;
    &amp;lt;weight&amp;gt;normal&amp;lt;/weight&amp;gt;
    &amp;lt;embedFile&amp;gt;${basedir}/src/fonts/Arial.ttf&amp;lt;/embedFile&amp;gt;
    &amp;lt;metricsFile&amp;gt;${basedir}/target/fonts/Arial-metrics.xml&amp;lt;/metricsFile&amp;gt;
   &amp;lt;/font&amp;gt;
   &amp;lt;!-- ... --&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-912143685418710554?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/912143685418710554/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/11/szabad-navigacio-okozta-problemak-webes.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/912143685418710554?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/912143685418710554?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/11/szabad-navigacio-okozta-problemak-webes.html" title="Szabad navigáció okozta problémák webes környezetben" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0UARHc7cCp7ImA9WhRSFkg.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-6776798504599496909</id><published>2011-11-19T00:05:00.005+01:00</published><updated>2011-11-19T00:34:05.908+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-19T00:34:05.908+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="git" /><title>GitHub</title><content type="html">&lt;p&gt;Mivel ki kellett próbálnom valamit a Spring Security-val, frissítettem az erről szóló &lt;a href="http://jtechlog.blogspot.com/2010/01/spring-security.html"&gt;postot&lt;/a&gt;. Ennek keretében csatlakoztam a &lt;a href="https://github.com/vicziani"&gt;GitHub-hoz&lt;/a&gt;, így ezentúl ott közlöm a postokhoz tartozó példa alkalmazásokat, forráskódokat, érdemes figyelni. Az említett posthoz is megtalálható az első &lt;a href="https://github.com/vicziani/jtechlog-spring-security"&gt;példaprogram&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A példaprogramokban angol megnevezéseket használok, de a megjegyzések, dokumentáció, valamint a felületen megjelenő szövegek (pl. jsp-ben) magyarok lesznek.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-6776798504599496909?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/6776798504599496909/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/11/github.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/6776798504599496909?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/6776798504599496909?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/11/github.html" title="GitHub" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEEER38yeSp7ImA9WhRSE0Q.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-9075776410959180550</id><published>2011-09-27T01:15:00.007+02:00</published><updated>2011-11-15T22:30:06.191+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-15T22:30:06.191+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><title>Maven legjobb gyakorlatok</title><content type="html">&lt;p&gt;Technológiák: Maven 3.0.3&lt;/p&gt;

&lt;p&gt;Maven-nel foglalkozó sorozatom részét azzal zárnám, hogy milyen legjobb gyakorlatokat érdemes betartani. Lehet, hogy bizonyos dolgokat ismételni fogok a &lt;a href="http://jtechlog.blogspot.com/2010/04/maven-kezdolepesek.html"&gt;Maven kezdőlépések&lt;/a&gt; post-omból, de álljanak itt összegyűjtve. Lehet, hogy bizonyos szabályok túl szigorúak, azért van lehetőség egy-két helyen lazábbra engedni.&lt;/p&gt;

&lt;h4&gt;Projekt granularitás&lt;/h4&gt;

&lt;p&gt;Talán a legnehezebb témakör, azaz mennyi projektet hozzunk létre egy bonyolultabb rendszer esetén, és ezek milyen függőségekben legyenek egymással. Az egy projekt csak kis alkalmazásoknál, 3rd party library-knél szokott elegendő lenni, kicsit is bonyolultabb alkalmazások esetén szükség van több projektre. Egy projekt esetén a fejlesztés nehézkesebb, hiszen nem tudjuk kisebb részekben kezelni, mindig mindent le kell fordítani, nagy csomagot előállítani, stb. Maven egy kitűnő támpontot ad, ugyanis az alapfilozófiája az, hogy amennyi projekt, annyi artifact, tehát annyi jar, war, ear, zip, stb.&lt;/p&gt;

&lt;p&gt;Másik kérdés, hogy ezek a projektek mennyire mozognak együtt, vagy külön. Együtt történik a release, vagy gyakran előfordul, hogy az alkalmazás csak egy kis részlete kerül mindig javításra, kiadásra? Van-e olyan rész, mely önmagában is megállja a helyét, pl. egy külön grafikai komponens, melyet akár más projektekben is fel lehet használni. Élhetnek-e külön életet, külön verziószámozással?&lt;/p&gt;

&lt;p&gt;Ezt egyedül a gyakorlat tudja megmondani. Láttam olyan rendszert, ami teljesen különálló modulokból állt, és szépen, külön volt fejleszthető. Egy másik projekt esetében bármit kellett módosítani, mindig hozzá kellett nyúlni 3-4 modulhoz is. Sőt, olyan is megeshet, hogy az elején még minden módosul, míg a hibajavításkor, tovább fejesztéskor már elég csak egy-egy modult bolygatni.&lt;/p&gt;

&lt;p&gt;Néhány támpont azonban. Jó gyakorlat az interfész és implementáció különválasztása (, ez pl. interfészek - web szolgáltatások - esetén nagyon gyakori, és a technológia is megköveteli, mert az interfész osztályoknak mindkét oldalon meg kell lennie). Használjunk szervezet és projekt szintű szülő projekteket. Hasznosak lehetnek a prototípus projektek. Gyakran használt utility osztályokat emeljük ki library-ként. Közös erőforrásokat emeljük ki külön projektbe. Integrációs teszt eseteket emeljük ki külön projektbe. Függőségeket is ki lehet emelni külön projektbe. Ezekről még mindről lesz később szó a post-ban.&lt;/p&gt;

&lt;p&gt;Fontos, hogy a projekt granularitása összefügg az issue tracker-ünkben felvett projektekkel is. Hiszen ha a projektek külön életet élnek, külön verziószámokkal rendelkeznek, akkor érdemes ezeket az issue tracker-ben is külön követni. Ha a projektek általában együtt mozognak, és egyszerre kell javítani, kiadni, követni őket, akkor mind a release, mind a verziókezelés, mind az issue tracking folyamán jelentős pluszmunkát veszünk magunkra.&lt;/p&gt;

&lt;h4&gt;pom.xml formázása&lt;/h4&gt;

&lt;p&gt;Mutasd a pom.xml-ed, megmondom, milyen a projekted! A pom.xml-eket is olyan tisztán kell tartani, mint a forráskódot. Ez egy XML állomány, ahol a tag-ek sorrendje nem kötött, azonban mégis javaslom, hogy a projekten belül az összes modulban ugyanazt a sorrendet használjuk. A függőségeknél is ajánlott egy sorrendet meghatározni, pl. előbb a belső függőségek, majd a nem publikus repository-kból nyert függőségek, majd scope-onként a compile, provided, test scope-ú függőségek. Így ahhoz szokik a szemünk, automatikusan tudjuk, hogy mit hol kell keresni, azonnal láthatjuk, hogy valami van-e definiálva, vagy hiányzik. A forráskódhoz hasonlóan ne használjunk felesleges comment-eket, de amit célszerű, azt jegyezzük fel (pl. függőségekkel kapcsolatos tudnivalók). Ne használjunk csupa nagybetűs comment-eket, ahogy sormintákat se.&lt;/p&gt;

&lt;h4&gt;DRY, KISS&lt;/h4&gt;

&lt;p&gt;Forrásokhoz megfelelően próbáljuk a pom.xml-ekben az ismétlődéseket kerülni (Don't Repeat Yourself). Ez megoldható öröklődéssel, azaz a szülőben definiált a gyermek örökli. Használjunk property-ket, akár beépítetteket, akár saját magunk által definiáltakat. Legyenek a pom.xml-ek egyszerűek (Keep it short and simple). Persze ez főleg akkor lehetséges, ha a projektünk alkalmazkodik a konvenciókhoz, és nem használ semmiféle egzotikus megoldást, ami követendő. Használjunk szabványos megoldásokat, a Maven beépített eszközeit és plugin-jeit. (Pl. verziószám megjelenítését &lt;a href="http://jtechlog.blogspot.com/2011/09/verzioszam-megjelenitese-az.html"&gt;resource filtering&lt;/a&gt; segítségével.) Használjuk a default értékeket, ahelyett, hogy konfigurálnánk (convention over configuration). Pl. standard könyvtárstruktúra.&lt;/p&gt;

&lt;h4&gt;Felelős&lt;/h4&gt;

&lt;p&gt;Legyen a pom.xml-eknek egy felelőse. Lehetőleg a vezető programozó, architect. A pom.xml-be felvett változások általában az architektúra, függőségek módosítását jelzik. Sem a modulok között, sem a 3rd party library-ra nem jó, ha bekerül egy új függőség, a felelős tudta nélkül. Igenis figyelni kell, hogy ne kerüljön bevezetésre egy sokadik XML parser. Remélhetőleg a pom.xml a projekt életciklusa során keveset változik.&lt;/p&gt;

&lt;h4&gt;Konvenciók&lt;/h4&gt;

&lt;p&gt;Ha már a Maven alapelve a konvenciók használata, próbáljunk meg mi is alkalmazkodni ehhez több szinten is, vezessünk be projekt konvenciókat. Ilyen pl. a projektek elnevezési konvenciója (javasolt kisbetűkkel, szavakat kötőjellel elválasztva írni), verziószám konvenciók, stb.&lt;/p&gt;

&lt;h4&gt;Build reprodukálhatóság&lt;/h4&gt;

&lt;p&gt;Lehetőleg törekedjünk arra, hogy nem előkészített környezetben, notebook-on, otthon is fusson le a build. Ne legyen szükség külső függőségekre, speciális könyvtárakra, adatbázis szerverre, stb. Lehetőleg csak a céges repository manager elérésével bárhol le tudjuk futtatni a build-et. A Sonatype könyv organizational portability-nek hívja azt, amikor egy cég belső hálóján lévő bármilyen gépen azonnal le tudjuk futtatni a build-et.&lt;/p&gt;

&lt;p&gt;Olvastam olyan ötletről is, hogy a Maven-t se kelljen egyénileg feltelepíteni, és a repository se foglalja mindenki gépén a helyet, egy megosztott meghajtóra lehet ezeket tenni, és mindenki onnan használhatja. A repository helye alapértelmezésben a home könyvtárunk alatt a /.m2/repository könyvtár. Ez sok esetben nem megfelelő, pl. ékezet, space van benne, vagy pl. szerverrel szinkronizált, központilag mentett, vagy egyszerűen nem szeretnénk a rendszer partíciónkon tárolni ezeket. A lokális repository új helyét a settings.xml-ben a localRepository tag-ek között adhatjuk meg.&lt;/p&gt;

&lt;p&gt;Ügyeljünk arra, hogy lehetőleg környezetenként (fejlesztői/teszt/éles) ugyanazokat az artifact-okat használjuk. Minden környezet függő információt az alkalmazáson kívül tároljuk, konfigurációs állományokban, JNDI-ben, adatbázisban. Így ugyanazt az állományt telepíthetjük minden környezetbe.&lt;/p&gt;

&lt;h4&gt;Repository manager és CI&lt;/h4&gt;

&lt;p&gt;Mindig használjunk repository manager-t. Egyrészt proxy a publikus repository-k felé, másrészt a saját artifact-jainkat is tartalmazza, ami nélkülözhetetlen több modulból álló projektek esetén. Ide tölthetjük fel az egyéb forrásból származó 3rd party jar-okat is.&lt;/p&gt;

&lt;p&gt;Bár nem ide tartozik szorosan, használjunk Continuous Integration eszközt is, mely egyrészt segít az integráció idejének csökkentésében azáltal, hogy gyakori időközönként build-el, és lefuttatja a teszt eseteket, így a problémákról mielőbb értesítést kapunk, nem csak akkor mikor mi is elvégeznénk az integrációt. Valamint különösen alkalmas arra, hogy ellenőrizzük, hogy nem csak egy beállított környezetben fut a projekt, egy fejlesztői gépen, hanem egy független build szerveren is.&lt;/p&gt;

&lt;h4&gt;Magas szintű pom.xml-ek&lt;/h4&gt;

&lt;p&gt;Bizonyos konfigurációkat szervezet szinten (corporate), vagy projekt szinten definiáljuk egy szülő pom.xml-ben. A gyermek projektek ebből öröklik a beállítások, melyek leíró információk pl. a szervezettel, projekttel, fejlesztőkkel kapcsolatban. Tartalmazhatja a distributionManagement szekciót, mely a repository manager elérhetőségét írja le (ne a konkrét projekteknél definiáljuk). Valamint tartalmazhatja a plugin konfigurációkat, azok verziószámát (lásd később, a "Függőségek" fejezetben).&lt;/p&gt;

&lt;h4&gt;Függőségek&lt;/h4&gt;

&lt;p&gt;Mindig tartsuk rendben a függőségeinket. Lehetőleg publikus repository-ban található 3rd party library-ből építkezzünk (, ebben segíthet a &lt;a href="http://mojo.codehaus.org/versions-maven-plugin/"&gt;Version Maven Plugin&lt;/a&gt;). Amennyiben van nem ilyen is, tüntessük fel annak a forrását, amennyiben van forráskódjának, dokumentációjának elérhetőségét. Vigyázzunk, ugyanannak a library-nak ne szerepeljenek különböző verziója függőségben. Ez akkor lehet, ha pl. egy artifact-et egyik verzióról a másikra át is neveztek, vagy pl. groupId-t váltottak. Figyeljünk a library-k megfelelő scope-jára. Lehetnek olyan jar-ok, melyek csak teszteléskor kellenek (test), illetve olyanok, melyeket nem kell az artifact-unkba csomagolni, az alkalmazásszerver biztosítja ezeket (provided). A moduljaink között ne legyen körkörös hivatkozás. A függőségek definiálásánál ne használjunk intervallumokat, adjuk meg a pontos verziószámokat. Amennyiben egy függőséghez több artifact is tartozik, pl. Hibernate, Spring sok modulból áll, akkor javasolt a verziószámot egy külön property-be kiemelni, és az összes modulban arra hivatkozni (pl. ${spring.version}).&lt;/p&gt;

&lt;p&gt;A függőségeinket tartsuk karban. Ne engedjük őket elburjánzani (lsd. "Felelős" fejezet). Futtassuk a dependency:analyze goal-t, feltárva ezzel a deklarált, de nem használt függőségeket (töröljük), valamint a használt, de nem deklarált függőségeket. Ez utóbbi akkor jelentkezhet, ha egy függőségre csak tranzitív függőség van, és mégis használjuk az osztályait. Ekkor javítsuk direkt függőségre.&lt;/p&gt;

&lt;p&gt;Plugin-ek esetén is mindig deklaráljuk a verziószámot, szülő projekt létezése esetén annak pluginManagement szekciójában, hiszen az öröklődik, ahogy egy régebbi &lt;a href="http://jtechlog.blogspot.com/2011/08/maven-plugin-ek-verzioszama.html"&gt;post-ban&lt;/a&gt; írtam.&lt;/p&gt;

&lt;p&gt;Amennyiben ugyanazt a függőséget több modul is használja, érdemes a szülő projektben felsorolni a függőségek verziószámát, és exclude tag-eket a dependencyManagement szekcióban, melyet a gyermek projektek örökölnek, így azokban elegendő csak a groupId-t és artifactId-t deklarálni.&lt;/p&gt;

&lt;p&gt;Amikor egy problémát meg akarunk oldani, és van egy bevált receptünk, és erre több 3rd party library-t is mozgósítunk, és mindig ugyanazokat, akkor szervezzük ki a függőségeket egy külön projektbe (dependency group), így elég erre az egyre függőséget definiálni, ami tranzitíven berántja a többi függőséget is. Ez ellentmondhat annak a szabálynak, hogy amit közvetlenül használunk, azt mindig direkt függőségben deklaráljuk. Ez utóbbit tartsuk be inkább.&lt;/p&gt;

&lt;p&gt;Nem csak Java osztályokat, hanem közösen használt erőforrásokat, pl. képeket, stíluslapokat, stb. is kiszervezhetünk külön projektbe. Vagy akár plugin konfigurációkat is, pl. checkstyle, pmd konfigurációkat is, ha különböző projekteken ugyanúgy akarjuk ezeket használni. A Maven dependency pluginnel sok csodát meg lehet csinálni.&lt;/p&gt;

&lt;h4&gt;Prototípus&lt;/h4&gt;

&lt;p&gt;Kicsit furcsa lehet, hogy a projektek közötti szülő-gyermek kapcsolat, és a modul-almodul kapcsolat két külön fogalom. A szülő-gyermek kapcsolat estén a gyermekben definiáljuk a szülőt, a parent tag-ek között. A gyermek ekkor örökölni fogja a szülő beállításait (lsd. még effective pom). A szülő nem tud a gyermek projektjeiről. Míg egy modul a modules tag-ek között felsorolhatja az almoduljait. Ez által megeshet az a furcsa eset is, hogy egy almodult olyan modul tartalmaz, mely az almodulnak nem szülő projektje. Nézzünk erre egy példát. Van több projektünk, mely nagyon hasonló egymáshoz, mind egy Java EE alkalmazás, melynek kimenete egy EAR. Mindegyik projekt több alprojektből áll, külön az EJB réteg, külön a web réteg, stb. Az ejb és web rétegek azonban nagyon hasonlítanak egymáshoz. Ezért, hogy a copy-paste-et elkerüljük, a közös dolgokat kiemeljük egy szülő projektbe, külön az ejb rétegeknek egy, külön a web rétegeknek egy. Ezeket a projekteket hívják prototípus projekteknek.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" rel="lightbox" href="http://4.bp.blogspot.com/-BgONRQSen2k/ToEIxcJT0yI/AAAAAAAAHdc/uwBC1WOIPdc/s1600/maven_prototype.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 140px;" src="http://4.bp.blogspot.com/-BgONRQSen2k/ToEIxcJT0yI/AAAAAAAAHdc/uwBC1WOIPdc/s320/maven_prototype.png" alt="" id="BLOGGER_PHOTO_ID_5656812252415906594" border="0" /&gt;&lt;/a&gt;

&lt;h4&gt;Archetype&lt;/h4&gt;

&lt;p&gt;Ha gyakran kezdünk új projektet, vagy egy létező rendszerbe új modult, akkor lehetőség van archetype deklarálására. Ez tulajdonképpen egy projekt sablon, amiből ki lehet indulni. Így nem úgy kezdünk egy új projektet, hogy veszünk egy létezőt, és lebutítjuk, hanem már egy sablonból. Vannak előregyártott archetype-ok is, pl. egyszerű Java alkalmazás, egyszerű web alkalmazás, Maven plugin, Confluence plugin, NetBeans modul, stb. Vagy pl. nézhetjük &lt;a href="http://raibledesigns.com/"&gt;Matt Raible&lt;/a&gt; tevékenységét is, az &lt;a href="http://appfuse.org/display/APF/Home"&gt;AppFuse-t&lt;/a&gt; is, mely előre gyártott projekt sablonok, melyek különböző technológiák integrálásával (Spring, JSF, Struts 2, Spring MVC, Stripes, Tapestry 5, Wicket, JPA, stb.) jöttek létre. Ezek kis példa alkalmazások, melyek önmagukban is működnek, nem nekünk kell konfigurálgatni, integrálgatni, jó kiinduló alapot biztosítanak. Be kell vallanom, én annyira nem hiszek az archetype-okban, mert mire új projektet kellett indítani, mindig változott valamelyest a technológia, más keretrendszereket használtunk, más megközelítésmódot alkalmaztunk. Ezeknek tényleg inkább alkalmazásgyáraknál van jelentősége.&lt;/p&gt;

&lt;h4&gt;Assembly&lt;/h4&gt;

&lt;p&gt;Az assembly plugin használatának minden könyv külön fejezetet szentel. Arra használható, hogy gyakorlatilag bármilyen artifact-ot elő tudunk vele állítani, attól függően, hogy hogyan szeretnénk terjeszteni az alkalmazásunkat. Vannak &lt;a href="http://maven.apache.org/plugins/maven-assembly-plugin/descriptor-refs.html"&gt;előre beépített&lt;/a&gt; struktúrák (ezek közül van, ami csak a binárist tartalmazza, a binárist tartalmazza a függőségekkel, csak a forrást tartalmazza, teljes projektet tartalmazza), de természetesen sajátot is tudunk gyártani.&lt;/p&gt;

&lt;h4&gt;Verziókezelő struktúra&lt;/h4&gt;

&lt;p&gt;Bár nem így kéne lennie, egy kicsit kényszerpályán vagyunk azzal kapcsolatban, hogy hogyan szervezzük a verziókezelőben a projektjeinket, Subversion esetén trunk-ot, tag-eket, branch-eket, stb. Erről már írtam egy korábbi &lt;a href="http://jtechlog.blogspot.com/2010/10/release-maven-nel-es-hudson-nel.html"&gt;post-ban&lt;/a&gt;. Egyszerű szabály, hogy a projekt neve és a könyvtár neve egyezzen meg. Nagyon tervezzük meg, dokumentáljuk, és teszteljük a választott struktúrát, különösen a release folyamat esetén.&lt;/p&gt;

&lt;h4&gt;Teszt, release és deployment&lt;/h4&gt;

&lt;p&gt;A unit tesztek lefutása legyen gyors. Amennyiben integrációs teszteket is alkalmazunk, nyugodtan nyissunk neki külön projektet. Gyorsabb lesz tőle a build folyamat, és megfelelően szeparálva lesz a unit tesztektől.&lt;/p&gt;

&lt;p&gt;Használjuk a Maven release plugin-t, egy release elkészítésére. Egy release egy végleges, megváltoztathatatlan artifact, mely könnyen azonosítható, bármikor később reprodukálható. (Szemben a snapshot verzióval, mely egy folyamatosan változó, fejlesztés alatt lévő verzió.&lt;/p&gt;

&lt;p&gt;A deployment-re is külön projektet érdemes készíteni, mely függőségként definiálja a telepítendő artifact-ot. Ezt aztán telepítés során letölti a telepítendő állományt, és telepíti a megfelelő alkalmazásszerverre. Így nem zavarja a normál fejlesztési munkafolyamatot.&lt;/p&gt;

&lt;h4&gt;Nem erőltetném&lt;/h4&gt;

&lt;p&gt;Természetes, hogy amiket a fentiekben javaslok, azoknak ne használjuk az ellentétét. Tehát pl. ne használjunk version range-eket, hanem mindig pontosan deklaráljuk a verziószámokat.&lt;/p&gt;

&lt;p&gt;Én nem szeretem a profile-ok használatát sem, amennyiben lehetőség van rá, kerülöm őket. Konkrétan ott szoktam alkalmazni, ahol gyorsítják a fejlesztés - telepítés - tesztelés folyamatot. Pl. fejlesztés közben nem érdemes a war-t összecsomagolni, ha az alkalmazásszerver a kibontottat is (exploded war, in place deployment) fel tudja olvasni (persze release-kor meg a fájl kell), vagy release-kor más artifact-ot is elő kell állítani (pl olyan jar állományt, melyben bele vannak csomagolva a függőségek). Ezeket fejlesztés közben nem akarom előállítani.&lt;/p&gt;

&lt;p&gt;Csakis a legvégső esetben folyamodnék ahhoz, hogy saját Maven plugin-t fejlesszek. Szerencsére erre még nem volt szükség, mindig találtam olyat, mely megfelelő volt az igényeimnek.&lt;/p&gt;

&lt;p&gt;Ti használtok Maven-t? Mennyi energiát fektettek a pom struktúra kidolgozásába, szinten tartásába, tökéletesítésébe? Segít, vagy hátráltat? Kedvelt eszköz, vagy a szükséges rossz? Tapasztalatok alternatív eszközökkel?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-9075776410959180550?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/9075776410959180550/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/09/maven-legjobb-gyakorlatok.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/9075776410959180550?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/9075776410959180550?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/09/maven-legjobb-gyakorlatok.html" title="Maven legjobb gyakorlatok" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-BgONRQSen2k/ToEIxcJT0yI/AAAAAAAAHdc/uwBC1WOIPdc/s72-c/maven_prototype.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkABQn49eyp7ImA9WhdUEEU.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-3642971482325571342</id><published>2011-09-18T14:24:00.010+02:00</published><updated>2011-09-27T01:45:53.063+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-27T01:45:53.063+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><title>Maven bevezetés, modernizáció</title><content type="html">&lt;p&gt;Technológiák: Maven 3.0.3&lt;/p&gt;

&lt;p&gt;Valahogy az elmúlt időszakban úgy alakult, hogy három projektben is Maven szaktanácsadást nyújthattam. Ebből egy egy teljesen nulláról induló projekt, egy Ant-ról migrálós projekt valamint egy már meglévő Maven projekt továbbfejlesztése. Az ezekben szerzett tapasztalatokról szeretnék itt beszámolni.&lt;/p&gt;

&lt;p&gt;Ebből a legizgalmasabb a már létező Maven projekt modernizálása, egy Gibraltáron működő online szerencsejáték cégnek, ahova a meghívást &lt;a href="http://britpalmak.blogspot.com/"&gt;Magyusz&lt;/a&gt; és Cseki haverom intézte, akik ott vezető programozói státuszban tevékenykednek. Ezúttal is köszönöm nekik! &lt;a href="http://britpalmak.blogspot.com/2011/07/magyarok-majd-megoldjak.html"&gt;Három napot töltöttem a projektben&lt;/a&gt;, ami során sikerült megismerni a jelenlegi Maven struktúrát, a legjobb gyakorlatokat alkalmazni, és felderíteni a gyenge pontokat. Persze sok utómunkával jár, és vannak ötletek, hogy merre lehetne tovább fejlődni. A három nap tartalmazta a verziókezelés folyamatának kialakítását is, az előző post-jaim ezekről szóltak.&lt;/p&gt;

&lt;p&gt;Magáról az országról sokat nem tudok írni, az eltöltött öt nap benyomások szerzésére volt elegendő. Egy apró brit tengerentúli terület (7 négyzetkilométer), ami minden egyes pontján erősen érződik is. Angol a hivatalos nyelv, emeletes busz, klasszikus londoni telefonfülke és még sok minden megtalálható itt. Amiről az úti beszámolók a leggyakrabban írnak, hogy az országba jutáskor át kell kelni a repülőtér felszállópályáján, ami keresztezi a határról érkező utat, lámpával irányítva, ami piros, ha épp egy repülőgép száll fel, vagy le. Valamint a szikla tetején (, ahonnan gyönyörű a kilátás minden irányban) élő Európában egyedülállóan szabadon élő majmok híresek itt. Apropó Gibraltár egy hatalmas mészkőszikla, ami ki tudja honnan került ide, és át és át van lyuggatva, mint a sajt, belsejében érdekesebbnél érdekesebb és titkos dolgokkal, valamint egy kis feltöltött terület. Déli pontjáról tiszta időben szépen látszik Afrika. Északon Spanyolországgal határos, a nem éppen legszebb La Linea de la Conception várossal, de kicsit messzebb menve már gyönyörű helyekre lehet eljutni, mint egy &lt;a href="http://britpalmak.blogspot.com/2011/07/sikloernyos-etterem.html"&gt;siklóernyős starthely&lt;/a&gt;, vagy egy &lt;a href="http://britpalmak.blogspot.com/2011/07/kitesurf-paradicsom.html"&gt;kitesurf paradicsom&lt;/a&gt;, az óceánnál.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-PZmnGNKjaMw/TnXnWB8KyjI/AAAAAAAAHZs/F6nx45R1OMg/s1600/gib1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/-PZmnGNKjaMw/TnXnWB8KyjI/AAAAAAAAHZs/F6nx45R1OMg/s320/gib1.jpg" alt="" id="BLOGGER_PHOTO_ID_5653679272897464882" border="0" /&gt;&lt;/a&gt;

&lt;p&gt;A cég nagyon meggyőző volt, látszott, hogy komolyan veszik, amit csinálnak. Olyan hangulat uralkodott, hogy érződött, hogy odafigyelnek a munkájukra. A társaság igen vegyes, mind nemzetiségileg, mind szakmailag. Érdekes jelenség, hogy a szerverekkel nem fukarkodnak, azonban az emberi erőforrásokban sokkal inkább. Egyik szobában a sporteseményeket követték, impresszív volt a minden asztalon három LCD monitor, valamint a mennyezetről lógó plazmatévék sora. Természetesen a fejlesztőknél is volt egy tévé, hogy a fontosabb sporteseményeket követni lehessen. Alapvetően különbségeket azonban nem tapasztaltam, sem szakmailag, sem technológiailag. Az irodából kilépve azonban azonnal elöntötte a mediterrán hangulat, a meleg, a késő este is napsütés, tengerpart, a hatalmas és tekintélyt parancsoló, a kikötőben állomásozó hajókkal, vonzották az embert a part menti bárok és kaszinó.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-L9G38OUpUHg/TnXnghWhidI/AAAAAAAAHZ0/kEunQcyTHwI/s1600/gib2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/-L9G38OUpUHg/TnXnghWhidI/AAAAAAAAHZ0/kEunQcyTHwI/s320/gib2.jpg" alt="" id="BLOGGER_PHOTO_ID_5653679453128198610" border="0" /&gt;&lt;/a&gt;

&lt;p&gt;Lássuk, hogy hogyan is telt a szakmai három nap, hogyan lehet egy Maven "rendrakást" kivitelezni. Egy build folyamat modernizációja subproject sem tér el a klasszikus szoftverfejlesztéstől, ugyanúgy van követelményfelmérés, tervezés, implementáció és tesztelés. Ugyanúgy iterációkra kell bontani, és dokumentációval megtámogatni. A következő lépésekből áll a folyamat.&lt;/p&gt;

&lt;h4&gt;Követelmények&lt;/h4&gt;

&lt;p&gt;A projekt célját érdemes tisztázni. Mi a probléma a jelenlegi folyamattal, mi nehezíti a build folyamatban legjobban a szoftverfejlesztést, mi az ami "legjobban fáj"?. Lehet ez a túl durva vagy túl finom granularitású modularizáció, a hosszú build, a nehézkes fejlesztés, a sok szaktudást igénylő release. Meg kell hallgatni az ügyfelet, hogy milyen ötletei vannak, hiszen ő él a projektben, lehet, hogy sejti, esetleg tudja, hogy mit és hogyan szeretne. Hasznosak a mérőszámok, pl. projektek száma, pom.xml állományok száma, benne szereplő sorok száma, build folyamat hossza időben, stb.&lt;/p&gt;

&lt;p&gt;A felmérés során meg kell ismerni a jelenlegi rendszer architektúráját is, én komponens diagramot használok. Milyen alkalmazások futnak, ezek hogyan kapcsolódnak egymáshoz, milyen közös könyvtárakat használnak. Milyen típusú alkalmazások vannak, standalone, web alkalmazások, esetleg Java EE alkalmazások. Milyen környezetben futnak, milyen operációs rendszerek, alkalmazásszerverek használtak, mennyire fontos a platformfüggetlenség. A build folyamat szempontjából ezek cseppet sem elhanyagolhatóak, hiszen ez alapján nagyjából sejteni lehet, hogy mennyi és milyen típusú artifact-okra lehet számítani. Ez esetemben kb. 10 alkalmazás, közte standalone és webes is.&lt;/p&gt;

&lt;p&gt;Fel kell térképezni a jelenlegi Maven struktúrát. Ez a fejlesztői környezet installálása saját gépen (rögzítsük, hogy ez milyen lépésekből áll, mennyire bonyolult, hogyan lehet egyszerűsíteni), valamint annak futtatása. Rögzítsük impresszióinkat, mennyi ideig tart, vannak-e warning-ok, hibaüzenetek. És a legunalmasabb rész, át kell böngészni egyesével a pom.xml-eket, és jegyzeteket készíteni, hol lehet és kell módosítani. Közben rögzítem azokat az eszközöket is, amelyek nem szokványosak, pl. egyedi forráskód generálás, stb. Feljegyzem, hogy hol "bűzlik a kód". Az ügyfelet is kérdezzük meg, hogy hol érzi rossznak, mit miért csináltak, mert ilyenkor lehet rábukkanni arra, hogy valamiért speciális/egyedi-e az adott projekt, valamint vannak-e hiányosságok az ügyfél tudásában, vagy bizonyos megoldások mellett miért döntött.&lt;/p&gt;

&lt;p&gt;Én közben egy függőségi gráfot is rajzolok. Osztálydiagramot szoktam alkalmazni, ahol színekkel jelzem az alkalmazások típusait, valamint dependency-vel a függőségeket, kompozícióval a modul tartalmazást és generalizációval a szülő kapcsolatot.&lt;/p&gt;

&lt;a ref="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-Sp5_3iaRpM0/TnXyWTzjFfI/AAAAAAAAHaE/EUlOKwnisUM/s1600/modulok.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 177px;" src="http://4.bp.blogspot.com/-Sp5_3iaRpM0/TnXyWTzjFfI/AAAAAAAAHaE/EUlOKwnisUM/s320/modulok.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5653691372321052146" /&gt;&lt;/a&gt;

&lt;p&gt;Nem javaslom a függőségi gráfok generálását. Egyrészt, ha magunk rajzoljuk, sokkal jobban megértjük, valamint vannak olyan függőségek, amik evidensek, és csak az ábrát bonyolítanák (pl. egy common könyvtárra biztos mindenki hivatkozik). Valamint ezek az eszközök értelmesen sem tudják elhelyezni az artifact-okat.&lt;/p&gt;

&lt;p&gt;Sajnos gyakran futok bele olyan projektekbe is, ahol körkörös függőségre bukkanok. Pl. a common library-ra hivatkozik a service és a ui réteg is, de a common visszahivatkozik az ui rétegre. Kiemelten kezeljük ezeket a problémákat.&lt;/p&gt;

&lt;p&gt;Vizsgáljuk meg a külső függőségeket. Ezeket feltűnően lazán szokták kezelni, bekerül a projektbe, de utána kikerül, de a függőségek közül nem távolítják el. Nem megfelelő scope-ba veszik fel, pl. csak teszteléskor van rá szükség, mégis normál függőségként szerepel. Egymással ütköző library-k vannak, melyek csak a véletlennek köszönhetően működnek együtt (pl. előbb van a classpath-ban), ilyenek pl. az naplózó keretrendszerek, az XML library-k. Láttam olyant is, hogy egy library-nak különböző verziói szerepeltek a függőségek között (pl. változott a library group vagy artifact id-ja). Egy feladatra különböző library-k szerepelnek a projektbe, pl. az előbb említetteken túl több webes keretrendszer, REST API, SOAP API, perzisztencia réteg, stb. Sokan megfeledkeznek róla, de ellenőrizzük a licence-eket is.&lt;/p&gt;

&lt;p&gt;Vizsgáljuk meg a teszt eseteket. Granularitásukat, bonyolultságukat. Gyakran keverednek a fogalmak, pl. unit tesztek között találhatunk integrációs tesztet, ami nagyobb egységet tesztel, esetleg külső rendszerekre, adatbázisra is szüksége van.&lt;/p&gt;

&lt;p&gt;Egyeztessünk, milyen riportokra állnak rendelkezésre, és ezek közül melyekre van szükség?&lt;/p&gt;

&lt;h4&gt;Tervezés&lt;/h4&gt;

&lt;p&gt;Amint felmértük a követelményeket, az ügyfél elvárásait, tervezzük meg a migráció, bevezetés folyamatát. Bontsuk lépésekre, definiáljuk a lépések scope-ját.&lt;/p&gt;

&lt;p&gt;Első esetben mindenképpen az elvárt struktúrát tervezzük meg, a már fentebb említett osztálydiagrammal. Lehet, hogy nem kell rajta változtatni, lehet, hogy gyökeres változtatásokat kell bevezetni. Amit mindenképpen meg kell szüntetni, az a körkörös függősségek. Ki kell találni a megfelelő granularitást, új modulokat bevezetni, modulokat összevonni vagy szétválasztani.&lt;/p&gt;

&lt;p&gt;Válasszuk ki a megfelelő eszközöket. Amennyiben úgy gondoljuk, ne erőltessük a Maven-t. Nem minden projekt, és nem minden fejlesztőgárda tud megfelelően illeszkedni hozzá. Minél szabványosabb a projekt, annál egyszerűbb adoptálni. Amennyiben túl sok egyediség van az architektúrában, a fejlesztési folyamatban, vagy a fejlesztők nem eléggé nyitottak a Maven irányába, alaposan gondoljuk meg, hogy van-e értelme, ilyen környezetben kétes a projekt sikere. Amennyiben azonban a Maven-t válasszuk, jelöljük meg, hogy milyen plugin-eket kívánunk használni. Dokumentáljuk döntéseinket.&lt;/p&gt;

&lt;p&gt;Elemezzük a függőségeket. Tervezzük meg, hogy mely függőségek maradhatnak, azok milyen scope-ban. Nézzük meg, hogy a legfrissebb verziók kerültek-e felhasználásra, és ha nem, ennek van-e valamilyen oka. Tervezzük meg, hogyan szüntethetjük meg az ütközéseket. Nézzük meg, hogy mely függőségek nem publikus repository-ból kerülnek letöltésre, létezik-e publikus megfelelőjük. Ha nem, honnan származnak, megvan-e a forráskódjuk.&lt;/p&gt;

&lt;p&gt;Tervezzük meg, hogy az alkalmazások verziószáma hogyan jelenik meg a felületen, és a build folyamat során hogyan kerül beírásra. Erről szól az előző &lt;a href="http://jtechlog.blogspot.com/2011/09/verzioszam-megjelenitese-az.html"&gt;post-om&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tervezzük meg a test harness-t. Elegendő-e a JUnit, vagy érdemesebb-e a TestNG-t használni. Mivel mérjük a kódlefedettséget? Milyen integrációs teszt keretrendszert használjunk.&lt;/p&gt;

&lt;p&gt;Tervezzük meg a használni kívánt riportokat, azok paraméterezését.&lt;/p&gt;

&lt;p&gt;Én a tervezési fázisban egy olyan dokumentációt is készítek, mely leírja, hogy a fejlesztő csapatnak milyen feladatokat kell elvégeznie. Ez egyrész tartalmazza azokat a feladatokat, melyek előfeltételei a migrációnak. A forráskód, a rendszer megismerésével is találkozni lehet olyan problémákkal, amiket érdemes jelezni, de nem tartoznak szorosan a modernizációhoz - ezeken a fejlesztőcsapat akár párhuzamosan is dolgozhat. Valamint egy olyan dokumentációt is írok, mely a build folyamat továbbfejlesztési lépéseit is tartalmazza, hiszen nem hiszek abban, hogy egyszerre túl nagyot kéne lépni, érdemes kis lépésekben elvégezni a bevezetést. Hiszen az első használatbavételkor pontosodnak majd az igények.&lt;/p&gt;

&lt;h4&gt;Implementáció&lt;/h4&gt;

&lt;p&gt;Amennyiben van olyan teendő, mely blokkolja a Maven build bevezetését, továbbfejlesztését, meg kell várnunk azok befejezését. Találkoztam olyan projekttel, ahol ez több hetet is igénybe vett, hiszen az élet nem állhat meg, a fejlesztő csapat nem minden esetben képes csak a modernizációra figyelni, közben új verziókat kell kiadni, hibákat javítani, stb.&lt;/p&gt;

&lt;p&gt;Első körben, amennyiben a projekt még nem végleges, egy olyan build folyamatot valósítsunk meg, mely bitre pontosan ugyanazokat az artifact-okat gyártja le, mint az előző build folyamat (pl. script-ek, Ant build.xml-ek). Bár lehet, hogy nagyobb refactoring-ot kell elvégeznünk, ez mégis segít a megértésben, a trükkös megoldások felderítésében, a projekt sajátosságainak megértésében. És azonnali eredményt biztosít, hiszen azonnal bevethetjük.&lt;/p&gt;

&lt;p&gt;Alakítsuk ki a könyvtárstruktúrát, lehetőleg a Maven által definiált kvázi szabványoknak megfelelően, és írjuk, módosítsuk a pom.xml állományokat, és alakítsuk ki a verziókezelő struktúrát. A pom.xml-ek megírására most nem térnék ki, a követendő legjobb gyakorlatok a következő post-om tárgya. Konvencióknak megfelelően nevezzük meg a projekteket, adjunk verziószámot, definiáljuk a függőségeket, a plugin-eket (legyenek akár report plugin-ek). Amennyiben szükséges, használjuk profile-okat.&lt;/p&gt;

&lt;p&gt;Az egyik projekt során feladat volt Maven 2-ről Maven 3-ra migrálni. Ezzel csak jó tapasztalataim voltak. Első körben azonnal warning-okat ír ki, ami a nem megfelelő pom.xml bejegyzéseket tartalmazza (pl. nincs definiálva a plugin-ek verziószáma). Ezeket mindenképpen eliminálni szükséges. A build is gyorsabb 3-as Maven-nel, bár nem számottevően. És volt olyan is, hogy egy multimodule projektet a 2-es nem tudott release-elni, mert a modulok közötti függőség esetén nem találta a "testvér" modult a reactor-ban, míg a 3-as gond nélkül megcsinálta.&lt;/p&gt;

&lt;p&gt;Az implementáció során előállt termékek:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verziókezelő struktúra&lt;/li&gt;
&lt;li&gt;A pom.xml állományok&lt;/li&gt;
&lt;li&gt;Különböző segéd script-ek&lt;/li&gt;
&lt;li&gt;Különböző napló állományok&lt;/li&gt;
&lt;li&gt;Build folyamat dokumentációja&lt;/li&gt;
&lt;li&gt;Továbbfejlesztési javaslatok dokumentációja&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Tesztelés&lt;/h4&gt;

&lt;p&gt;A build folyamatot ugyanúgy kell tesztelni. Első körben elegendő összehasonlítani, hogy az előállított artifact-ek bitre megegyeznek-e. Ha már ezen a szinten is módosításokat tettünk, akkor tesztelni kell, hogy az előállított artifact-el ugyanúgy működnek-e (nem hiányzik-e jar, amit egy ClassNotFoundException jelez, stb.). Adjuk oda a fejlesztőknek az eszközt, hogy vegyék használatba. Elemezzük a használati eseteket, hogy mindent lefedtünk-e. Ez az egyszerű fejlesztés, build parancssorban, build és futtatás IDE-ben. Build a CI szerveren. Fejlesztés branch-en, merge-ölés. Release. Artifact-ek deploy-olása különböző környezetekre. Gyűjtsük össze a fejlesztők benyomásait, tapasztalatait. Határozzuk meg újra a mérőszámokat, és hasonlítsuk össze a projekt kezdetén mértekkel. Szükség esetén javítsuk a hibákat, gyűjtsük a továbbfejlesztési ötleteket.&lt;/p&gt;

&lt;p&gt;Befejezésül annyit, hogy egy Maven alapú build folyamat kialakítása nem egyszerű feladat, és nagymértékben meg kell ismerni, meg kell érteni az alkalmazást is, mely build-elésre kerül. A build folyamat megvalósítása egy kis szoftverfejlesztési projekt, ugyanazon lépésekkel, ugyanúgy iteratívan. Szánjunk időt és erőforrást a kialakítására és karbantartására. Ez az ugródeszka, mely a teljes szoftverfejlesztési infrastruktúra alapját képzi, melybe ezen kívül beletartozik a verziókezelő rendszer, issue tracker, tudástár, repository manager, CI, test harness, quality management eszköz, és beletartoznak olyan lépések, mint tesztelés, release, deployment, code review, minőségbiztosítás, stb.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-mBhh7Ya1CSY/TnXnnPNKlyI/AAAAAAAAHZ8/TeQOJXqSLgk/s1600/gib3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/-mBhh7Ya1CSY/TnXnnPNKlyI/AAAAAAAAHZ8/TeQOJXqSLgk/s320/gib3.jpg" alt="" id="BLOGGER_PHOTO_ID_5653679568516192034" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-3642971482325571342?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/3642971482325571342/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/09/maven-bevezetes-modernizacio.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/3642971482325571342?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/3642971482325571342?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/09/maven-bevezetes-modernizacio.html" title="Maven bevezetés, modernizáció" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-PZmnGNKjaMw/TnXnWB8KyjI/AAAAAAAAHZs/F6nx45R1OMg/s72-c/gib1.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkMMQn0zfCp7ImA9WhdWGUg.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-6632348504802797991</id><published>2011-09-14T00:52:00.001+02:00</published><updated>2011-09-14T00:54:43.384+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-14T00:54:43.384+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><title>Verziószám megjelenítése az alkalmazásban</title><content type="html">&lt;p&gt;Technológiák: Maven 3.0.3, Build Number Maven Plugin 1.0&lt;/p&gt;

&lt;p&gt;Kocka írt nem olyan régen egy &lt;a href="http://iwillworkforfood.blogspot.com/2011/08/verzioszam.html"&gt;blog post&lt;/a&gt;-jában arról, hogy hogyan lehet az alkalmazás verziószámát kiírni a felületre. Mivel én is nemrég csináltam meg több projektünkben is, álljon itt az én megoldásom.&lt;/p&gt;

&lt;p&gt;Új projektjeink már Maven-t használnak build-eléshez, ahol a pom.xml tartalmazza a verziószámot. Én azt javaslom, hogy ez legyen is elég. Ez egyértelműen azonosít egy artifact-ot, azaz egy alkalmazást (vagy annak moduljait). Maven használata esetén a SNAPSHOT verziószámmal rendelkező artifact-ból lehet több is, de a release-elt artifact-ból csak egy lehet, ha egyszer kiadtuk, az már többet nem módosulhat. Javasolt tesztelésre, élesre csakis release-elt artifact-ot kitenni, így egyértelműen azonosítható, így elég lesz az azonosításra a verziószám is. Abban az esetben, ha mi SNAPSHOT verziókat is ki akarunk adni tesztelésre (amit nem javaslok), érdemes még valamilyen plusz azonosítót társítani a verziószám mellé. Ez lehet egy egyedileg kézzel megadott érték (ekkor elég nagy a hibalehetőség), egy automatikusan növelt egész szám (ennek a tárolásával lehetnek gondok), timestamp, vagy a legegyszerűbb esetben az SCM revision number. De ismétlem, erre csak akkor van szükség, ha snapshot-okat is kiadunk tesztelésre, és azokat akarjuk egyedileg azonosítani, ellenkező esetben elég a verziószám. A verziószámhoz tartozó információkat pedig lehetőleg az issue tracker tartalmazza. Ebből is látszik, hogy az SCM-et én egyszerű tárolónak tekintem, ott nem szeretek plusz meta információkat tárolni, vagy pl. a revision number-t venni bármi alapjául.&lt;/p&gt;

&lt;p&gt;Amennyiben csak a release-elt alkalmazás verziószámát akarjuk kiírni, elegendő egy properties állományt létrehozni, és a Maven-t rávenni, hogy ebbe az állományba írja bele a verziószámot. Utána az alkalmazásba ezt a properties állományt kell becsomagolni, majd ezt beolvasni (pl. classpath-ról, getResourceAsStream-mel). Egy példa alkalmazás &lt;a href="http://dl.dropbox.com/u/7683931/jtechlog/versioninfo.zip"&gt;letölthető&lt;/a&gt;, mellyel ezt demonstrálom. Nem javaslom a MANIFEST.MF állomány piszkálását, mert ez csak akkor működik, ha a JAR be van csomagolva, ha pl. az alkalmazásszerver deploy-kor kicsomagolja az alkalmazást, akkor nem fog működni. A verziószám beírását a properties állományba a Maven a resoure-ok filter-elésével képes megoldani. Ekkor definiáljuk a következőt a pom.xml-ben: &lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;build&amp;gt;
 &amp;lt;resources&amp;gt;
  &amp;lt;resource&amp;gt;
   &amp;lt;directory&amp;gt;src/main/resources&amp;lt;/directory&amp;gt;
   &amp;lt;filtering&amp;gt;true&amp;lt;/filtering&amp;gt;
  &amp;lt;/resource&amp;gt;
 &amp;lt;/resources&amp;gt;
&amp;lt;/build&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Valamint a properties állományban:&lt;/p&gt;

&lt;pre&gt;
version=${project.version}
&lt;/pre&gt;

&lt;p&gt;Ekkor látni fogjuk, hogy amikor a Maven átmásolja a properties állományt, kicseréli benne a ${project.version} szöveget a projekt verziószámára.&lt;/p&gt;

&lt;p&gt;Amennyiben a MANIFEST.MF állományban is látni szeretnénk a verziószámot, a következővel egészítsük ki a pom.xml-t.&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;maven-jar-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;2.1&amp;lt;/version&amp;gt;
 &amp;lt;configuration&amp;gt;
  &amp;lt;archive&amp;gt;
   &amp;lt;manifest&amp;gt;
    &amp;lt;addDefaultImplementationEntries&amp;gt;true&amp;lt;/addDefaultImplementationEntries&amp;gt;
   &amp;lt;/manifest&amp;gt;
  &amp;lt;/archive&amp;gt;
 &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Ha mégis úgy döntünk, hogy szükségünk van build number-re is, mert SNAPSHOT verziót is azonosítani akarunk, akkor használhatjuk a &lt;a href="http://mojo.codehaus.org/buildnumber-maven-plugin/"&gt;Build Number Maven Plugin&lt;/a&gt;-t. Ennek két üzemmódja van. A build number-nek vagy az SCM revizióját használja, vagy megadhatunk neki egy formátumot. A formátumot a MessageFormat osztályban leírtaknak megfelelően lehet megadni. Itt behelyettesíthető egy vagy több egész szám, melye(ke)t automatikusan növel, a timestamp, valamint konstans értékek (szöveg és szám is).&lt;p&gt;

&lt;p&gt;Érdekes, hogy mindkét esetben definiálni kell az scm tag-et a pom.xml-ben, mert mindenképp lefuttat egy svn status parancsot, ahonnan ki tudja olvasni a branch nevét, amin éppen vagyunk. Ha nem adjuk meg az scm tag-et, a következő hibajelzést kapjuk:&lt;/p&gt;

&lt;p&gt;Failed to execute goal org.codehaus.mojo:buildnumber-maven-plugin:1.0:create (default) on project versioninfo: Execution default of goal org.codehaus.mojo:buildnumber-maven-plugin:1.0:create failed: The scm url cannot be null. -&gt; [Help 1]&lt;/p&gt;

&lt;p&gt;Először nézzük, hogy mi történik, ha a build number-t a revision-ből akarjuk venni. Ehhez a következőt illesszük a pom.xml-be:&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;buildnumber-maven-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;
 &amp;lt;executions&amp;gt;
  &amp;lt;execution&amp;gt;
   &amp;lt;id&amp;gt;buildNumber&amp;lt;/id&amp;gt;
   &amp;lt;phase&amp;gt;validate&amp;lt;/phase&amp;gt;
   &amp;lt;goals&amp;gt;
    &amp;lt;goal&amp;gt;create&amp;lt;/goal&amp;gt;
   &amp;lt;/goals&amp;gt;
   &amp;lt;configuration&amp;gt;
    &amp;lt;doCheck&amp;gt;true&amp;lt;/doCheck&amp;gt;
    &amp;lt;doUpdate&amp;gt;true&amp;lt;/doUpdate&amp;gt;
   &amp;lt;/configuration&amp;gt;
  &amp;lt;/execution&amp;gt;
 &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Ekkor egyrészt lefuttat egy "svn status" parancsot, és ellenőrzi, hogy van-e módosított állomány. Majd egy "svn update" parancsot, és egy "svn info" parancsot. Ez alapján eltárolja a revision number-t a ${buildNumber} property-be, az aktuális timestamp-et a ${timestamp} property-be és a branch-et, amin vagyunk a ${scmBranch} property-be (ez lehet a trunk is). Ezeket a property-ket aztán a properties fájlba írva a Maven filter-eli.&lt;/p&gt;

&lt;p&gt;Furcsa mód amennyiben a formátumos megadást is használni akarjuk, akkor azt nem tudjuk itt konfigurálni, hanem fel kell venni egy újabb execution tag-et.&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;execution&amp;gt;
 &amp;lt;id&amp;gt;buildInfo&amp;lt;/id&amp;gt;
 &amp;lt;phase&amp;gt;validate&amp;lt;/phase&amp;gt;
 &amp;lt;goals&amp;gt;
  &amp;lt;goal&amp;gt;create&amp;lt;/goal&amp;gt;
 &amp;lt;/goals&amp;gt;
 &amp;lt;configuration&amp;gt;
  &amp;lt;buildNumberPropertyName&amp;gt;buildInfo&amp;lt;/buildNumberPropertyName&amp;gt;
  &amp;lt;format&amp;gt;Incremental build number {0}.{1} 
at {2,time} on {2,date}, build on build server {3}{4}, env var: {5}.&amp;lt;/format&amp;gt;
  &amp;lt;items&amp;gt;
   &amp;lt;item&amp;gt;buildNumber0&amp;lt;/item&amp;gt;
   &amp;lt;item&amp;gt;buildNumber1&amp;lt;/item&amp;gt;
   &amp;lt;item&amp;gt;timestamp&amp;lt;/item&amp;gt;
   &amp;lt;item&amp;gt;jupiter&amp;lt;/item&amp;gt;
   &amp;lt;item implementation=&amp;quot;java.lang.Integer&amp;quot;&amp;gt;8&amp;lt;/item&amp;gt;
   &amp;lt;item&amp;gt;${envVar}&amp;lt;/item&amp;gt;
  &amp;lt;/items&amp;gt;
 &amp;lt;/configuration&amp;gt;
&amp;lt;/execution&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Látható, hogy hogyan lehet megadni a formátumot a format tag-ben, és ekkor meg kell adni az items tag-et is, felsorolva a behelyettesítendő értékeket. A buildNumber/d* (ami azt jelenti, hogy a buildNumber szó, megtoldva egy egész számmal) azt fogja eredményezni, hogy létrejön egy buildNumber.properties állomány (helye, neve konfigurálható), és ebben fogja tárolni az aktuális verziót, és build esetén megnöveli egyel. Az előző példában két ilyen verziószámot növelget, és jegyez be ebbe az állományba. A timestamp-et is ki lehet írni, méghozzá formázva (még érdekesebb formátum pl. {0,date,yyyy-MM-dd HH:mm:ss}), valamint konstansokat is meg lehet adni. Ebbe az a jó, hogy akár egy Maven property-t is, ahogy az ${envVar} property mutatja. Ekkor a build-et a "mvn -D envVar=CI install" paranccsal indítva a CI szót fogja a formátumba behelyettesíteni. Ez azért jó, mert akár a build szerveren, a CI (pl. Hudson/Jenkins) is be tudja ezt külön-külön állítani.&lt;/p&gt;

&lt;p&gt;A fenti konfigurációval futtatva a build-et a következőt kapjuk:&lt;/p&gt;

&lt;p&gt;Incremental build number 1.1 at 23:50:06 on 2011.09.13., build on build server jupiter8, env var: CI.&lt;/p&gt;

&lt;p&gt;Ezt az értéket, ahogy a buildNumberPropertyName tag-ben láthatjuk, a ${buildInfo} property-be fogja eltenni (hogy ne üsse az előző ${buildNumber} proerty-t). Ezt a properties állományunkban a Maven megintcsak tudja filter-elni.&lt;/p&gt;

&lt;p&gt;Amennyiben ezeket az értékeket a MANIFEST.MF-ben is szerepeltetni akarjuk, a következőt kell a pom-xml-be írni a maven-jar-plugin konfigurációjánál:&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;archive&amp;gt;
...
 &amp;lt;manifestEntries&amp;gt;
  &amp;lt;Implementation-Build&amp;gt;${buildNumber}&amp;lt;/Implementation-Build&amp;gt;
 &amp;lt;/manifestEntries&amp;gt;
...
&amp;lt;/archive&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-6632348504802797991?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/6632348504802797991/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/09/verzioszam-megjelenitese-az.html#comment-form" title="5 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/6632348504802797991?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/6632348504802797991?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/09/verzioszam-megjelenitese-az.html" title="Verziószám megjelenítése az alkalmazásban" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>5</thr:total></entry><entry gd:etag="W/&quot;CUYDR3Y5fCp7ImA9WhdWF00.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-3165730631942130096</id><published>2011-09-11T03:02:00.002+02:00</published><updated>2011-09-11T03:06:16.824+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-11T03:06:16.824+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Módszertan" /><title>Branch-elés a fejlesztési munkafolyamatban</title><content type="html">&lt;p&gt;Miután tisztában vagyunk az verziókezelő eszközünk képességeivel, a munkafolyamatot kell meghatároznunk, hogyan illesszük be a branch-elést a munkafolyamatainkba, miket kell átgondolni, szabályozni. Én nem hiszem azt, hogy az eszköz nagyban befolyásolná azt, hogy miképpen dolgozunk, de ha mégis így van, lehet, hogy el kell gondolkoznunk az eszköz cseréjén. Megpróbálok most már nem Subversion közeli maradni, azonban pár dolog még mindig Subversion specifikus.&lt;/p&gt;

&lt;p&gt;A branch-elés nem költséges. Ezzel a kijelentéssel sokszor lehet találkozni. Valóban így van, de a branch-eléssel sok olyan dolog is a felszínre kerül, ami azonban mégis kényelmetlenebbé teszi a munkafolyamatot. Nézzük ezek közül egy párat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adminisztrálni kell, hogy melyik branch-ben éppen mi történik. Valamint ezt meg kell osztani a fejlesztőgárda tagjaival is, hogy tudják, mikor melyik ágba kell fejleszteni, mikor melyik ágból lehet új branch-t nyitni.&lt;/li&gt;
&lt;li&gt;Merge. Azt hiszem ez önmagáért beszél. Amennyiben módosításokat akarunk ágak között átvinni, nem egyszerű feladat. Persze, az újabb eszközök már támogatják, de gondoljunk csak a szemantikus conflict-okra.&lt;/li&gt;
&lt;li&gt;A branch-eket meg kell szüntetni, különben elburjánzanak, elszaporodnak, így nehéz követni, hogy melyikben éppen milyen fejlesztés folyik, melyikkel mi a cél. Sajnos gyakran előfordul, hogy az ágak annyira elcsúsznak egymástól, hogy a fejlesztőcsapatnak már esélye sincs a merge-re, így párhuzamosan fejlesztenek több ágat.&lt;/li&gt;
&lt;li&gt;Egy fejlesztő egyszerre több branch-en dolgozik, időbe és energiába telik a váltogatás (context switching), esetleg előfordulhat, hogy össze is keveri a branch-eket. Különösen problémás lehet egy mixed working copy esetén.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Elöljáróban néhány jó tanács. A munkafolyamataink megtervezésénél se essünk abba a hibába, hogy túltervezzük, minden lehetőségre felkészítjük őket. Tartsuk be a KISS, YAGNI alapelveket itt is. Ne akarjunk minden problémát megoldani, ne akarjuk a munkafolyamatot kőbe vésni. Javasolt kis lépésekben kell bevezetni, iterációkkal haladva előre. Amennyiben úgy tapasztaljuk, hogy a munkafolyamat nem megfelelő, módosítsunk, legyünk bátrak más megoldást választani. Ez így van a branch-ekkel is. Ha kialakítottunk egy konvenciót, és nem megfelelő, szervezzük át. A verziókezelő rendszerek erre nagyszerű eszközöket nyújtanak. Ennél a témakörben ráadásul gyakran azt vettem észre, hogy egymással teljesen ellentmondó igényekre akarnak a fejlesztők egységes munkafolyamatot kitalálni. Ismerjük fel ezeket, és hozzunk döntést. Amennyiben elakadtunk, vagy túl nagy falatnak érezzük, ne szégyelljünk segítséget kérni. Néha úgy fogjuk érezni, hogy hátraléptünk, hogy kényelmetlenebb a fejlesztési folyamat, de ez néha szükséges ahhoz, hogy tovább tudjunk lépni.&lt;/p&gt;

&lt;p&gt;Én nem hiszek a teljes automatizálásban. A fejlesztőknek igenis egymással kommunikálniuk kell. A Subversion csak egy eszköz a kommunikáció megkönnyítésére. Ezeket az eszközöket ne akarjuk a kommunikáció kiváltására használni. Nem javaslom a branch-ek automatikus létrehozását, automatikus merge-ök futtatását, release kiadást, deploy, stb. Én szeretem, ha mindenre van egy élő embernek is rálátása, és ami jól jöhet, felelőse is. Nem jó, ha ezek a nem egyszerű folyamatok a senki földjét képviselik. Különösen, ha nem fix, hanem alakítható munkafolyamatunk van, sosem jutunk el oda, hogy minden automatikusan történjen. Persze egyes részfolyamatok lehetnek automatizáltak.&lt;/p&gt;

&lt;p&gt;Igaz, hogy azt javaslom, hogy humán erőforrás felügyelje ezeket a műveleteket, azonban érdemes nem mindent rábízni. Tapasztalataim szerint nagyon sokat segít az, ha a leggyakoribb dolgokra előregyártott script-eket használunk. (Illetve a Maven is támogatást biztosít.)&lt;/p&gt;

&lt;p&gt;Kezdjük is az első problémával, hogy hogyan lehet megtudni, hogy melyik branch-en mi történik. Valójában a fejlesztés egyik első számú eszközének egy issue tracker-nek kell lennie. Én a JIRA-ban hiszek, bár egyre kevésbé, ahogy a belsejét is kezdjük megismerni. Ettől függetlenül az egyik legjobb eszköz, és bár fizetős, gyakran találkozhatunk vele, ugyanis ingyenes open source projektek számára, és kis cégek is rendkívül kedvező áron juthatnak hozzá. Ebben verziókat lehet felvenni, és a verziókhoz lehet rendelni az issue-kat. Különböző nézetekben lehet látni a verziók állását (nyitott/összes issue), a verziókhoz tartozó issue-kat, valamint kiadás esetén changelog-ot lehet generálni. A verziókhoz megjegyzéseket lehet hozzáfűzni. Tehát az issue tracker szolgálhat elsődleges információval a branch-ekről is.&lt;/p&gt;

&lt;p&gt;Egy kis közbevetés. A fejlesztőcsapattal, mikor arról beszélgetünk, hogy hogyan használjuk a munkafolyamatban a verziókezelőt, mindig valamilyen ábrákat rajzolunk, ahol a branch-eket rajzoljuk fel, a commit-okat, merge-öket, stb. Ahhoz, hogy megértsük egymást érdemes egységes jelölésrendszert kialakítanunk. Sajnálatos, hogy még nincs ilyen szabványosítva, ha a blogokat is olvasunk, mindenki saját jelölésrendszert használ erre.&lt;/p&gt;

&lt;p&gt;Egy &lt;a href="http://jtechlog.blogspot.com/2011/08/branch-eljunk-e-vagy-sem.html"&gt;előző post-ban&lt;/a&gt; már szó esett a continuous integration-ről, a feature vagy release branch-ek fogalmáról. Létezik köztes megközelítés is. Ilyenkor általában a trunk-ba mennek a javítások, csak a nagyobb fejlesztések, melyek több commit-ból állnak, és a commit-ok között inkonzisztensen hagyják a szoftvert, azokat szervezik külön branch-be. Ha feature branch-t indítunk nem feltétlenül érdemes feature-önként külön branch-et indítani, megfelelő lehet az is, ha a feature-öket csoportokba rendezzük, és egy csoporthoz indítunk egy branch-et. Egy ilyen csoport kap egy verziót, amit fel lehet venni az issue tracker-be, és a feauture-öket meg a verzióhoz rendelni.&lt;/p&gt;

&lt;p&gt;Tehát egy jó fejlesztési munkafolyamat leírás megmondja, hogy bizonyos helyzetekben mit kell tenni. Szabályokat kell hozni a következőkre:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hogyan kell szervezni a branch-eket?&lt;/li&gt;
&lt;li&gt;Ki hozhat létre branch-et?&lt;/li&gt;
&lt;li&gt;Mikor kell branch-et létrehozni?&lt;/li&gt;
&lt;li&gt;Honnan nyitható új branch?&lt;/li&gt;
&lt;li&gt;Hogyan kell a branch-eket elnevezni?&lt;/li&gt;
&lt;li&gt;Honnan hova történik a merge?&lt;/li&gt;
&lt;li&gt;Mikor, milyen gyakran történik a merge?&lt;/li&gt;
&lt;li&gt;Ki merge-öl?&lt;/li&gt;
&lt;li&gt;Mikor történik a branch törlése?&lt;/li&gt;
&lt;li&gt;Ki törli a branch-et?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Subversion specifikus, hogy a branch-eket hogyan érdemes szervezni. Az alap struktúra a /trunk, /branches, /tags könyvtárak használata. Lehet ezen variálni, de vigyázzunk, sok eszköz, köztük a Maven is default ezen a struktúrán dolgozik. Csinálhatunk külön alkönyvtárakat a release és feature branch-eknek. Csinálhatunk külön könyvtárakat a kiadás különböző stációi alapján, pl. QA, RC, beta, GA, stb.&lt;/p&gt;

&lt;p&gt;Láttam olyan működést is, ahol a branch-ek fejlesztőnként voltak. Ezt elfogadhatónak tartom egy open source projektnél, ahol bizonyos fejlesztők csak néha-néha néznek rá a projektre, és szabad akaratukból fejlesztenek. Komoly projektnél azonban szerintem nem jöhet szóba.&lt;/p&gt;

&lt;p&gt;A branch létrehozása történhet a projektvezető által szigorúan vezetett projekteknél. De nem mindig érdemes megszorítást adni, bizonyos projekteknél bármelyik fejlesztő nyithat új ágat. Sőt, lehetséges összekötni az issue tracker-rel is, amikor a verzió létrehozásakor implikálja a branch létrehozását. De akár létrehozhatja a CI eszköz is. Amennyiben azt akarjuk, hogy az új branch a CI-be is be legyen kötve, erről azt értesíteni kell. (A Jenkins REST interfészén keresztül pl. nagyon egyszerű más névvel egy projektet másolni, és az SVN URL-jét megváltoztatni.)&lt;/p&gt;

&lt;p&gt;Feature branch két esetben jöhet létre. Vagy a feature branch deklarálásakor, vagy akkor mikor a fejlesztő elkezdi a munkát. Release branch létrehozása természetesen a release során történik.&lt;/p&gt;

&lt;p&gt;Egy feature branch egészen kis módosítástól kezdve nagy változtatásokat is tartalmazhat. Ez a granularitás projektenként, de akár projekten belül is változhat. Történhet issue-nként, és akkor lehetőség van arra is, hogy egy release esetén össze lehessen válogatni a fejlesztéseket. Ennek előnye a maximális flexibilitás, hátránya azonban az overhead, hiszen sok branch-et kell kezelnünk. Ekkor a branch-et egy issue-val kell azonosítanunk. Másik módszer, ha egy branch több fejlesztést is tartalmaz, melyet verziószámmal tudunk azonosítani. Előző &lt;a href="http://jtechlog.blogspot.com/2011/09/subversion-branch-akar-maven-release.html"&gt;post-ban&lt;/a&gt; láthattuk, hogy a Maven, valamint a Maven Release plugin támogat minket ebben. Mindenképpen javasolt valami verziószám konvenciót alkalmazni. Leggyakoribb a hármas tagolású, ahol az elsőt akkor változtatjuk, ha API szintű változás van, a másodikat, ha API-t nem érintő funkcionális változás van, és a harmadik, ha bugfix-et adunk ki.&lt;/p&gt;

&lt;p&gt;Ahhoz, hogy dönteni tudjunk, ismerni kell a projektet. Az issue-nkénti branch jól jöhet akkor, ha időzítve vannak a kiadásaink, és nem tudjuk, hogy egy kiadásra melyik feature készül el. Prioritások változhatnak, az issue fejlesztése indításakor még fontosnak tűnt, de közben beelőzhet pár fontosabb issue. Az issue-ink elkészülési ideje nem jósolható meg, vagy a szoftver bonyolultsága, vagy a megrendelő megbízhatósága, vagy a fejlesztőcsapat tapasztalatlansága miatt. Így egy verzióban azok lesznek kiadva, melyek fontosnak tűnnek és elkészülhetnek. Amennyiben azonban a projektünk olyan, hogy egy iteráció kezdetén eldönthető, hogy mely issue-k lesznek a verzióban, és addig nem megy ki a verzió, míg mind készen nincs, akkor érdemes verziónként branch-elni.&lt;/p&gt;

&lt;p&gt;A branch a release vagy feature branch esetén legtöbbször a trunk-ból nyitható.&lt;/p&gt;

&lt;p&gt;Akár issue, akár verzió alapján branch-elünk, a branch neve mindig utaljon erre.&lt;/p&gt;

&lt;p&gt;Tag-eket is használnunk kell, amennyiben helyes fejlesztési folyamatot akarunk felépíteni. Gyakori tag pl. a nightly build. Vagy készíthetünk egy tag-et, ami mindig a legutolsó nightly build-re mutat. Ez mindig törölhetjük és újra létrehozhatjuk, de jobb megoldás az svn:externals használata. Természetesen tag-eket használni kell release estén is. (Ezt a Maven release plugin automatikusan elvégzi helyettünk.)&lt;/p&gt;

&lt;p&gt;És akkor a merge-ről. A feature branch, release branch esetén az előző post-ban leírásra került, hogy hova történik a merge. A merge-öt érdemes minél gyakrabban elvégezni úgy, hogy még nem zavarja a fejlesztési munkafolyamatot. Ebben az esetben azonban arra is kell figyelni, hogy a branch-ben gyakran, apróbb részletekben commit-oljunk, hiszen csak ekkor garantálható, hogy a merge is kis részletekben történik. Minél ritkábban van merge, annál nagyobb az esélye, hogy a két ág szétcsúszik, és nő a conflict veszélye. Én előnyben részesítem, ha egy branch-nek van egy felelőse, és ő végzi a merge-ölést. Ő tisztában van a branch keletkezési körülményeivel, céljaival, a benne folyó fejlesztésekkel. Ha conflict van, akkor ő végzi el a merge-öt. Azonban kijelölhető egy másik személy is, aki a merge-öt végzi, vagy akár egy automata is lehet. Ha conflict-hoz ér, a következők közül választhat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Megkeresi a hozzáértő szakembert&lt;/li&gt;
&lt;li&gt;Legjobb tudása szerint feloldja az ellentmondást, és körbeküldi, hogy van-e valakinek kifogása&lt;/li&gt;
&lt;li&gt;Egyből körbeküldi a hibát, és várja a megoldást&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Amikor a branch-ben szereplő fejlesztés kiadásra került, a branch törölhető. Ez akár a release része is lehet. Törölheti a release, vagy a branch felelőse, vagy egy fejlesztési munkafolyamatért felelős más személy. Ehhez is lehet, hogy extra műveleteket is el kell végezni, pl. job megszüntetése a CI-ben.&lt;/p&gt;

&lt;p&gt;Ami még egy dolog, ami a branch-hez tartozik (és ígérem, hogy utoljára írok erről), hogy a verziókezelőben hogyan érdemes több összetartozó projekt esetén a hierarchiát szervezni. Erről is szó került már egy &lt;a href="http://jtechlog.blogspot.com/2010/10/release-maven-nel-es-hudson-nel.html"&gt;előző post-ban&lt;/a&gt;. Első eset, mikor a /branches, /tags és /trunk könyvtárak alá helyezzük a projektjeinket. A második, mikor minden projektnek van ez a három alkönyvtára. Mindegyiknek van előnye és hátránya. Sőt, a kettőt keverni is lehet, hogy bizonyos projekteket így, bizonyos projekteket úgy szervezünk. Az első eset akkor jó, ha együtt mozognak a projektek verziói, azaz pl. egyszerre történik a release. Azonban ha külön akarjuk választani a verziókat, akkor onnantól kezdve bajban vagyunk. Ha később külön akarjuk választani a projekteket, az sem egyszerű. Jogosultságot megadni csak egy projektre sem egyszerű. A második megoldással azonban mindent meg lehet valósítani, de ha egyszerre akarunk pl. tag-geli, sokkal nehezebb. Erre van egy &lt;a href="http://svn.apache.org/repos/asf/subversion/trunk/tools/client-side/svnmucc"&gt;svnmucc&lt;/a&gt; nevezetű eszköz, mely lehetővé teszi, hogy egy műveletet több URL-en is végre tudjunk hajtani, egy commit-on belül.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-3165730631942130096?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/3165730631942130096/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/09/branch-eles-fejlesztesi.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/3165730631942130096?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/3165730631942130096?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/09/branch-eles-fejlesztesi.html" title="Branch-elés a fejlesztési munkafolyamatban" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CU4NRnwyfip7ImA9WhdWE0g.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-3931037512697146491</id><published>2011-09-07T02:02:00.002+02:00</published><updated>2011-09-07T02:06:37.296+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-07T02:06:37.296+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Subversion" /><category scheme="http://www.blogger.com/atom/ns#" term="Módszertan" /><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><title>Subversion branch, akár Maven Release plugin-nal</title><content type="html">&lt;p&gt;Technológiák: Subversion 1.6, Maven 3.0.3, Maven Release Plugin 2.0&lt;/p&gt;

&lt;p&gt;Amennyiben mégis amellett döntünk, hogy branch-elni (, és ennek következtében merge-ölni is) fogunk, rengeteg szempontot kell figyelembe venni. Hogyan működik a branch-elés, milyen szabályokat kell és milyen best practice-eket érdemes betartani, hogyan illeszkedik a fejlesztési munkafolyamatba, stb. Bár sok helyen használják, kevés helyen láttam ezek használatát kellően (teljes körűen) leszabályozva, dokumentálva, és bevetve. Nincsenek konvenciók, nem egységes a használata, nehéz beszerezni az információt, hogy honnan kell leágazni, kallódó, már senki által nem karbantartott és ismert branch-ek vannak. Ez a post ismerteti az alapfogalmakat, a Subversion lehetőségeit, valamint hogyan illeszthető a branch-elés a Maven-es munkafolyamatainkba, és milyen problémába ütközhetünk, és oldhatjuk meg. Ez a post előkészíti a post-ot, ami abban próbál majd segíteni, hogy felállítsunk egy szabályrendszert, megpróbál rávilágítani a lehetőségekre, előnyeikre/hátrányaikra, hogy miket kell szem előtt tartani, hogy a fejlesztési munkafolyamatunkat tökéletesítsük, gyakorlatilag best practice-eket ad.&lt;/p&gt;

&lt;p&gt;Mivel azt látom, hogy jelenleg a Subversion a legelterjedtebb verziókezelő rendszer, így erről fogok írni. Bizonyos dolgok mások, bizonyos dolgok egyszerűbbek elosztott verziókezelő rendszer (pl. GIT, Mercurial, stb.) esetén. Abban bízom, hogy az itt (, de inkább a következő post-ban) leírt dolgok egy része azért ott is felhasználható.&lt;/p&gt;

&lt;p&gt;Bár Subversion parancsokat parancssorból kiadni menő, azért néha szóba hozom a &lt;a href="http://tortoisesvn.tigris.org/"&gt;TortoiseSVN&lt;/a&gt; klienst is, ami azon szinte megbocsájthatatlan hibáján kívül, hogy a Windows Explorer-be épül, az egyik legjobb kliens. Próbáltam Subversion-t használni mind NetBeans, mind Eclipse IDE-kből is, de valahogy mindig csak bajom volt vele, sokszor a galibát csak TortoiseSVN-nel tudtam rendbetenni.&lt;/p&gt;

&lt;p&gt;A branch nem más, mint egy új fejlesztési ág, mely már független attól, melyből kinőtt, mégis közös a történelmük. A Subversion-ben a branch (és a tag) létrehozása is egy egyszerű másolás (copy), ebben rejlik az egyszerűsége. A mantra, amit mondogathatunk magunkba, hogy a branch-elés (technikailag) nem költséges. Nem lesz tőle nagyobb a repository, nem fog belassulni, stb. Unix hasonlattal élve, valójában egy hard link létrehozásának felel meg. Azért olcsó csak technikailag, mert az erőforrásigény csak a fejlesztési munkafolyamatba illesztésnél, projekt adminisztrációnál, és a rettegett merge-nél fog megjelenni.&lt;/p&gt;

&lt;p&gt;A branch és merge az 1.5-ös Subversion előtt nagyon problémás. Ennek használatát mindenképp el kell kerülni, érdemes a legfrissebb, 1.6-os verzióval dolgozni, mind szerver, mind kliens oldalon. (Annak megakadályozására, hogy 1.5 előtti klienssel használjuk a Subversion szervert, ezzel veszélyeztetve a merge-höz szükséges adatokat, egy commit hook is telepíthető.) Az 1.5-ös verzióban jelent meg ugyanis a mergeinfo, mely nagyon hasznos a merge-ök nyomon követésénél. Az svn:mergeinfo gyakorlatilag egy közönséges property. Bár lehetőség van rá, lehet kézzel is szerkeszteni, de ez meglehetősen ellenjavalt, hagyjuk a kezelését a merge parancsra.&lt;/p&gt;

&lt;p&gt;A témában az egyik legjobb olvasmány a &lt;a href="http://svnbook.red-bean.com/"&gt;Version Control with Subversion&lt;/a&gt; könyv, mely ingyenesen elérhető. Ez a changeset elnevezést használja, és már az elején definiálja is, ugyanis sokféleképpen szokták ezt a fogalmat használni. A könyv terminológiájában a changeset az változások halmaza (ahol a változás lehet egy állományban történt változás, de akár egy állomány törlése, vagy átmozgatása is), mely egy nevet kap. Subversion-ben minden commit egy külön azonosítót kap (revision), ami gyakorlatilag szintén egy changeset, de implicit névvel, hiszen a verziókövető rendszer adja. A merge legkisebb egysége a changeset.&lt;/p&gt;

&lt;p&gt;A klasszikus használati mód a következő. Elindul a fejlesztés a fősodron, és kiderül, hogy szükség van egy branch-re. Ekkor az svn copy-val (másolással) gyakorlatilag létrehozzuk az új ágat. Mivel a főágon is folyik a fejlesztés, ezt bizonyos időközönként át kell hozni a módosításokat. Ezt már a merge paranccsal tudjuk elvégezni. A Subversion automatikusan karbantartja a mergeinfo property-t is, amibe bekerül, hogy mely revision-ök kerültek már át. Tehát egy újabb merge esetén tudja, hogy mik kerültek már át, és amelyek nem, azokat a módosításokat gyakorlatilag lejátssza az új ágon is. Az állományokat lokálisan módosítja, szóval itt lehet fordítani, tesztelni, és ha minden helyes, akkor lehet commit-olni. Amennyiben vissza akarjuk a branch-ben történt módosításokat vezetni a főágra, először mindenképpen ellenőrizzük, hogy a főág módosításai átkerültek-e, majd a merge-öt a --reintegrate kapcsolóval kell kiadni. Itt a működés teljesen más, ezért kell a --reintegrate kapcsolót használni, ugyanis a branch-en találhatók saját fejlesztések, valamint a főágon történt merge-ök is. Ennek a kapcsolónak a használatával valójában összehasonlítja a két ágat, és a különbséget próbálja a főágra rájátszani. (A merge kiadható a --dry-run kapcsolóval is, ekkor nem módosulnak az állományok, csak egy áttekintést kapunk, hogy mely állományok hogyan módosulnának.) Ha ez megvan, akkor ezt is lehet commit-olni, majd az új ágat törölni lehet.&lt;/p&gt;

&lt;p&gt;Ez a klasszikus eset, azonban fejlesztés közben ez nagyon ritkán ilyen egyszerű. Először is sokszor van conflict. Ez az, mikor a két ágon olyan változás történik, ami látszólag ellentmond egymásnak. A Subversion amúgy is híresen rosszul kezeli ezeket az elosztott verziókezelőkhöz képest. És ráadásul még ott van az előző &lt;a href="http://jtechlog.blogspot.com/2011/08/branch-eljunk-e-vagy-sem.html"&gt;post&lt;/a&gt;-ban említett szemantikus ütközés is, amikor fordulni fordul ugyan a módosított projekt, azonban nem fog helyesen működni.&lt;/p&gt;

&lt;p&gt;Különösen átnevezésekkel van gond. Ugyanis a Subversion átnevezése effektív egy copy, majd egy delete, és nem őrzi meg az információt, hogy ez valójában egy átnevezés volt. Képzeljük el, hogy egy külön ágon javítunk egy állományon, míg a főágon egy mozgatást hajtunk végre. Mikor ezt a külön ágra akarjuk merge-ölni, az eredeti állományt letörli, és az újat hozzáadja. Csak közben elveszik a külön ágon történt javítás. A könyv szerint, amíg ezen nem javítanak, óvatosan merge-öljünk átnevezést.&lt;/p&gt;

&lt;p&gt;Amúgy a könyv a merge parancsra azt mondja, hogy jobb lenne diff-and-apply-nak hívni, mert semmi bűvészkedés nincs a háttérben, a merge összehasonít két ágat, és a különbséget a working copy-ra alkalmazza.&lt;/p&gt;

&lt;p&gt;Ezen eszközökkel haladóbb feladatokat is el tudunk végezni. Pl. ha egy revision-ben hibás kódot commit-oltunk, vissza tudjuk ezt vonni, méghozzá a reverse merge használatával (-c kapcsolóval). Persze a history-ban megmarad, de legalább automatikusan megtörténik az "undo" művelet. Ez TortoiseSVN-ben is megtalálható, bár nem utal a reverse merge-re: Revert changes from this revision menüpont. Ebben az esetben nem keletkezik vagy módosul a mergeinfo.&lt;/p&gt;

&lt;p&gt;Törölt elemet is vissza lehet állítani a merge-gel, azonban javasolt inkább a copy parancs használata, hiszen ha egy revision-ben más is történt a törlésen kívül, akkor az is visszajátszásra kerül, míg a copy esetén kedvünkre tudunk válogatni.&lt;/p&gt;

&lt;p&gt;A cherrypicking szintén egy haladó fogalom, magyar fordításban mazsolázásnak, csemegézésnek, szemezgetésnek lehetne fordítani. (A &lt;a href="http://plastik.hu/2011/08/24/heti-meteor-6/"&gt;Heti Meteor #6&lt;/a&gt;-ban is előjött a téma, teljesen más kontextusban.) Verziókezelés terén ez gyakorlatilag azt jelenti, hogy én egyenként kiválogatom, hogy milyen módosításokat szeretnék merge-ölni az egyik ágról a másik ágra. Ez Subversion esetén annyit tesz, hogy egy vagy több revision-re tudom megmondani, hogy annak a módosításaival történjen a merge (elég bonyolult feltételeket, intervallumokat fogalmazhatok meg). Ez különösen fontos akkor, ha a másik ágon folyik egy hosszabb fejlesztés, de közben egy bug-ot is kijavítottak, amit érdemes áthozni az én ágamba is. Persze ez is eltárolásra kerül a mergeinfo-ban, így ha később az ágban lévő többi módosítást is merge-ölni akarjuk, akkor ezt a revision-t automatikusan átugorja. Itt azonban lehet egy probléma, méghozzá egy revision intervallum közepén lévő merge két intervallumra bontja a módosításokat. Ha ez elsőben elhal a merge conflict-tal, és elhalasztjuk a conflict feloldását, a teljes merge elhal. Ez lehet, hogy későbbi Subversion verziókban javítják, de addigis két részletben kell ilyenkor merge-ölnünk.&lt;/p&gt;

&lt;p&gt;Egy kicsit bővebben a mergeinfo-ról. Egy normál merge esetén létrejön vagy módosul ez a property, azonban vannak esetek, mikor mégsem. Ez lehet akkor, ha a forrás és cél URL nincs egymással kapcsolatban, azaz nincs közös history-juk. Ugyanez van akkor is, ha másik repository-ból merge-ölünk. A mergeinfo-t a TortoiseSVN-nel a Properties menüponttal tudjuk megnézni, nincs rá külön menüpont, hiszen standard property. Ezt amúgy az Subversion explicit mergeinfo-nak nevez. Az implicit mergeinfo nem más, mint a közös history. Ez annyit jelent, ha a közös history-ban lévő módosítást akarunk merge-ölni, akkor a Subversion tudja, hogy semmit nem kell tennie, hisz a közös history miatt a módosítás mindkét ágon benne van.&lt;/p&gt;

&lt;p&gt;A merge tehát figyelembe veszi a history-t. Képzeljünk el egy esetet, ahol az egyik ágon törlünk egy állományt, commit, majd újra hozzáadjuk, és commit. Ebben az esetben az első és második módosításban szereplő állományoknak nincs közös history-ja. Ekkor a merge is törölni, majd hozzáadni fog. Abban az esetben, ha a --ignore-ancestry kapcsolót használjuk, a history-t nem veszi figyelembe a merge, úgy működik, mint egy szimpla diff. Ekkor sem keletkezik vagy módosul a mergeinfo.&lt;/p&gt;

&lt;p&gt;Ha megvizsgáljuk a merge parancsot, három paramétert lehet átadni. Initial repository tree, hasonlítás jobb oldalának is hívják. A final repository tree, a hasonlítás bal oldalának is hívják. A working copy, ahova az összehasonlítás eredményeként előállt diff rá lesz módosítva. Ezzel a paraméterezéssel nagyon vigyázzunk, hisz olyan tree-ket is megadhatunk, aminek semmi köze nincs egymáshoz, ennek az eredménye nagy kavarodás lehet. A könyv még azt is javasolja, hogy a merge-öt mindig a branch főkönyvtárán hajtsuk végre, ne alkönyvtárakon.&lt;/p&gt;

&lt;p&gt;A TortoiseSVN ezt úgy oldja meg, hogy mikor merge-ölni akarunk, megkérdezi, hogy mit szeretnénk.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Merge a range of revisions&lt;/li&gt;
&lt;li&gt;Reintegrate a branch&lt;/li&gt;
&lt;li&gt;Merge two different trees&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ez alapján a fenti paraméterezések helyett csak nekünk kell választanunk, hogy melyiket szeretnénk.&lt;/p&gt;

&lt;p&gt;Mint később látni fogjuk, a --record-only kapcsoló nagyon hasznos lehet. Ezzel ugyanis egy változásra azt mondhatjuk, hogy nem akarjuk, hogy a merge figyelembe vegye. Gyakorlatilag ekkor az történik, hogy a mergeinfo módosul, mintha a kiválasztott módosítás már be lenne merge-ölve (konkrétan behazudjuk a merge-t). Ezért a következő merge ezt ki fogja hagyni.&lt;/p&gt;

&lt;p&gt;Ha branch-ekkel dolgozunk, hasznos lehet a switch parancs használata, mellyel a working copy-t tudjuk update-elni egy másik URL-re. Azaz megadunk egy másik branch-et, és a working copy-nk átáll arra. Pl. jól jöhet akkor, ha fejlesztünk, és rájövünk, hogy ez akkora módosítás, hogy érdemes lenne branch-be tenni. Akkor létrehozzuk a branch-et, át-switch-elünk rá, majd oda történhet a commit. Mivel ez alkönyvtárra is működik, tudunk un. mixed working copy-t is csinálni, ahol az egyik könyvtár az egyik branch-et, a másik könyvtár a másik branch-et tartalmazza. Ezzel egyrészt nagyon vagány dolgokat is meg lehet csinálni, viszont rettenetesen be tud kavarni egy merge esetén. Javaslom, hogy kerüljük ilyenkor a mixed working copy használatát, azaz olyan working copy-val dolgozzunk, melynek minden eleme ugyanahhoz az időpontbeli állapothoz tartozik.&lt;/p&gt;

&lt;p&gt;A tag létrehozása nem sokban különbözik a branch-től, hiszen itt is egy másolás történik, valójában egy pillanatnyi állapot (snapshot), mely egy egyedi nevet kap. A revision is egy ilyen snapshot, azonban számmal azonosított. Konvenció szerint a projekt alá érdemes létrehozni a trunk, tags és branches könyvtárat, tartalmuk értelemszerű. A TortoiseSVN szól is, ha a tags-be akarunk commit-olni. Ezt ugyan lehet, hiszen a Subversion nem különbözteti meg a tag és branch fogalmát, azonban mégis jó, ha betartjuk a konvenciókat.&lt;/p&gt;

&lt;p&gt;Ezen ismeretekkel már meg lehet valósítani az előző &lt;a href="http://jtechlog.blogspot.com/2011/08/branch-eljunk-e-vagy-sem.html"&gt;post-ban&lt;/a&gt; említett feature és release branch-eket.&lt;/p&gt;

&lt;p&gt;A könyv megemlíti a vendor branches fogalmát is. Ezt akkor használhatjuk, ha egy 3rd party library-t patch-elünk, de szeretnénk mindig a módosításokat rávezetni, de a mi módosításunkat nem akarjuk kiadni (persze, ha a licence engedi). Ekkor importáljuk saját repository-ba a 3rd party library-t. Módosítjuk. Amint a 3rd party library-ból kijön egy következő verzió, merge-el vezetjük rá a változásokat, annak a repositry-jából. Így egyrészt a saját módosításaink is megmaradnak, valamint a verziókat is tudjuk emelni.&lt;/p&gt;

&lt;p&gt;Ahhoz azonban, hogy a post-nak valami köze legyen a Java-hoz is, belekeverem a Maven-t is, pontosabban annak &lt;a href="http://maven.apache.org/plugins/maven-release-plugin/"&gt;Release Plugin&lt;/a&gt;-ját, ami ugyanis a &lt;a href="http://maven.apache.org/plugins/maven-release-plugin/branch-mojo.html"&gt;release:branch céllal (goal)&lt;/a&gt; remekül tud branch-elni is, nem csak release-elni, mint egy &lt;a href="http://jtechlog.blogspot.com/2010/10/release-maven-nel-es-hudson-nel.html"&gt;előző post-ban írtam&lt;/a&gt;. Ez a cél igen jól paraméterezhető, de az alapbeállításokkal is el lehet boldogulni. A kötelező paramétere a branchName, amivel a branch nevét kell megadni. Amennyiben ezt nem adjuk meg, a következő hibaüzenetet kapjuk:&lt;/p&gt;

&lt;pre&gt;
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.0:branch (default-cli) on project acltuto
rial: The parameters 'branchName' for goal org.apache.maven.plugins:maven-release-plugin:2.0:branch are missing or inval
id -&gt; [Help 1]
&lt;/pre&gt;

&lt;p&gt;Adjuk meg tehát a branch nevét! Tartsuk észben, hogy ezzel a paraméterezéssel létrejön egy branch (copy a branch-es könyvtárba), melyben lévő projekt az &lt;emp&gt;aktuális verziószámot&lt;/emp&gt; fogja tartalmazni, és a working copy verziószáma fog emelkedni.&lt;/p&gt;

&lt;pre&gt;
mvn release:branch -DbranchName=my-branch
&lt;/pre&gt;

&lt;p&gt;A következő dolgok fognak megtörténni. A paraméterek alapértelmezettek, azaz updateBranchVersions=false, updateWorkingCopyVersions=true.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Megvizsgálja, hogy nincs-e lokális módosítás, mely nem lett commit-olva. Ha van, hibaüzenettel leáll (Cannot prepare the release because you have local modifications).&lt;/li&gt;
&lt;li&gt;Megkérdezi, hogy mi legyen a working copy új verziószáma. (Persze ezt parancssorban is meg lehet adni, ha nem interaktív módot akarunk.)&lt;/li&gt;
&lt;li&gt;Módosítja a pom.xml-ben a scm helyét, hogy a branch-re mutasson.&lt;/li&gt;
&lt;li&gt;Commit-olja a pom.xml-t. A commit comment szövege: [maven-release-plugin] prepare branch my-branch&lt;/li&gt;
&lt;li&gt;Végrehajtja a branch-et. A commit comment szövege: [maven-release-plugin]  copy for branch my-branch&lt;/li&gt;
&lt;li&gt;Megemeli a pom.xml-ben a verziószámot, és visszaállítja a scm helyét.&lt;/li&gt;
&lt;li&gt;Commit-olja a pom.xml-t. A commit szövege: [maven-release-plugin] prepare release my-branch
&lt;/ol&gt;

&lt;p&gt;Amennyiben azonban azt akarjuk, hogy a branch-ünk verziószáma ugorjon, viszont a working copy verziószáma maradjon, a következő parancsot adjuk ki:&lt;/p&gt;

&lt;pre&gt;
mvn release:branch -DbranchName=my-branch -DupdateBranchVersions=true -DupdateWorkingCopyVersions=false
&lt;/pre&gt;

&lt;p&gt;Ekkor a folyamat hasonló, mint az előbb, csak a working copy új verziószáma helyett a branch verziószámát kéri be a 2. lépéseben, és a pom.xml-ben is átírja a verziószámot. Ebben az esetben a 6. lépésben nem emel verziószámot, csak az scm helyét állítja vissza.&lt;/p&gt;

&lt;p&gt;Meg lehet adni azt is, hogy mindkét verziószám változzon, mindkét property igazra állításával.&lt;/p&gt;

&lt;p&gt;És valójában itt jön a feketeleves. Amennyiben van két fejlesztési águnk, és mindkettőn folyamatosan fejlesztünk, és adjuk ki a verziókat, mindkét ágon a release során változnak a pom.xml-ek, kizárólag az scm url-ek és a verziószámok. Amennyiben merge-ölni akarunk, a pom.xml-ek conflict-olni fognak, hiszen külön vezettük a verziószámokat mindkét ágon. Ez a conflict azonban a fejlesztési munkafolyamatunkba nem illik bele, hiszen nem akarunk pom.xml-ekben verziószámot szerkesztgetni, az kizárólag release során a release plugin feladata. Azaz ennek a merge-nek úgy kell lefutnia, hogy a pom.xml-ekben a verziószám változásokat ne vegye figyelembe.&lt;/p&gt;

&lt;p&gt;Itt vethetjük be a Subversion --record-only kapcsolóját. Nem kell mást csinálnunk, mint azokra a revision-ökre, melyekben a pom.xml-ben csak a verziószám változott, lefuttatni a merge-öt a --record-only kapcsolóval. Így gyakorlatilag becsapom a Subversion-t, a mergeinfo-ba bekerül, hogy ezen revision-ök már merge-ölve lettek. És a következő merge-nél már nem lesz conflict a pom.xml-re. Ettől függetlenül az olyan pom.xml változások, melyek lényegi részt érintenek, és nem a csak a release plugin által szerkesztett verziószámot, pl. dependency, stb., merge-ölésre kerülnek. Erre a problémára könnyű script-et is írni, hiszen a release plugin mindig úgy commit-ol, hogy a commit message-be szerepel a [maven-release-plugin] szó, valamint konfigurálhatunk saját commit message-eket is, így ezekre lehet szűrni, és rájuk futtatni a merge-öt --record-only kapcsolóval.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-3931037512697146491?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/3931037512697146491/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/09/subversion-branch-akar-maven-release.html#comment-form" title="2 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/3931037512697146491?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/3931037512697146491?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/09/subversion-branch-akar-maven-release.html" title="Subversion branch, akár Maven Release plugin-nal" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;D0cBSH88fSp7ImA9WhdRGEk.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-5347349015396857015</id><published>2011-08-09T01:03:00.003+02:00</published><updated>2011-08-09T01:10:59.175+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-09T01:10:59.175+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Módszertan" /><title>Branch-eljünk-e vagy sem?</title><content type="html">&lt;p&gt;Amíg a szoftverfejlesztés az elején tart, nem adtunk még ki verziót, a folyamat legtöbb esetben lineáris, egy kódbázison dolgozunk, minden fejlesztő ugyanazt látja. Bizonyos esetekben ez így is marad, és sorban fejleszthetjük bele az adott funkciókat, adhatunk ki újabb verziókat. Sajnos azonban ez a legtöbb esetben nem elegendő, így előbb-utóbb szükség lehet eltérni a fősodortól, és párhuzamos fejlesztéseket végezni, elágazunk, branch-et képzünk. Remélhetőleg a legtöbb helyen már rendelkeznek valamilyen verziókezelő eszközzel, mely képes állományokat, és ezek összességét véve a teljes projektet (forrás, erőforrás állományok, script-ek, dokumentáció) hisztorikusan tárolni, ezzel segítve a változások nyomon követését, ki, mikor, mit módosított. Sajnos munkám során láttam olyan fejlesztőcsapatot, ahol még mindig megosztott meghajtókon tárolják a projektet. A fejlesztési munkafolyamatot, a branch-ek kezelését és a fejlesztők közötti kollaborációt pedig ezen eszközök emelik egy magasabb szintre.&lt;/p&gt;

&lt;p&gt;A fő fejlesztési sodor a mainline, melyen a fő fejlesztés történik. Branch-re több esetben is szükség lehet. A klasszikus példa, mikor kiadjuk az 1.0 verziót, elkezdjük a 2.0-ás verzió fejlesztését, és közben derül ki, hogy az 1.0-ás verzióban hibák vannak, melyre az ügyfél azonnali javítást vár, és nem várja meg a 2.0-ás verzió kifejlesztését. Ekkor elágazhatunk az 1.0-ás verziónál, és létrehozhatunk egy külön branch-et az 1.1-es verziónak, mely a hibajavítást fogja tartalmazni. A példán máris látszik, hogy később szükséges lesz a hibajavítás visszavezetése a 2.0-ás verzióba is. Ez a merge, mely során az egyik branch módosításait kell átvezetni egy másik branch-be, jelen esetben a mainline-ba. A jelenlegi eszközök a branch-ek elkészítését nagymértékben támogatják, általában egy parancs, azonban a merge már sokkal problematikusabb művelet.&lt;/p&gt;

&lt;p&gt;Az előbbi használati eseten (, amit nevezzünk bug-fix branch-nek) kívül is szükség lehet branch-ek használatára. Mostanában egyre divatosabb a feature branch-ek és release branch-ek használata, a branch-ek nagymértékű elszaporodása. A feature branch esetén a fejlesztők minden egyes szoftver funkciót (feature, de nevezik story-nak is) külön ágon fejlesztenek. Ezen funkciók lehetőleg legyenek egy jól körülhatárolható és azonosítható egységek, pl. bugtracker issue-k, de láttam már olyant is, hogy mivel ezek túl kis egységek voltak (granularitás), ezeket összefogták nagyobb egységekbe. (Direkt nem nevezném külön verziónak, később kiderül, miért.) Egy feature branch-en egy vagy több fejlesztő is dolgozhat. Amíg a funkció el nem készül, a fejlesztés ezen a branch-en folyik, és párhuzamosan mellette más feature branch-eket is lehet fejleszteni. Amikor egy feature branch elkészül, ez visszavezetésre kerülhet a fősodorba, és kiadható.&lt;/p&gt;

&lt;p&gt;Ez az elmélet, de a használat során felmerülnek kérdések. Egyrészt miért is hasznos, miért nem a fősodorban történik a fejlesztés? A feature branch használatával ugyanis egy adott időpillanatban választhatunk, hogy mely funkciók állnak készen, melyikeket lehet kiadni. Ez a klasszikus szoftverfejlesztéssel, ahol is előre kitűzzük a verziószámokat, és hogy abban milyen funkciók lesznek elérhetőek (, maximum kicsit sakkozunk közöttük) teljesen ellentétes, hiszen itt a következő verzió azokat a fejlesztéseket fogja tartalmazni, amik készen vannak. A funkciók ilyen szintű összeválogatását nevezzük cherry-picking-nek. Ezért nem kell a branch létrehozását verzióhoz kötni. Sok helyen történik ilyen típusú fejlesztés, általában ott, ahol bizonyos okok miatt (politikai indokok, megrendelői bizonytalanság, fejlesztőcsapat képzettsége, stb.) a funkciók kifejlesztésének erőforrásigénye nem kalkulálható, vagy a különböző funkciók szintén ugyanilyen okokra visszavezethetően előzgethetik egymást (pl. épp melyik osztály az erősebb a megrendelőnél). A funkciók külön ágon készülnek, egymást nem zavarják, bármikor bármelyiket be lehet hozni. A probléma természetesen itt is az lesz, hogy mi van akkor, ha két branch módosításait kell összevezetni. Ilyenkor ismét merge-ölni kell.&lt;/p&gt;

&lt;p&gt;Abban az esetben, ha több feature branch-et szeretnénk egy release-be összevonni, akkor az integráció, a merge akár hosszabb folyamat is lehet. Ilyenkor az integrációval akár meg is akaszthatjuk a fő fejlesztést, ha azt a mainline-on végezzük. Ilyenkor szokták bevetni a release branch fogalmát. A release branch-en történik a merge, valamint történhet a tesztek, akár QA tesztek elvégzése is. És amikor ez sikeresen befejeződik, csak ekkor kerülnek vissza a módosítások a mainline-ba. Ezzel a fősodorban mindig az aktuálisan működő, kitesztelt verziónk lesz, melyből biztonságosan le lehet ágazni, és nem kell kérdezni, hogy egy új fejlesztés (branch nyitása) most honnan történjen.&lt;/p&gt;

&lt;p&gt;Ez a fejlesztési folyamat elsőre tökéletesnek tűnhet, de az ördög a részletekben lakozik. Jelen esetben a merge-ben. Amennyiben mindkét ágon módosítás történik, akkor ütközés léphet fel (conflict). Ez szöveges állomány esetén, ha külön sorokban történt a módosítás, egész könnyen, automatikusan kezelhető. Ellenkező esetben humán beavatkozás szükséges. A kezdeti verziókezelők viszont már azt sem tudták kezelni, ha az egyik ágon egy állományban módosítás, a másik ágon ugyanazon állománynak az átnevezése történt. Szerencsére a modern verziókezelőknek ez már nem jelent problémát, hiszen a merge során felhasználják azt az információt is, hogy átnevezés történt. A probléma &lt;a href="http://martinfowler.com/"&gt;Martin Fowler&lt;/a&gt; által elnevezett &lt;a href="http://martinfowler.com/bliki/SemanticConflict.html"&gt;szemantikai ütközéssel&lt;/a&gt; van. Mivel ő a refactoring atyja, ilyen példával a legkönnyebb magyarázni. Az egyik ágon egy refactoring, egy metódus átnevezés történik, a másik ágon meg bevezetésre kerül újabb metódushívás még a régi névvel. A merge során azonnal conflict történik, hiszen a második branch-ben még a régi névvel történik metódushívás. Ezt az eszközök képtelenek feloldani, mert ugyan az állomány átnevezést tudják kezelni, de az ilyen mély, nyelvi szintű refactoring-ot nem. (Vajon elgondolkodott már valaki olyan verziókezelőn, mely egy speciális programozási nyelvre lenne kifejlesztve, és érzékelné a struktúrális változásokat?) A legrosszabb az olyan conflict és annak feloldása, ami során ugyan a forráskód lefordul, de a szoftver nem az elvártnak megfelelően működik&lt;/p&gt;

&lt;p&gt;Fowler nagy híve a Test Driven Development-nek, így az utóbbira az azonnali válasza, hogy minél több teszt esetet írjunk, mely során kijönnek a szemantikai ütközések. Valamint még egy, a bug-fix branch-eken kívül ne használjunk branch-eket, azaz az egész eddigi okfejtést negálja.&lt;/p&gt;

&lt;p&gt;Erre találta ki ugyanis a &lt;a href="http://martinfowler.com/articles/continuousIntegration.html"&gt;continuous integration&lt;/a&gt; fogalmát, mely az Extreme Programming egyik alapelve is. Egy dolgot szeretnék ezzel kapcsolatban mindenekelőtt tisztázni. Azért, mert a fejlesztési folyamatunkban van CI eszköz (pl. a legelterjedtebb Hudson/Jenkins), még nem használunk CI-t. Láttam több helyen olyant, hogy minden egyes branch-re rá volt fűzve a CI, ami a branch-eket build-elgette. Ez nem CI, a CI tagadja a branch-ek használatát, így nem barátja a &lt;a href="http://martinfowler.com/bliki/FeatureBranch.html"&gt;feature branching-nek&lt;/a&gt; sem! Fowler ezt continuous building-nek nevezi, ami ugyan jó dolog, de szerinte nem elegendő.&lt;/p&gt;

&lt;p&gt;A continuous integration gyakorlatilag arra épít, hogy a fejlesztési folyamatban az egyik legfájóbb pont a merge. Ezt úgy próbálja kiküszöbölni, hogy kizárólag a mainline-ban történik a fejlesztés, így nincs szükség merge-ölésre. A mainline-nak mindig egy működő, futtatható, tesztelhető állapotnak kell lennie, hogy ne akassza meg a többiek munkáját. A fejlesztés során így a fejlesztők kötelesek azonnal kommunikálni, hiszen nem vonulhatnak el külön kis branch-ükbe, hanem ha olyan funkciókat fejlesztenek, melyek közös területeket érintenek, azonnal össze kell dolgozniuk. A külön branch-ek esetén erre nincs szükség, két teljesen különböző irányokba elmehetnek, és csak a conflict során derül ki, hogy esetleg már az elején közösen kellett volna dolgozniuk (nem tudta az egyik kéz, mit csinál a másik). A CI arra ösztökéli a fejlesztőket, hogy minél gyakrabban tegyék vissza a saját gépükről a változásokat a mainline-ba (minimum naponta egyszer), megelőzve ezzel az ütközéseket, valamint kis, atomi egységekben dolgozzanak. Szemben a branch-ek esetén, ahol igen nagy méretű módosításokat kellhet összevezetni. A branch-ek használata esetén megfigyelték, hogy a fejlesztők féltek a refactoring-tól, hiszen leggyakrabban azok okoznak szemantikai ütközést. CI esetén a refactoring-ot el lehet végezni, folyamatosan javítva ezzel a kódminőséget.&lt;/p&gt;

&lt;p&gt;Amennyiben a feature branch-ing esetén csökkenteni akarjuk a merge veszélyét megtehetjük azt is, hogy merge-ölgetünk a branch-ek között. Ezt Fowler promiscuous integration-nek nevezi, de ezt sem tartja jó megoldásnak. Több branch esetén már problémás lehet, valamint nagy adminisztrációs terhe van, hogy mi hova lett már merge-ölve (ezen az eszközök kicsit enyhíthetnek).&lt;/p&gt;

&lt;p&gt;Mi van akkor, ha az ügyfél mégis azt kéri, hogy kell neki egy olyan verzió, ami nem tartalmaz olyan funkciókat, amiket mi már elkezdtünk fejleszteni. A CI megoldása erre a &lt;a href="http://martinfowler.com/bliki/FeatureToggle.html"&gt;funkciók ki- és bekapcsolása&lt;/a&gt;. Ugyanis a branch-ek hiánya miatt nincs cherry-picking. Úgy fejlesszük le az új funkciókat, hogy azok kikapcsolhatóak legyenek - például menüpont eltüntetésével. (Azért azt ő sem tagadja, hogy ez több hibalehetőséget is magában rejthet - pl. furcsa olyan teszt esetet írni, ami azt ellenőrzi, hogy nincs-e valami plusz.)&lt;/p&gt;

&lt;p&gt;A CI-nek több eleme is van (automatikus build, melynek időtartamát illik 10 perc alatt tartani, staged build/build pipeline, tesztelés, deployment, CI eszköz, stb.), de a branch-elés szempontjából a post-ban említettek a kiemelendők.&lt;/p&gt;

&lt;p&gt;Martin Fowler szerint a CI szinte mindenütt bevethető. Én ennél sokkal óvatosabban fogalmaznék, szerintem mindkét megközelítésnek megvan a megfelelő alkalmazási környezete. Mint sok mindenben, itt is a projekt ismeretében lehet dönteni. Kevésbé képzett, kevésbé agilis fejlesztőteam-ek, kevésbé rugalmas, vagy problémásabb megrendelő, nagyobb projekt büdzsé esetében kellő körültekintéssel nem lehet probléma a branch-ek használatával. Vigyázzunk, ezek ne szaporodjanak el, kontrolláljuk őket, mert nem egy céget/fejlesztést láttam, ahol annyira szétcsúsztak a branch-ek, hogy a fejlesztők nem látnak esélyt arra, hogy valaha is merge-öljenek, pl. ügyfelenként külön branch-ük van. A menedzsment meg nem biztosít erre erőforrást (idő/pénz), hiszen a problémát sem érti. Vigyázzunk, hogy a branch-ek kellően rövid élettartamúak legyenek, és szüntessük meg őket. A CI egy nagyon jó irány, amennyiben kellően pörgős vagy kicsi a team, a projekt, sikerrel alkalmazhatjuk. Mi saját fejlesztéseinkben a CI-t alkalmazzuk, de több esetet láttam, ahol indokolt a branch-ek használata. Az alkalmazás megfelelő modularizálásával szintén léphetünk egyet a CI felé, egy monolitikus maradványrendszer megkövetelheti a branch-ek használatát. A fejlesztők képzettsége nem biztos, hogy számottevő tényező, mert branch esetén a merge-ben kell nagyon jónak lenni, CI esetén viszont úgy kell fejleszteni, hogy véletlenül se tegyünk a mainline-ba olyan dolgot, ami megakasztja a többi fejlesztőt. Mindkét esetben nagy odafigyeléssel dolgozó, motivált és kommunikációra képes kollégákra van szükségünk.&lt;/p&gt;

&lt;p&gt;A következő post-ban arról fogok írni, hogyha a branch-elés mellett döntünk, mire kell figyelni, milyen lehetőségeink vannak, milyen eszközök támogatnak ebben.&lt;/p&gt;

&lt;p&gt;Te milyen aktívan branch-elsz és miért?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-5347349015396857015?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/5347349015396857015/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/08/branch-eljunk-e-vagy-sem.html#comment-form" title="7 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/5347349015396857015?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/5347349015396857015?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/08/branch-eljunk-e-vagy-sem.html" title="Branch-eljünk-e vagy sem?" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>7</thr:total></entry><entry gd:etag="W/&quot;DkcGRno5eip7ImA9WhdRF0Q.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-1041560709147746097</id><published>2011-08-08T10:53:00.002+02:00</published><updated>2011-08-08T11:00:27.422+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-08T11:00:27.422+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Community" /><title>Goldenblog 2011</title><content type="html">&lt;p&gt;Elindult a Goldenblog szavazás, kilenc kategóriában lehet szavazni a kedvenc blogodra. Szavazni Facebook-belépéssel lehet. Mind a kilenc kategóriában egyet-egyet szavazhattok. A szavazás augusztus 8-án reggel (szintén 7 óra 7 perckor) indul és 21-én éjfélig tart. Újdonság idén, hogy minden kategóriában két (egy szakmai és egy közönségzsűri) nyertest hirdetnek.&lt;/p&gt;

&lt;p&gt;Idén a &lt;a href="http://jtechlog.blogspot.com/"&gt;JTechLog&lt;/a&gt; is indult az IT-blogok kategóriában. Amennyiben tetszik a blog, &lt;a href="http://goldenblog.hu/szavazas.aspx?bId=1353"&gt;szavazz rá&lt;/a&gt;!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-1041560709147746097?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/1041560709147746097/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/08/goldenblog-2011.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/1041560709147746097?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/1041560709147746097?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/08/goldenblog-2011.html" title="Goldenblog 2011" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkcBRHw7fSp7ImA9WhdRFEQ.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-1410480971650480828</id><published>2011-08-05T00:40:00.005+02:00</published><updated>2011-08-05T00:47:35.205+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-05T00:47:35.205+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><title>Maven plugin-ek verziószáma</title><content type="html">&lt;p&gt;Technológiák: Maven 2.1.1, Maven 3.0.3&lt;/p&gt;

&lt;p&gt;Egy régebbi &lt;a href="http://jtechlog.blogspot.com/2010/04/maven-kezdolepesek.html"&gt;postban&lt;/a&gt; már említettem, hogy a Maven moduláris felépítésű, és minden plugin-ben van megvalósítva. Az életciklus különböző fázisaiban (phase) különböző plugin-ok különböző céljai (goal) futnak le. Minden feladatot tehát valójában egy-egy plugin végez el, ezen plugin-okból &lt;a href="http://maven.apache.org/plugins/index.html"&gt;rengeteg támogatott&lt;/a&gt; és egyedi plugin is létezik. A compiler plugin végzi a fordítást, a jar, war és ear például a csomagolást, stb. A plugin-ek két csoportra oszthatók, build plugin-ek és reporting plugin-ek.&lt;/p&gt;

&lt;p&gt;A következő post azt demonstrálja, hogy miért szükséges a plugin-ek verziószámát is deklarálni a pom.xml-ben. Egy nem általunk készített alkalmazás Maven 3.0.3-ra migrációjánál a következő hibaüzenetet vettem észre egy projektnél:&lt;/p&gt;

&lt;pre&gt;
[WARNING] Warning: selected war files include a WEB-INF/web.xml which 
will be ignored 
(webxml attribute is missing from war task, or ignoreWebxml attribute 
is specified as 'true')
&lt;/pre&gt;

&lt;p&gt;A hibaüzenet a war plugin adja, a hibaüzenet számomra teljesen értelmezhetetlen. Milyen war fájlok (többesszám!) tartalmaznak már web.xml állományt? A dokumentációt megnézve a hibaüzenetben ezen kívül két hiba is van, az első említett paraméter helyes írásmódja webXml, a másik ignoreWebxml paraméter nem is létezik (http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html).&lt;/p&gt;

&lt;p&gt;Mivel emlékeztem, hogy a Maven 2.1.1 hasonló hibát nem dobott, ezt újra leellenőriztem, és tényleg nem írt ki hibát. Ebből már sejthető volt, hogy verzióeltérés lesz.&lt;/p&gt;

&lt;p&gt;Először egy help:describe paranccsal próbálkoztam Maven 3.0.3-assal, mely egy rövid súgót ad az adott plugin-re vonatkozóan. Ez még egy olyan könyvtárban, ahol nincs pom.xml, tehát projekttől függetlenül. Erről a &lt;a href="http://docs.codehaus.org/display/MAVENUSER/FAQs-1#FAQs-1-HowdoIdeterminewhatversionofapluginIamusing%3F"&gt;FAQ&lt;/a&gt; kicsit félrevezetően ír.&lt;/p&gt;

&lt;pre&gt;
$ mvn help:describe -Dplugin=war
...
Name: Maven WAR Plugin
Description: Builds a Web Application Archive (WAR) file from the project
  output and its dependencies.
Group Id: org.apache.maven.plugins
Artifact Id: maven-war-plugin
Version: 2.1.1
Goal Prefix: war
...
&lt;/pre&gt;

&lt;p&gt;A plugin paraméternél megadott prefix (war) helyett megadhatunk groupId, artifactId párt is (-Dplugin=org.apache.maven.plugins:maven-war-plugin). Amennyiben nem a verziószámra vagyunk kíváncsiak, hanem egy adott verzióhoz tartozó célokra, megadhatunk GAV (groupId, artifactId, version) hármast is, a szokásos jelöléssel, kettőspontokkal elválasztva. De megadhatjuk a GAV-ot három paraméterrel is:&lt;/p&gt;

&lt;pre&gt;
$ mvn help:describe -DgroupId=org.apache.maven.plugins 
  -DartifactId=maven-war-plugin -Dversion=2.1.1 -Ddetail=true -Dgoal=war
&lt;/pre&gt;

&lt;p&gt;Ne feledjük, hogy amennyiben elírjuk a paraméter nevét, a Maven erről nem figyelmeztet, egyszerűen figyelmen kívül hagyja. Részletesebb súgót, mely a paramétereket is tartalmazza a -Ddetail paraméterrel kérhetünk (régebben full paraméter volt). A -Dgoal=war paraméterezéssel tudunk csak egy célról információt kérni.&lt;/p&gt;

&lt;p&gt;Az első parancsot kiadva Maven 2.1.1-nél azt tapasztalhatjuk, hogy a verzió 2.2-SNAPSHOT. Egy kis &lt;a href="https://cwiki.apache.org/MAVEN/maven-3x-compatibility-notes.html"&gt;kutakodás után kiderült&lt;/a&gt;, hogy a Maven 2 és 3 között inkompatibilitás van, azzal kapcsolatban, hogy hogyan keresi meg a verziószámát a használni kívánt plugin-nek. Míg a 2-es a legutolsó verziót tölti le (2.2-SNAPSHOT), addig a 3-asban a stabilitás érdekében azt a döntést hozták, hogy a legutolsó release verziót használja, ami jelenleg a 2.1.1.&lt;/p&gt;

&lt;p&gt;Ez a parancs nem adja viszont azt meg, hogy az adott projektben a kérdéses plugin melyik verziója kerül felhasználásra. Az adott projektben nem volt a plugin definiálva. A Maven 3 már futás közben is tájékoztat a verziószámról.&lt;/p&gt;

&lt;pre&gt;
--- maven-war-plugin:2.1.1:war (default-war) @ earconfig-web ---
&lt;/pre&gt;

&lt;p&gt;Ahhoz, hogy a Maven 2 futás közben is kiírja, a -X kapcsolóval kell indítani, és a nagyon részletes logból kibogarászni:&lt;/p&gt;

&lt;pre&gt;
[DEBUG] Configuring mojo 
  'org.apache.maven.plugins:maven-war-plugin:2.1-alpha-2:war' --&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Látható, hogy míg a 2-es Maven a 2.1-alpha-2 verzióval dolgozik, addig a 3-as a 2.1.1-gyel. De mégis hol van ez definiálva? A választ a következő parancs adja meg:&lt;/p&gt;

&lt;pre&gt;
mvn help:effective-pom
&lt;/pre&gt;

&lt;p&gt;A Maven help plugin-jének effective-pom paranccsa összefésüli a super pom-ot és a projekt pom-ját (, és annak szülőit, valamint figyelembe veszi a profilokat). Mivel a projekt pom-jában nincs a plugin definiálva, azt a super pom-ból veszi, ami a 2-esben a M2_HOME/lib/maven-2.2.1-uber.jar:org/apache/maven/project/pom-4.0.0.xml helyen, míg a 3-asban a M2_HOME/lib/maven-model-builder-3.0.3.jar:org/apache/maven/model/pom-4.0.0.xml helyen van. Tehát a Maven verziójától függ, hogy mik az alapértelmezett plugin verziószámok egy projekten belül.&lt;/p&gt;

&lt;p&gt;Tehát míg a Maven 2 által definiált 2.1-alpha-2 nem dobja a hibát, addig a 2.1.1 igen, amiről egy &lt;a href="http://stackoverflow.com/questions/4342245/maven-webxml-is-missing-from-war-task"&gt;stackoverflow kérdés&lt;/a&gt;, és egy &lt;a href="http://jira.codehaus.org/browse/MWAR-248"&gt;JIRA issue&lt;/a&gt; is megemlékezik. Ennek megoldása egyszerű, helyezzük el a pom.xml-ben a következőt:&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;build&amp;gt;
  &amp;lt;plugins&amp;gt;
    &amp;lt;plugin&amp;gt;
      &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
      &amp;lt;configuration&amp;gt;
        &amp;lt;packagingExcludes&amp;gt;WEB-INF/web.xml&amp;lt;/packagingExcludes&amp;gt;
      &amp;lt;/configuration&amp;gt;
    &amp;lt;/plugin&amp;gt;
  &amp;lt;/plugins&amp;gt;
&amp;lt;/build&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Úgy tűnik nem tanultunk az előző hibánkból, és újra elkövettük, hogy a plugin verziószámát nem definiáltuk. Erre a Maven 3 már alapból figyelmeztet:&lt;/p&gt;

&lt;pre&gt;
[WARNING] 
[WARNING] Some problems were encountered while building the effective model 
  for jtechlog.earconfig:earconfig-web:war:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for 
  org.apache.maven.plugins:maven-war-plugin is missing. @ line 60, column 9
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they 
  threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer 
  support building such malformed projects.
[WARNING] 
&lt;/pre&gt;

&lt;p&gt;A version tag beillesztésével azonnal javíthatjuk a hibát. Ekkor már nem a super pom-ban definiált verzió, hanem a saját pom.xml-ünkben definiált verzió fog
érvényesülni. A verzió automatikus meghatározását a Maven Automatic Plugin Version Resolution-nek nevezi, és warning amiatt jelenik meg, mert a későbbi verziókban a build reprodukálhatóságának megsegítéseként el kívánják távolítani, ezért érdemes mindenképp explicit definiálni a verziókat.&lt;/p&gt;

&lt;p&gt;Amennyiben a 2-es Maven verziót használjuk, ugyanerre megfelelő az &lt;a href="http://maven.apache.org/plugins/maven-enforcer-plugin/"&gt;enforcer&lt;/a&gt; plugin enforce célja. A következőképp konfigurálhatjuk:&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;plugin&amp;gt;
  &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;maven-enforcer-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;1.0.1&amp;lt;/version&amp;gt;
  &amp;lt;executions&amp;gt;
    &amp;lt;execution&amp;gt;
      &amp;lt;goals&amp;gt;
        &amp;lt;goal&amp;gt;enforce&amp;lt;/goal&amp;gt;
      &amp;lt;/goals&amp;gt;
      &amp;lt;configuration&amp;gt;
        &amp;lt;rules&amp;gt;
          &amp;lt;requirePluginVersions&amp;gt;
            &amp;lt;banLatest&amp;gt;true&amp;lt;/banLatest&amp;gt;
            &amp;lt;banRelease&amp;gt;true&amp;lt;/banRelease&amp;gt;
          &amp;lt;/requirePluginVersions&amp;gt;
        &amp;lt;/rules&amp;gt;
      &amp;lt;/configuration&amp;gt;
    &amp;lt;/execution&amp;gt;
  &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Futtatáskor a következő hibát kaphatjuk:&lt;/p&gt;

&lt;pre&gt;
[WARNING] Rule 0: org.apache.maven.plugins.enforcer.RequirePluginVersions 
  failed with message:
Some plugins are missing valid versions:(LATEST RELEASE SNAPSHOT are 
  not allowed )
org.apache.maven.plugins:maven-war-plugin.  The version currently in 
  use is 2.1-alpha-2
&lt;/pre&gt;

&lt;p&gt;A Maven 3-nál többet tud, ugyanis a nem definiált plugin-okat is jelzi. Az előbbi példánál maradva, ha nem tettük volna bele a maven-war-plugin definícióját a pom.xml-be, a Maven 3 nem panaszkodott volna, hogy nem a legfrissebb plugin-t futtatja. Az enforcer plugin viszont ezt is észreveszi, bővebb a funkcionalitása.&lt;/p&gt;

&lt;p&gt;Az enforcer plugin-t a 3-as Maven-nel futtatva viszont a következő hibaüzenetet kapjuk. Erről is van &lt;a href="http://jira.codehaus.org/browse/MENFORCER-98"&gt;JIRA issue&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;
[INFO] The requirePluginVersions rule is currently not compatible with Maven3.
&lt;/pre&gt;

&lt;p&gt;Projekt öröklődés esetén a plugin beállításai alapesetben nem öröklődnek. Ahhoz, hogy mégis, a beállításokat a szülő projekt pom-jában a pluginManagement részben kell elhelyezni. Így a verziószám és a konfiguráció is öröklődik. Ekkor a gyermek projektben elegendő csak a groupId-t és az artifactId-t elhelyezni. Nagy projekt esetén jelentős copy-paste munkát takaríthatunk meg ezzel.&lt;/p&gt;

&lt;p&gt;Néha szükségünk lehet arra is, hogy megnézzük, hogy van-e frissebb verzió egy adott plugin-ból. Ezt a versions pluginnal kérhetjük le a következő módon:&lt;/p&gt;

&lt;pre&gt;
mvn versions:display-plugin-updates
&lt;/pre&gt;

&lt;p&gt;Régebben a -cpu kapcsoló is jó volt erre, de ez deprecated, így ne használjuk. Másik lehetőség, hogy egyszerűen rákeresünk a Maven repository-ban a http://search.maven.org címen.&lt;/p&gt;

&lt;p&gt;A plugin-ek verziószámát a site generálás is szépen megmutatja a Maven 2-ben, a plugin-management.html oldalon.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-uxSShb6DUDM/TjsgidXjC7I/AAAAAAAAHR0/tNYk_m5mttE/s1600/plugin-management.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 303px;" src="http://2.bp.blogspot.com/-uxSShb6DUDM/TjsgidXjC7I/AAAAAAAAHR0/tNYk_m5mttE/s320/plugin-management.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5637135134955342770" /&gt;&lt;/a&gt;

&lt;p&gt;A Maven 3-ban ez &lt;a href="https://cwiki.apache.org/MAVEN/maven-3x-and-site-plugin.html"&gt;nem ilyen egyszerű&lt;/a&gt;. A mvn site parancsot kiadva alapértelmezetten semmit nem kapunk. Konfigurálni kell a maven-site-plugin-t, hogy futtassa a maven-project-info-reports-plugin-t, és az generálja le pl. a plugin-management riporot. Ez a következőképp néz ki:&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;plugin&amp;gt;
  &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;maven-site-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;3.0&amp;lt;/version&amp;gt;
  &amp;lt;configuration&amp;gt;
    &amp;lt;reportPlugins&amp;gt;
      &amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-project-info-reports-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;2.4&amp;lt;/version&amp;gt;
        &amp;lt;reports&amp;gt;
          &amp;lt;report&amp;gt;plugin-management&amp;lt;/report&amp;gt;
        &amp;lt;/reports&amp;gt;
      &amp;lt;/plugin&amp;gt;
    &amp;lt;/reportPlugins&amp;gt;
  &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Azaz ha biztosak akarunk lenni a build reprodukálhatóságában, mindig definiáljuk a plugin-ek verziószámát. A Maven 3 tett egy lépést ennek kikényszerítésének az irányában.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-1410480971650480828?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/1410480971650480828/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/08/maven-plugin-ek-verzioszama.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/1410480971650480828?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/1410480971650480828?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/08/maven-plugin-ek-verzioszama.html" title="Maven plugin-ek verziószáma" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-uxSShb6DUDM/TjsgidXjC7I/AAAAAAAAHR0/tNYk_m5mttE/s72-c/plugin-management.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUMNQns_fCp7ImA9WhZaF00.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-535551803739667071</id><published>2011-07-02T20:22:00.006+02:00</published><updated>2011-07-03T17:38:13.544+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-03T17:38:13.544+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="open source" /><category scheme="http://www.blogger.com/atom/ns#" term="IDE" /><category scheme="http://www.blogger.com/atom/ns#" term="Swing" /><category scheme="http://www.blogger.com/atom/ns#" term="könyv" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>Vastag kliens Java-ban? NetBeans Platform</title><content type="html">&lt;p&gt;Technológiák: NetBeans Platform 7.0 - Rich-Client Platform (RCP)&lt;/p&gt;

&lt;p&gt;Az előző két post kellően megmozgatta a fantáziátokat, egy-két hozzászólásból nagyon sokat tanultam, most megpróbálok ismét egy kellően provokatív témát felvetni, a vastag kliens fejlesztésről általában, és speciálisan Java környezetben. Ne fogjátok vissza magatokat, várom a véleményeiteket.&lt;/p&gt;

&lt;p&gt;Egy projekt úgy hozta, hogy vastag klienses alkalmazást kell fejleszteni. Igazából mi döntöttünk, hogy az alkalmazást vastag kliensként fejlesztjük le, ilyen szempontból nem volt megkötés, a követelmények elemzésekor azonban mégis oda jutottunk, hogy így járunk a legjobban.&lt;/p&gt;

&lt;p&gt;Nagyon sok embernek említettem, és majdnem mindannyian kérdően néztek rám, és láttam, hogy nem értették. A legjobban az zavar, hogy megemlítettem, hogy vastag kliens alkalmazást fejlesztünk, és bármi egyéb információ nélkül azonnal rávágta, hogy miért. Volt, aki azonnal elkezdte kifejteni, hogy a GWT (ide bármilyen kedvenc keretrendszer neve beilleszthető) mennyivel jobb, mint a vastag kliens alkalmazás fejlesztése.&lt;/p&gt;

&lt;p&gt;Vajon miért ez az ellenszenv? Miért vált ilyen divatossá a webes fejlesztés? De ami a legsúlyosabb kérdés, mindenáron ragaszkodni kell a webes megközelítéshez? Hogy nem is érdekel, hogy miről szól a projekt, nem is érdekel, hogy mik a követelmények, azonnal véleményt formálok, és megpróbálom lebeszélni a fejlesztőket a vastag kliensről? Azokat a fejlesztőket, akik hónapokat gondolkodtak ezen, pilotokat dolgoztak ki, körültekintően próbálták és hasonlították össze a technológiákat?&lt;/p&gt;

&lt;p&gt;Véleményem szerint a vastag kliens fejlesztésének még mindig megvan a létjogosultsága. Kinek jutna eszébe fejlesztőeszközt webeset használni? (Na jó, vannak elvetemültek, április témaként is megjelent, hogy az Eclipse-nek elkészítik a webes verzióját, és félek, vannak, akik meg is tennék.) Egy 3D modellező eszköz (pl. Blender), CAD rendszer (AutoCAD), hatalmas képeket/3d objektumokat feldolgozó orvosi rendszerek, GIS alkalmazások (térképészet) mind mind csak egy példa arra, hogy a vastag kliensnek van még alkalmazási területe. (Corel, Photoshop szerű, valamint videóvágó alkalmazások webes verziói mostanában nagyon mennek, de azért ezek távol állnak a professzionális megoldásoktól. Persze, bizonyos felhasználóknak ezek is elegendőek.) Nekünk egy Visio szerű rajzoló alkalmazást kell fejlesztenünk, bonyolult mögöttes üzleti logikával.&lt;/p&gt;

&lt;p&gt;A vastag kliens kiválasztásában a következő érvek döntöttek. Talán a döntő érv az volt, hogy pixel pontos grafikai megjelenítést és tervezést kell megvalósítani, nagyíthatósággal. A telepítési munkálatok nem problémásak, mivel Intraneten központilag képesek az alkalmazásokat telepíteni. (A Java Web Start óta viszont amúgy sem bonyolult a Java alkalmazások telepítése, de tény, hogy a Java Runtime Environment-et ugyanúgy teríteni kell.) Valamint vastag kliens fejlesztése eszméletlenül hatékony tud lenni, irgalmatlanul gyorsan lehet a képernyőket gyártani. (Láttam projektet, melynél az implementáció felében döntöttek arról, hogy legyen inkább vastag kliens, és az idő tört része alatt összerakták ugyanazon képernyőket.) Sajnos a http protokoll, a html formátum, a különböző adatátvitel megoldások, XML, JSON, AJAX, stb. mind-mind egy plusz probléma, plusz réteg, mellyel foglalkozni kell, teljesen egyik keretrendszer sem képes ezeket elfedni. Meggyőződésem, hogy a http formátumot már rég kinőttük, az egészet el kéne felejteni, és egy újat használni, mely alkalmazás fejlesztésére sokkal megfelelőbb lenne. A vastag kliens alkalmazásfejlesztés esetén azonban a képernyőket tényleg WYSIWYG módon össze lehet dobálni (nem is használunk mockup-okat, drótvázakat, a képernyőket egyből a cél keretrendszerben állítjuk elő), a régóta bizonyított observer tervezési minta (, és az ebből továbbfejlődő eseménykezelés, stb.), valamint az MVC modell is nagyon hatékonyan működik. (Nem véletlen az sem, hogy a legtöbb tervezési mintára itt lehet szép példákat hozni.) Látszik ez abból is, hogy az összes webes keretrendszer próbálja ezt alkalmazni, bár nem sikerülhet nekik, hiszen az alatta lévő http szabvány ezt majdhogynem ellehetetleníti. Szintén nagyon hatékony a komponensekből való építkezés is, itt tényleg megvalósítható könnyen az újrafelhasználás, valamint a személyre szabás is. Ezeknek az elvnek webes környezetben talán legjobban a JSF próbál megfelelni, de az abban való fejlesztés sem olyan hatékony, mint a vastag kliens környezetben. És akkor ne is beszéljünk arról, hogy a fejlesztés mennyivel kényelmesebb, mennyivel gyorsabbak az iterációk, hiszen nem kell környezetet felépíteni, nincs szükség alkalmazásszerverre. Egy bonyolultabb alkalmazásnak is pár másodperc alatt indulni kell. Érdemes webes projekt után átülni kicsit egy vastag klienses projektbe, sokkal gördülékenyebb, magától értetődőbb. És nincs szükség annyi technológia, protokoll, szabvány ismeretére sem.&lt;/p&gt;

&lt;p&gt;Persze, vannak hátrányai is. Egyrészt a fentebb említett telepítési problémák, melyek bizonyos környezetekben egyszerűen kizárják a vastag klienses alkalmazás használatát. Azért ne legyenek téveszméink, ilyen problémák webes környezetben is adódhatnak, különböző böngésző inkompatibilitások, bezavaró plugin-ek, elkonfigurált tűzfalak, stb. Másik a platformfüggetlenség. Ha Java alapú technológiákat választunk, akkor ezzel sem lesz annyi problémánk, mint régen, amikor azért tényleg másképp néztek ki az alkalmazások különböző környezetekben. Amit fel szoktak hozni érvként, tipikusan a Swing ellen, hogy mivel pehelysúlyú komponenseket használ (pont az előbb említett platformfüggetlenség miatt), lassú lehet a megjelenítés, hiszen szoftveresen rajzol, és nem az operációs rendszer (ablakozó rendszer) beépített komponenseit használja az egységes megjelenítés érdekében. A JDK utóbbi verzióiban azonban olyan szintű optimalizációkat hajtottak végre, hogy azért ez már kevésbé érezhető.&lt;p&gt;

&lt;p&gt;A legnagyobb ellenérzés a Swing-gel kapcsolatban történeti okok miatt van. Egyrészt igen, tényleg rossz volt, lassú, és kevésbé platform független. A másik, hogy sokan azt gondolták, hogy minden fajta tudás, előképzettség nélkül neki lehet ülni benne fejleszteni, akár egy Borland Delphi alkalmazást. Sok Swing fejlesztőnek fogalma sincs például a Swing szálkezeléséről. Ez a hozzáállás azonban Swing esetén nem megfelelő. Ahhoz, hogy jó alkalmazásokat írjunk, igenis magas fokú előképzettség kell. Meg kell érteni az MVC modellt (annak is speciális válfaját, hiszen a Swing esetén a kontroller és a nézet össze van nőve), az eseménykezelést (azok fajtáit), a szálkezelést (EDT - event dispatcher thread, 6-os Java-ban megjelent SwingWorker), a kirajzolás folyamatát, a double bufferinget, stb. Ezek hiányában olyan alkalmazások kerülnek ki, melyek gyakran lefagynak, nem válaszolnak a felhasználónak. És nem utolsó sorban a leglényegtelenebb, vagy mégis a legfontosabb a megjelenés. Egyrészt a Swinges komponensek egy időben rettentő rondák voltak, valamint álláspontom szerint a programozóknak csak kis részét szabad az interfész tervezéséhez engedni. Swing esetén nincs ez így, általában a fejlesztők készítik teljes egészében a felhasználói interfészt. Webes környezetben szerencsére ez hamarabb elvált. Igen, és ennek eredménye az volt, hogy a Swing-es interfészek egyszerűen rondák voltak.&lt;/p&gt;

&lt;p&gt;A vastag kliens megvalósításakor azonban már nem elegendő a Swing használata, mely a Java része. Egy ideje nem nagyon fejlesztik, rengeteg komponens hiányzik belőle, és ennek használatával felépíteni egy alkalmazást, hatalmas munka. Jelenleg a Java világban két versenyző van, a &lt;a href="http://netbeans.org/features/platform/"&gt;NetBeans Platform&lt;/a&gt;, valamint az &lt;a href="http://wiki.eclipse.org/index.php/Rich_Client_Platform"&gt;Eclipse Rich Client Platform&lt;/a&gt;. Amint valaki szembesül azzal, hogy vastag kliens alkalmazást fejlesztünk, azonnal arról akar meggyőzni, hogy ezt Eclipse platformon tegyük. Attól függetlenül, hogy az Eclipse RCP-t ismeri-e vagy sem, csupán arra alapozva, hogy az ő kedvenc IDE-je az Eclipse.&lt;/p&gt;

&lt;p&gt;Úgy látszik, ezen a területen mindig ellenállásba ütközöm, és mindig meg kell magyaráznom a döntéseimet. És mindenki tud hozzászólni, függetlenül attól, hogy kizárólag vékony klienses alkalmazásokat fejlesztett. Like-olj, ha idáig eljutottál, és látsz jövőt a Java alapú vastag kliens alkalmazás fejlesztésében.&lt;/p&gt;

&lt;p&gt;Természetesen összehasonlítottuk a két platformot, és arra jutottunk, hogy számunkra a NetBeans Platform használata célravezetőbb. Kerestünk NetBeans Platform fejlesztőt is, és kiderült, hogy sokan nem is ismerik a NetBeans IDE és a NetBeans API közötti különbséget, sok olyan életrajzot kaptunk, amiben az volt leírva, hogy fejlesztett NetBeans-szel. A NetBeans Platform egy keretrendszer vastag klienses alkalmazások fejlesztésére, melynek egyik alkalmazási módja a NetBeans IDE, mely egy Java fejlesztőeszköz. De ezen kívül &lt;a href="http://platform.netbeans.org/screenshots.html"&gt;rengeteg más alkalmazás&lt;/a&gt; is létezik felette. Persze a dolog pikantériája, hogy a Platform is Java-ban íródott, és NetBeans alkalmazást (valamint plugin-t is) NetBeans IDE-vel lehet fejleszteni. És most következzenek az érvek, amiért NetBeans mellett döntöttünk.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fejlesztés szempontjából szerintem mindegy, hogy ki mit választ, egy idő után mindkettőben ugyanazt a fejlesztői hatékonyságot el lehet érni. Tapasztalatom szerint a Eclipse-szel nagyobb munkával, de kényelmesebb környezetet lehet összehozni, mindent a saját, egyéni ízlésünkre igazítva. Rengeteg plugin közül válogathatunk. A NetBeans ezzel szemben nem ad akkora mozgásteret, de ha kicsit kisebbek az igényeink, egy alap telepítéssel mindenhez hozzájuthatunk, nem nekünk kell a pluginek között válogatni. Alapban támogatja a Maven-t, Subersion-t, Mercurial-t, Tomcat-et, és van benne properties fájl szerkesztő (megfelelő automatikus native2ascii kódolással), vizuális szerkesztő. Én inkább az előrecsomagolt megoldásokat szeretem, minthogy nekem kelljen összerakosgatni, ezért a NetBeans ebből a szempontból jobban tetszik, de ez egy szubjektív álláspont. A vizuális szerkesztővel nem nagyon lehet vitatkozni, az Eclipse-nél nincs ilyen, mely kellően egyszerű, könnyen használható és ingyenes lenne, mint a NetBeans Matisse felülete. Hallottam projektről, ahol a képernyőket NetBeans-ben szerkesztették, a fejlesztést Eclipse-ben végezték.&lt;/li&gt;
&lt;li&gt;Az Eclipse az SWT könyvtárat használja, mely saját elemeket, saját modellt alkalmaz. Ennek szükségességét azzal magyarázza, hogy a Swing a pehelysúlyú komponensek miatt lassú, az SWT komponensei natív kódrészleteket is tartalmaznak, így különböző operációs rendszerekre különböző natív komponenseket is telepíteni kell. Egyrészt a modern JVM-eken már nem tapasztalható különbség, érdemes összehasonlítani a NetBeans és Eclipse legújabb verzióit (!!!), számottevő eltérés nincs. Másrészt a projektben résztvevők nálunk masszív Swing tudással rendelkeztek, így felesleges lett volna egy újabb technológiát megtanulni, mely nem hoz semmi előnyt.&lt;/li&gt;
&lt;li&gt;Az Eclipse a modularizációra az OSGi de facto szabványt használja, annak az Equinox implementációját. Nemrég &lt;a href="http://www.theserverside.com/news/2240037102/OSGi-Not-Easy-Enough-to-Use-Not-as-Productive-as-it-Should-Be"&gt;jelent meg&lt;/a&gt; egy interjú Rod Johnsonnal (Spring Framework alapítója és vezetője, író), melyben azt állítja, hogy az OSGi egyrészt nem elég egyszerű, és nem elég produktív. Amire ráláttam projektre, pont ez derült ki, hogy ahelyett, hogy ez egy transzparens réteget biztosítana, elég sok problémát hoz be. A NetBeans modularizációja sokkal egyszerűbb, abszolút fájdalommentesen használható, és épít a Java 6-ban bevezetett szabványos JDK 6 ServiceLoader mechanizmusra. Alapjában véve elmondható, hogy a NetBeans szabványos, JDK-ban lévő megoldásokat próbál alkalmazni, pl. naplózásra is a Java Logging API-t. Melyek lehet, hogy nem a legszofisztikáltabb megoldások, de kipróbált, és sokak által ismert eszközök. Amúgy aki nem tud elszakadni az OSGi-tól, NetBeans-ben is használhatja, erről egy &lt;a href="http://platform.netbeans.org/tutorials/nbm-osgi-quickstart.html"&gt;tutorial&lt;/a&gt; is van.&lt;/li&gt;
&lt;li&gt;Ezen kívül a NetBeans eszméletlen sok &lt;a href="http://netbeans.org/features/platform/all-docs.html"&gt;dokumentációval&lt;/a&gt; rendelkezik, valamint egy &lt;a href="http://platform.netbeans.org/tutorials/nbm-10-top-apis.html"&gt;tíz videóból álló sorozat&lt;/a&gt;, egyenként 30-40 percesek, is bevezet a legfontosabb fogalmakba, mely alapján el lehet indulni.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Egy dolog azonban kiderült, ami hátránya a NetBeans Platformnak. Nagyon nehéz NetBeans Platformos embert találni, Eclipse RCP fejlesztőt talán egyszerűbb.&lt;/p&gt;

&lt;p&gt;Nézzük, hogy mik azok, melyet a NetBeans biztosít a Swing-en felül, mely megkönnyíti a vastag kliens fejlesztést. Csak az érdekesebbeket emelem ki, az összeset a &lt;a href="http://bits.netbeans.org/dev/javadoc/"&gt;JavaDoc-ban&lt;/a&gt; lehet megtalálni.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-CF2G4L88bE0/Tg9jDtJt_PI/AAAAAAAAG-U/f94Uygxh4iQ/s1600/netbeans-platform-architecture.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 178px;" src="http://1.bp.blogspot.com/-CF2G4L88bE0/Tg9jDtJt_PI/AAAAAAAAG-U/f94Uygxh4iQ/s320/netbeans-platform-architecture.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5624823374920154354" /&gt;&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Module System API: Modulok kezelése, függőségek (tranzitív is), verziózás, automatikus frissítés, életciklus kezelés.&lt;/li&gt;
&lt;li&gt;Lookup API: komponensek közötti laza kapcsolat megvalósítására. Valójában ez egy pehelysúlyú konténer, interfész alapján lehet a példányokat előhívni. Lehet a szolgáltatásokat deklaratív módon (XML-ben megadva), és programozottan is bejegyezni. Van globális tér, és lehet komponensenként is, lokálisan is Lookup-ot használni. Dependency injection nincs.&lt;/li&gt;
&lt;li&gt;Actions API: események definiálására és kezelésére, melyek forrása lehet menüpont, billentyűkombináció, toolbar, felugró menü, stb.&lt;/li&gt;
&lt;li&gt;Window System API, Docking Framework és Tab Control: klasszikus ablakozás, ismert mindenkinek, akár NetBeans-t, akár Eclipse-t használ.&lt;/li&gt;
&lt;li&gt;Dialog, Wizard, MultiView: dialógusablakok, varázslók és több nézettel rendelkező ablakok definiálására (pl. vizuális és XML forrás megjelenítés). Érdekes, hogy amikor ezeket definiálunk, sosem ablakokban, hanem panelekben kell gondolkozni. A hozzá tartozó ablakot és gombokat a NetBeans Platform köré teszi, és általában ad egy callback-et, melyen szabályozni tudjuk az ablak viselkedését, pl. az Ok gomb inaktívvá tételét.&lt;/li&gt;
&lt;li&gt;System Filesystem API, MIME Lookup API, Nodes API és Explorer and Property Sheet API, Navigator API: állományok kezelése, valamint állományok betöltése és hozzá tartozó modell generálása. A NetBeans sok komponense un. Node-okkal dolgozik, melyeket a modell elemeihez lehet rendelni. Pl. egy XML állomány esetén a Node-ok az XML tag-ek, vagy egy Java forráskód esetén a forráskód részei, mint osztály, attribútum, metódus, stb. Ezekből akár egy fa struktúrát is fe lehet építeni. Sok komponens ezeket a Node-okat jeleníti meg.&lt;/li&gt;
&lt;li&gt;Search és Quick Search API: keresések implementálásához.&lt;/li&gt;
&lt;li&gt;Editor API: szerkesztők implementálásához használható API, mely támogatja az IDE-kben ismert funkciókat, mint kódkiegészítés, kódszínezés, code folding, kód sablonok, automatikus behúzás, stb.&lt;/li&gt;
&lt;li&gt;Progress API, Task List API, Output Window, Favorites: olyan UI elemekhez való hozzáféréshez, mint progress bar, tennivalók ablak, konzol ablak, kedvencek.&lt;/li&gt;
&lt;li&gt;Options API: beállítások kezelésére.&lt;/li&gt;
&lt;li&gt;JavaHelp Integration API: szabványos JavaHelp formátumot támogatja a NetBeans Platform, ennek integrációjára való ez az API.&lt;/li&gt;
&lt;li&gt;Print API: nyomtatáshoz.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://platform.netbeans.org/graph/"&gt;Visual Library API&lt;/a&gt;: egy NetBeans-en kívül is használható API, mely gráfok grafikus megjelenítésre szolgál. Widget-eket (különböző grafikus elemek), és közöttük lévő Edge-eket (élek) definiál, és jelenít meg egy koordináta rendszerben, pixel pontosan. Támogatja a nagyíthatóságot, eseménykezelést, képként exportálást, stb. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Platform ezen kívül támogatja a több nyelvű interfészek fejlesztését (I18N), Undo/Redo funkcionalitást, aszinkron/háttérfolyamatok futtatását.&lt;/p&gt;

&lt;p&gt;Ami számomra a legérdekesebb volt, nem támogatja a felhasználó által bevitt adatok egységes ellenőrzését (validáció). Először a klasszikus megközelítést választottam, hogy hibás érték esetén dialógusablakot kap a felhasználó. A NetBeans azonban ezt nem támogatja, nagyon macerás a körbeprogramozása, inkább az a megoldás, hogy a felhasználónak ne engedjünk hibás értéket bevinni, vagy ha bevitte jelöljük meg, és ne engedjük el az ablakról. A Maven projekt létrehozásakor vettem észre, hogyha hibás értéket írtam be egy beviteli mezőbe, a mező más színre váltott, felkiáltójel ikon jelent meg benne, és alul is kiírásra került a hibaüzenet, valamint az Ok gomb letiltásra került. A forrásból jöttem rá, hogy a &lt;a href="http://kenai.com/projects/simplevalidation/pages/Home"&gt;Simple Validation API&lt;/a&gt;-t használja, melyet NetBeans-en kívül is lehet használni bármilyen Swing-es alkalmazásban. Ezzel kapcsolatban arra kell nagyon vigyázni, hogy csak régi verzió letölthető, kizárólag a forrásból (Subversion checkout után) fordított bináris a használható. Amúgy is gyakran használatos módszer, hogy hiába vannak nagyon szép és részletes dokumentációk, sok dolgot úgy lehet a legegyszerűbben kitalálni, hogy keresni kell egy hasonló funkciót a NetBeans IDE-ben, és annak kell megnézni a forrását.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-Esw6mur-AIM/Tg9jyGeuxkI/AAAAAAAAG-k/1_ISe_mqoUU/s1600/simple_validation.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 294px;" src="http://4.bp.blogspot.com/-Esw6mur-AIM/Tg9jyGeuxkI/AAAAAAAAG-k/1_ISe_mqoUU/s320/simple_validation.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5624824171993155138" /&gt;&lt;/a&gt;

&lt;p&gt;A NetBeans Platform támogatja a Maven eszközt, az artifact-ok benne vannak a saját repository-ban (http://bits.netbeans.org/maven2/), így standard módon build-elhető, ehhez a &lt;a href="http://mojo.codehaus.org/nbm-maven-plugin/"&gt;NetBeans Modules plugin&lt;/a&gt;-t használja. Automatikus teszt eseteket is lehet írni, erre is van támogatás, és ezáltal mi be is kötöttük continuous integration rendszerbe. A fejlesztés nagyon egyszerű, hiszen sok dolgot varázslóval lehet létrehozni, és a NetBeans legenerálja nekünk a szükséges konfigurációs és forrás állományokat (érdemes megnézegetni, pl. Subversion diff-fel, hogy mit csinál, általában megfelelő, de lehet rajta szépíteni).&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://blogs.oracle.com/geertjan/entry/new_cool_in_netbeans_platform"&gt;7.0-ás NetBeans Platform&lt;/a&gt; újdonsága, hogy a Platform is elkezdi kihasználni a Java 5 újdonságait, pl. több dolgot (lokalizáció, action-ök, mime type) is meg lehet adni annotációban, nem kell XML konfigurációs állományban.&lt;/p&gt;

&lt;p&gt;Az egyedüli dolog eddig, ami nem tetszik, az a paraméterek átadása különböző komponensek között. Nem definit, hogy mit, hol és hogyan kell átadni a következő lehetőségek közül: konstruktor, setter metódus, valamiféle környezeti objektum, callback, általános Map-ban, valamilyen Context/Environment objektumban, Lookup-pal, stb. Gyakran előfordul a tyúk és a tojás esete is, amikor két komponensnek egymásra kell hivatkoznia, de a másodikat nem adhatom át az első konstruktorának, hiszen még nem lett példányosítva.&lt;/p&gt;

&lt;p&gt;A fejlesztéshez a legnagyobb segítséget a The Definitive Guide to NetBeans Platform könyv adja. Minden egyes témába csak egy rövidebb bevezetőt ír, amin el lehet indulni, néhány kódrészlettel. Nem megy bele mélyen a témákba, erre nincs is szükség, a többi részt már bőven ki lehet nézni az API-ból, vagy a forráskódból.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-yNQDGWiQ2OI/Tg9jjzT-FLI/AAAAAAAAG-c/oYL7KmtcuOg/s1600/netbeans_book.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 241px; height: 320px;" src="http://3.bp.blogspot.com/-yNQDGWiQ2OI/Tg9jjzT-FLI/AAAAAAAAG-c/oYL7KmtcuOg/s320/netbeans_book.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5624823926329578674" /&gt;&lt;/a&gt;

&lt;p&gt;Javaslom mindenkinek, hogy akinek lehetősége van, próbáljon részt venni vastag kliens fejlesztésben is, utána a webes alkalmazásokat is másik oldalról lehet nézni, hiszen teljesen más problémák jönnek itt elő, ami ott egyszerű, itt bonyolult, és fordítva. Rengeteg ötletet lehet meríteni. Valamint a webes programozás után ez egy élmény, akár a fejlesztés sebességében, akár az elegáns megoldások terén. Azonban ne várjuk azt, hogy pár óra alatt belerázódunk, itt is van egy elég komoly felkészülési idő.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-535551803739667071?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/535551803739667071/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/07/vastag-kliens-java-ban-netbeans.html#comment-form" title="17 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/535551803739667071?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/535551803739667071?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/07/vastag-kliens-java-ban-netbeans.html" title="Vastag kliens Java-ban? NetBeans Platform" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-CF2G4L88bE0/Tg9jDtJt_PI/AAAAAAAAG-U/f94Uygxh4iQ/s72-c/netbeans-platform-architecture.png" height="72" width="72" /><thr:total>17</thr:total></entry><entry gd:etag="W/&quot;CUIHQn07eip7ImA9WhZbEEk.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-3752345250697097633</id><published>2011-06-14T00:00:00.005+02:00</published><updated>2011-06-14T11:25:33.302+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-14T11:25:33.302+02:00</app:edited><title>Második nyelv: Python?</title><content type="html">&lt;p&gt;Remélem ezzel a cikkel is sikerül annyi gondolatot megmozgatni, mint az előbbivel, ha valami eszetekbe jut, ne legyetek rest hozzászólni!&lt;/p&gt;

&lt;p&gt;Mostanában divat második/sokadik nyelvet keresni, egy kicsit kiszakadni a mindennapi munka egyhangúságából, és egy másik világot megismerni, egy másik programozási nyelvben is jártasságot szerezni.&lt;/p&gt;

&lt;p&gt;Bár sokan azt mondják, hogy ha megtanulsz egy programozási nyelvet, utána a többi gyerekjáték, azért ezzel nem teljesen értek egyet. Egyrészt igaz lehet ez imperatív nyelveknél, de egy funkcionális vagy logikai nyelv már távolabb áll ettől a világtól, érdemes rápillantani a Lispre. Másrészt nem a nyelvben való jártasság, ami a programozó értékét adja, hanem a köré épülő platform, "ecosystem" ismerete. Megtanulni a nyelv szintaktikáját egy dolog, de ismerni az elterjedt keretrendszereket, könyvtárakat, best practice-eket, konvenciókat, eszközöket. Egy másik nyelv megismerése a többi nyelv használatában is fejleszt, ugyanis lehet új és hasznos ötletekkel találkozni, melyeket újra lehet használni.&lt;/p&gt;

&lt;p&gt;Én is elindultam keresni, és a Python mellett döntöttem, olvassátok, miért. A bejegyzésben egy nyelv professzionális elsajátítása mellett érvelek, és nem egyszerű felhasználásról, ami elkerülhetetlen bizonyos esetekben (pl. mennyien használnak JavaScript-et, PL/SQL-t annak alapos ismerete nélkül).&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-nV-DYJYLDMs/TfaMUblTMUI/AAAAAAAAG64/ZZUf8o97ALw/s1600/python-logo-master-v3-TM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 108px;" src="http://1.bp.blogspot.com/-nV-DYJYLDMs/TfaMUblTMUI/AAAAAAAAG64/ZZUf8o97ALw/s320/python-logo-master-v3-TM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5617831867820749122" /&gt;&lt;/a&gt;

&lt;p&gt;Semmiképp nem akartam nagyon elrugaszkodni, egy imperatív nyelvet akartam választani. Először egy olyan nyelvet akartam választani, melyet sokan használnak, a munkám során is gyakran találkozok vele, és az álláshirdetésekben is gyakran szerepel. Szóba jöttek az előbb említett nyelvek, a JavaScript, PL/SQL, valamint a PHP is. Ezeket valamilyen szinten ismerni kell, miért ne ismerje meg az ember a lehető legmélyebb szinten. A PL/SQL-lel (Procedural Language extensions to the Structured Query Language) kezdtem. Egy adatorientált imperatív nyelvről van szó (Adán alapul), mely Oracle adatbázisban fut (embedded - viccesen platformfüggetlennek nevezik, hiszen amelyik platformra van Oracle telepítve, ott megy), és emiatt erősen gyártófüggő. Mivel alapvetően adatokon dolgozunk, gyakran jöhet jól, egy adatokhoz közelibb nyelv. Én hiszek abba a modellbe, hogy ne vigyünk fel mindent Java szintre, amit meg lehet egyszerűbben oldani adatbázisban, miért ne. Felesleges bizonyos dolgokat megjáratni a rétegek között. Tipikus ilyen példa a nagy adatmennyiséggel dolgozó riportok. A nyelv sajnos nem adta meg azt, amit vártam tőle, hiányzott a szépség, az elegáns megoldások. Az alap szinttől a professzionális szintig nehéz út vezet, mely nem olyan látványos, és sokszor nincs is igazán szükség az emelt szintű dolgokra, és feltételezem, hogy a látókörömet sem tágítja annyira. Az előnye a hátránya, kizárólag adatmanipulációra használatos.&lt;/p&gt;

&lt;p&gt;A JavaScript fénykorát éli, megvan benne minden, amire a programozónak szüksége lehet, és úton útfélen találkozik vele az ember. Bár szerver oldalon is használható, azért mégis kliens oldalon jellemző. Egy erősen JavaScript/AJAX megoldásokat használó projekt után ezt is elvetettem. Igaz, hogy vonzóak a nyelv képességei, és az, hogy egy oldal újratöltéssel azonnal tesztelhető, mégis úgy találtam, hogy a JavaScript legmélyebb szintű megtanulása a User Interface-hez köt, specializálódsz, és innentől kellenek a design, tipográfiai és usability ismeretek is. Én ebbe az irányba nem akartam elmenni, én ezt külön szakmának tartom, és alapvető hibának, ha a programozókkal akarnak felhasználói felületet terveztetni (tisztelet a kivételnek).&lt;/p&gt;

&lt;p&gt;A PHP-n kellett a legtöbbet gondolkozni, hogy mivel is érveljek ellene. Az alapvető unszimpátia megvolt, de nehéz ezt objektív érvekkel alátámasztani. A Java nagy kihívója webes felületek implementálására, de lazasága miatt nem köti meg annyira meg az ember kezét (értsd: könnyebb benne gányolni). Feltehetőleg ezért nem ismerik el annyira pl. bankos környezetben, és ezért tartják még mindig a Java-t alkalmasabbnak üzleti logika megfogalmazására. Megtanulásával ott vagyok, ahol a part szakad, egy újabb technológia, mellyel kb. ugyanúgy és ugyanazt lehet kihozni webes alkalmazások terén, mint Java használatával. Szerintem ugyanolyan kvalitású fejlesztők ugyanúgy használják jól vagy rosszul mind a kettőt. A .NET-tel kapcsolatban is azt érzem, hogy szimmetrikus párja a Java-nak, szemléletbeli váltást nem hoz, sok pluszt nem nyújt.&lt;/p&gt;

&lt;p&gt;A C, C++ mindig is az alacsony szintű programozásra volt alkalmas (értsd jól, pl. kernel, beágyazott rendszerek fejlesztése, amiről tudjuk, hogy az egyik legnagyobb szaktudást igényli), ebbe az irányba szintén nem akartam elmozdulni.&lt;/p&gt;

&lt;p&gt;Így kilőttem az első követelményt, hogy lehetőleg olyan nyelvet válasszak, ami nagyon elterjedt, és divatos, és nem utolsó sorban keresett. A második legfontosabb követelmény az volt, ha nem is annyira érték emelő, legalább a mindennapi munkámban bizonyuljon hasznosnak. Egyrészt gyakran kell ilyen-olyan kisebb feladatokat megoldani, melyekhez felesleges az IDE-t elindítani, és Java alkalmazást írni rá, tipikusan shell script-ekkel megoldható problémák. Amikkel ugye az a baj, hogy nem platformfüggetlenek, persze van pár jó Windows port, Cygwin pl., melyet aktívan használok. Valamint, ami ehhez is kapcsolódik, hogy bizonyos feladatok megoldásában nagyon lassúnak találom a Java fejlesztési ciklusát, kódolás - fordítás - futtatás, gyakran az effektív munkától veszi el a kapacitásokat, legrosszabb tapasztalatom ezen belül is a portál keretrendszerekkel való fejlesztés bizonyult, ahol több perc kellett a keretrendszer elindításához.&lt;/p&gt;

&lt;p&gt;Így adott is, hogy a script nyelvek közül választottam, méghozzá a Python nyelvet. A nyelv fejlesztése 1989-ben kezdték el fejleszteni, neve a Monty Python’s Flying Circus-ből ered. A nyelvet Guido van Rossum alkotta azzal a céllal, hogy eszközt teremtsen olyanoknak, akik érdeklődnek a programozás iránt, és jó eszközt biztosítson olyanoknak, akik szeretnek és tudnak programozni. Engem az ragadott meg, hogy egy Python script ránézésre megérthető, annyira tiszta a szintaxisa, olyan érzésem volt a nyelvvel való ismerkedés közben, hogyha én nyelvet alkotnék, én is mindent így csinálnék. (Szemben mondjuk egy Perl programmal.)&lt;/p&gt;

&lt;p&gt;A Python általános célú nyelv, interpretált, interaktív, platform független és ingyenes. Nem szükséges objektum orientáltan programozni, de megvan rá a lehetőség, támogatja a többszörös öröklődést, és az operátor overloading-ot.&lt;/p&gt;

&lt;p&gt;Mivel oktatok olyan szemmel is néztem, hogy milyen gyorsan tanulható, és mennyire alkalmas oktatásra. Be kell valljam, sokkal alkalmasabb, mint a Java. Mivel a program struktúrája a behúzáson alapul (igen!), az ifjú fejlesztőket rászoktatja a formázásra, és nagyon könnyen össze tudják kötni a formátumot a struktúrával. Java-ban gyakran látom, hogy küzdenek a szintaktikával, közben nincs idejük a kódot formázni (bár ebben az IDE is segít), és szétesik nekik. Valamint aki oktatott már Java-t, és a változó deklaráció oktatásánál megkérdezi a hallgató, hogy mi az a public static void main, és miért kell kiírni, az tudja, mire gondolok.&lt;/p&gt;

&lt;p&gt;A könnyű megértést az is bizonyítja, hogy egy projektben dokumentum generálásra vezettem be, és anélkül, hogy még bárkinek is részleteztem volna, másnapra többen lemásolták és adaptálták a megfelelő script-eket kizárólag a script és a Google alapján, és mindenkinek tetszett alapvetően.&lt;/p&gt;

&lt;p&gt;Gyakran kell fájlokon matató segédprogramokat írnom, pl. napló állományok elemzésére, amire sosem találtam általános eszközt, a grep/sed párosításból kell általában kihoznom a megoldásokat. Ahhoz, hogy Java-val nyúljunk a problémához, ahhoz egyrészt osztályt, main metódust kell deklarálnunk, majd jön a rémálom, a Stream-ek, Reader-ek használata, ami ugyan koncepció szinten nagyon szép, a decorator design pattern egy remek megvalósítása, de gyakorlatban sajnos használhatatlan. Szóval jó, ha egyszerűen lehet állományokat kezelni.&lt;/p&gt;

&lt;p&gt;Ugyanúgy ilyen jellegű tool-oknál nem hátrány, ha nem kell objektum orientáltan fejleszteni, valamint nem baj, hogy dinamikus típusú, azaz nem kell előre definiálni a típusokat. Nem kell memóriát foglalgatnunk, felszabadítanunk, automatikusan kezeli az erőforrásokat. Nyelvi szinten támogatja a listákat, szótárakat, ami szintén tömör és jól olvasható kódot eredményez. Hibakezelése kivételkezelésen alapszik, mely szintén a kód tisztaságán segít, hiszen tisztán elválik a hibaág. Azért mégsem enged mindent, erős típusosság jellemzi.&lt;/p&gt;

&lt;p&gt;Dinamikus, azaz Python kifejezéseket és utasításokat ki lehet értékeltetni. Ortogonális, azaz kevés fogalommal nagy számú konstrukció írható le, melytől szintén a tanulási görbe lesz meredekebb. Reflektív, azaz futásidőben lehet az osztályokon matatni és introspektív, azaz számos eszköz, mint a debugger és a profiler is, Pythonban implementált.&lt;/p&gt;

&lt;p&gt;A Python abban hasonlít a Java-hoz hogy hatalmas osztálykönyvtár adott hozzá, csak néhány a sok közül: regexp, diff, io, objektum szerializáció, tömörítés, CSV feldolgozás, hash függvények és kriptográfiai funkciók, naplózás, többszálúság, hálózatkezelés és internetes protokollok (socket, ssl, e-mail, json, http kliens és szerver, ftp), formátumok (xml, html), I18N, GUI, stb.&lt;/p&gt;

&lt;p&gt;Néhány kódrészlet, futtatható, ha bemásolod egy állományba és "python [fájlnév.py]":&lt;/p&gt;

&lt;pre class="brush: python"&gt;# Hello World
print "Hello World"

# Listán iterálás
for t in ["a", "b"]:
 print t

# Egy állományban a # karakterrel kezdődő sorok eltávolítása
import fileinput, re

for s in fileinput.input(inplace = 1):
   print re.sub("#.*", "", s),

# Két változó értékének megcserélése
a, b = b, a

# Állomány tartalmának kiírása
f = open("file.txt")
print (f.read())

# Függvény dokumentációjának definiálása és kiírása
def add(a, b):
 "Két szám összeadása"
 return a + b

print add.__doc__

# Egy weboldal letöltése, és a linkek kigyűjtése
import httplib, re

conn = httplib.HTTPConnection("jtechlog.blogspot.com")
conn.request("GET", "/")
r = conn.getresponse()
d = r.read()
for l in re.findall("&amp;lt;a href=\"([^\"]+)\"", d):
 print l

# coding=UTF-8

print "árvíztűrő tükörfúrógép".decode("UTF-8")

# XML beolvasása
import xml.dom.minidom

document = """
&amp;lt;books&amp;gt;
&amp;lt;book title="Beginning Python From Novice to Professional" /&amp;gt;
&amp;lt;/books&amp;gt;
"""
dom = xml.dom.minidom.parseString(document)
for book in dom.getElementsByTagName("book"):
 print book.getAttribute("title")
&lt;/pre&gt;

&lt;p&gt;Ha kedvet kaptál, lájkolj!&lt;/p&gt;

&lt;p&gt;Azért nem szabad letagadni, hogy azért álltam egyből pozitívan a nyelvhez, mert létezik a Jython, ami egy JVM-en futó Python implementáció, gyakorlatilag Java bytekódot állít elő. Emiatt azonban könnyen integrálható a Java-hoz, minden Java könyvtárat tudunk Python-ból is használni.&lt;/p&gt;

&lt;p&gt;Nézzünk is egy példát, méghozzá a QDox Java 3rd party library-t, mely a Java forráskódot tudja elemezni, és API-t biztosít annak bejárására. Egy könyvtárban lévő forráskódok beolvasása, majd az osztályok és azok metódusainak bejárása a következőképp történik Java-ban:&lt;/p&gt;

&lt;pre class="brush: java"&gt;import com.thoughtworks.qdox.*;
import com.thoughtworks.qdox.model.*;
import java.io.File;

public class QDoxSample {

public static void main(String args[]) {
 JavaDocBuilder builder = new JavaDocBuilder();
 builder.addSourceTree(new File(args[0]));
 for (JavaClass clazz: builder.getClasses()) {
   System.out.println("Class: " + clazz.getName());
   for (JavaMethod method: clazz.getMethods()) {
     System.out.println("Method: " + method.getName());
   }
 }
}

}
&lt;/pre&gt;

Ugyanez Python-ban (Jython-ban), figyeljük, milyen elegánsan történik a külső függőség használata:

&lt;pre class="brush: python"&gt;import sys

sys.path.append("qdox-1.12.jar")

from com.thoughtworks.qdox import JavaDocBuilder
from java.io import File

builder = JavaDocBuilder()
builder.addSourceTree(File(sys.argv[1]))
for clazz in builder.getClasses():
  print "Class: " + clazz.getName()
  for method in clazz.getMethods():
    print "Method: " + method.getName()
&lt;/pre&gt;
 
&lt;p&gt;Mivel nem kell mindig fordítgatnunk, hanem azonnal futtatható a script-ünk, tényleg gyorsabb lehet a fejlesztés. Pont emiatt, ha valamit gyorsan ki kell próbálni Java-ban, akkor is a Jython-t veszem elő, és nem egy Java-s IDE-t.&lt;/p&gt;

&lt;p&gt;A Python azért is lehet ismerős, mert a Google a &lt;a href="http://code.google.com/intl/hu-HU/appengine/docs/python/gettingstarted/"&gt;Google App Engine-t Python-ban&lt;/a&gt; és Java-ban bocsájtja rendelkezésünkre. Ahhoz, hogy elkezdjünk fejleszteni, le kell tölteni a &lt;a href="http://code.google.com/intl/hu-HU/appengine/downloads.html"&gt;Google App Engine SDK for Python&lt;/a&gt; környezetet. Hozzunk létre egy állományt, mely kiírja standard kimenetre a szokásos üdvözlő szöveget.&lt;/p&gt;

print 'Content-Type: text/plain'
print ''
print 'Hello, world!'

&lt;p&gt;Ezt az SDK majd HTTP kérésre fogja meghívni, és a kimenetet HTTP válaszba írja vissza. Ehhez konfigurálnunk kell, hogy az összes HTTP kérést ez a script szolgálja ki:&lt;/p&gt;

&lt;pre&gt;application: helloworld
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
script: helloworld.py
&lt;/pre&gt;

&lt;p&gt;Ha elindítjuk az SDK-t, akkor a menüből a File/Add Existing Application-re kattintva válasszuk ki a script-et és a konfigurációs állományt tartalmazó könyvtárat. Az alkalmazást kiválasztva, a script-et a http://localhost:8080 címen ki is próbálhatjuk. Ha fel akarjuk tölteni a felhőbe, akkor az &lt;a href="https://appengine.google.com/"&gt;App Engine Administration Console-on&lt;/a&gt; létre kell hozni egy alkalmazást, adni neki egy nevet, melyet az előbbi konfig állományban is át kell írni. Az SDK-ban a Deploy gombot megnyomva máris próbálhatjuk az alkalmazásunkat a http://[alkalmazás neve].appspot.com címen.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-HjYq-N6Kibo/TfaMdynwvlI/AAAAAAAAG7A/y8ozwCkWTJM/s1600/google-app-engine-python-sdk.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 228px;" src="http://4.bp.blogspot.com/-HjYq-N6Kibo/TfaMdynwvlI/AAAAAAAAG7A/y8ozwCkWTJM/s320/google-app-engine-python-sdk.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5617832028623912530" /&gt;&lt;/a&gt;

&lt;p&gt;Ugyanilyen egyszerű az ütemezés, valamint a hozzáférés a Datastore-hoz, Memcache-hez, stb.&lt;/p&gt;

&lt;p&gt;Ne értsetek félre, a Java továbbra is az elsődleges nyelv és platform, melyet használok, és javaslok, de a Python remek kiegészítő tud lenni a mindennapi munkában, hiszen általános célú nyelv, és bizonyos feladatokat könnyebben és gyorsabban lehet megvalósítani.&lt;/p&gt;

&lt;p&gt;Ti mit használtok Java-n kívül önszántatokból, és nem kötelező jelleggel, és miért?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-3752345250697097633?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/3752345250697097633/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/06/masodik-nyelv-python.html#comment-form" title="19 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/3752345250697097633?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/3752345250697097633?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/06/masodik-nyelv-python.html" title="Második nyelv: Python?" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-nV-DYJYLDMs/TfaMUblTMUI/AAAAAAAAG64/ZZUf8o97ALw/s72-c/python-logo-master-v3-TM.png" height="72" width="72" /><thr:total>19</thr:total></entry><entry gd:etag="W/&quot;AkAER345cCp7ImA9WhZWEUk.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-7709122161237145798</id><published>2011-05-11T23:06:00.002+02:00</published><updated>2011-05-11T23:18:26.028+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-11T23:18:26.028+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Módszertan" /><title>Miért ne fejlesszünk saját keretrendszert?</title><content type="html">&lt;p&gt;Ahogy különböző cégeknél végzek tanácsadásokat, sok helyen látom, hogy saját keretrendszert fejlesztettek, fejlesztenek, döntenek a fejlesztése mellett. Én nem vagyok híve az ilyen jellegű saját megoldásoknak, és mivel sokszor kérdezik, és szóba kerül, leírom az ezzel kapcsolatos gondolataimat.&lt;/p&gt;

&lt;p&gt;Saját keretrendszer fejlesztésének több oka is lehet. Találkoztam több, mint tíz éves (igen, Java) rendszerekkel, ahol ilyent használnak még mindig. Ezen szoftverek abból az időből származnak, amikor még JDBC, Servlet API létezett, és nem volt egységes, kialakult irány, szabványok, kvázi szabványok. Nem volt objektum-relációs megfeleltetés, MVC webes keretrendszerek. Ebben az esetben természetesen elfogadható saját keretrendszer kifejlesztése, bár itt is erősen ajánlott haladni a korral, és ahol lehet, újabb, szabványosabb irányokba elmozdulni. Láttam Java 1.4-en beragadt projektet, régi alkalmazásszerver verziókhoz kötött rendszereket. Ilyenkor érdemes olyan keretrendszereket bevezetni, melyek nem tolakodóak (non-intrusive, azaz a kódot nem járják át az architektúrális elemek), és lépésenként bevezethetőek. Egyik projektünkbe pl. a Spring-et sikerült úgy bevezetni, hogy először csak a perzisztens rétegben, majd egyre felsőbb rétegekben, végül a felhasználói felület rétegben. Érdemes a maradvány kódokat szépen elkeríteni. Amennyiben a maradvány kódjaink nem is objektum orientáltak, használhatjuk az object wrapper megoldást, azaz a procedurális kódunkat körbevesszük egy szép, objektumorientált API-val. Ez alatt az implementációt később cserélhetjük. Barátunk ilyenkor a refactoring, amivel kapcsolatban sokan elfelejtik, hogy refactor közben nem módosítjuk a funkcionalitást. A funkcionalitás teljes megtartásával strukturáljuk át a kódunkat, hogy könnyebben átláthatóbb és továbbfejleszthetőbb legyen.&lt;/p&gt;

&lt;p&gt;Nagyon ritkán érdemes ilyenkor a teljes újraírás mellett dönteni. Nem lehet egy tíz éve fejlesztett rendszert pár hónap alatt újraírni. Kisebb lépésekben érdemes haladni. És közben viszont szerfelett mennyiségű tapasztalattal lehet gazdagodni.&lt;/p&gt;

&lt;p&gt;Másik indok az szokott lenni, hogy a megrendelőknek, vagy inkább a fejlesztőknek egyedi igényeik vannak. Ezt csak nagyon ritkán tudom elképzelni. Amennyiben egy architect kellő tapasztalattal és tudással rendelkezik, biztos, hogy a legtöbb problémára már látott valamilyen megoldást. Nem hiszem el, hogy 9 millió Java programozó, és a nem tudom mennyi egyéb programozó nem futott volna bele ugyanabba a problémába. Ez legtöbbször a fejlesztő csapat szűklátókörűségét bizonyítja. Vagy egyszerűen túl lelkesek, és szeretnék megvalósítani saját ötleteiket. Melyek gyanítom nem is annyira világmegváltóak, hogy ne lehessen azokat máshol megtalálni.&lt;/p&gt;

&lt;p&gt;Ennek kicsit finomabb változata, hogy ugyan tud a fejlesztő csapat arról, hogy vannak már létező eszközök, de nem felel meg mind az összes igénynek. Esetleg összehasonlító elemzést is végeztek, hogy melyik miért nem felel meg az igényeknek. Sajnos a legtöbbször már ismert a vágyott cél, hogy mit kell az elemzésnek kihoznia. Itt is el kell gondolkodni azon, hogy ne a tökéletességet keressük, hiszen nem biztos, hogy pont mi fogjuk azt elérni. Lehet, hogy együtt lehet élni egy eszköz hiányosságaival, ahelyett, hogy teljesen sajátot fejlesztenénk. És ha találunk egy igényeinkhez közel állót, miért ne szállhatnánk be a fejlesztésébe, vagy miért is ne tudnánk arról leágazni (, bár utóbbival is vigyázni kell, hiszen a leágazás után már elveszik az automatikus magasabb verzióra váltás lehetősége, és merge-öléssel találjuk szembe hamar magunkat - ez talán az elosztott verziókezelő rendszerek megjelenésével már kevésbé fájdalmas).&lt;/p&gt;

&lt;p&gt;A gyakori ügyfél igény az, hogy az alkalmazás minél testre szabhatóbb, minél jobban konfigurálhatóbb legyen, igen, programozás nélkül. Mikor ilyen igény merül fel, legyünk óvatosak. Hiszen mit akar az ügyfél? Azt, hogy fejlesztés nélkül újabb funkciókat tudjon maga megvalósítani. Itt már gyanút foghatunk, hiszen nem nekünk akar fizetni, hanem a problémáit maga szeretné megoldani. Azaz bizalmatlan, és ez nem biztos, hogy jó jel egy projekt elején. Egy általános eszköz fejlesztése feltehetően nagyobb költség, mintha a kívánt funkciókat, egyesével, saját keretrendszer nélkül kifejlesztetné. És sajnos sokszor láttam, hogy a személyre szabás túl absztrakt, túl technikai lett, így az ügyfél mégsem tudta használatba venni. Így ahelyett, hogy a programozók implementálták volna a funkciókat standard módon, valami saját eszközben kellett ezeket speciálisan megoldaniuk.&lt;/p&gt;

&lt;p&gt;És már el is jutottunk a 4GL, CASE és RAD eszközök világához. (Vigyázat, nem ugyanazt jelentik, csak ugyanarra a problémára szeretnének megoldást adni.) A programozókban mindig is megvolt az igény, a lustaság, hogy olyan eszközöket készítsenek, melyek saját és mások munkáját könnyítik, akár programot generáljanak. Lehessen "egérrel programozni", informatikai szaktudás nélkül. És valahogy mégis, ezek az eszközök mégsem hozták el a világmegváltást. Miért van az, hogy egy egyszerű programozási nyelv, melyhez csak parancssoros fordító volt, szövegszerkesztőben írtuk a kódot, le tudott taszítani a trónról olyan eszközöket, mint a Delphi, Oracle Forms, stb.? És most is születnek ilyen nyelvek, és megvan a létjogosultságuk, terjednek. Miért hisszük azt, hogy amibe a Borlandnak, Oraclenek beletört a bicskája, mi meg tudjuk valósítani? A nagy piros gombot, amit megnyomunk, és kiesik a szoftver?&lt;/p&gt;

&lt;p&gt;Véleményem szerint itt is látszik a ciklikusság, egyre jobban elkezdenek a nyelvek, platformok elmenni az irányba, hogy automatizálják a fejlesztést, és a végén mindig a süllyesztőben kötnek ki, és egy primitív, egyszerű eszköz veszi át a helyüket. Gondoljunk a Java ilyen irányú fejlesztéseire is, pl. VisualAge for Java, NetBeans ilyen irányú fejlesztései, stb.&lt;/p&gt;

&lt;p&gt;Itt érdemes megemlíteni a forward engineering, reverse engineering és ennek egyvelegét, a roundtrip engineeringet is. Vagy beszélhetünk a Model-driven architecture (MDA) megközelítésről is. A háttérben mindig valami kódgenerálás is áll. Ilyen projektet is gyakran láttam, és sosem tudott meggyőzni. Mi is próbálkoztunk ilyenekkel, de nem sikerült egyértelmű eredményeket elérni. A legtöbb esetben nagyon nehéz belőni a modellezés absztrakciós szintjét, amiből az alkalmazás vázát le lehet generálni, és az fejlesztéssel befejezni. Általában elmennek olyan irányba, hogy már mindent a modellbe akarnak leírni. Ezáltal egy programozási nyelvhez közeli, vagy bonyolultabb modellező nyelv sül ki belőle. A fejlesztőknek ez csak egy darabig izgalmas. Miért kell egy Java fejlesztőnek diagramot rajzolnia? Ezzel kapcsolatban tetszik az UMLet álláspontja. Egy modellt sok tíz képernyőn keresztül, sok ezer tulajdonsággal, szabállyal beparaméterezni sokkal bonyolultabb, mint egy leíró nyelvet használni erre. Sosem szerettem a Rational Rose-t. Sajnos ezen rendszerek a megbízhatatlanságukkal, kiforratlanságukkal szintén elveszik az ember kedvét. Próbáltam AndroMDA-t, openMDX-et, de nagyon behatároltak voltak és hibáktól hemzsegtek. Próbáltam Posseidon for UML, ArgoUML, StarUML eszközöket. Kimérve mindig sokkal gyorsabb volt Java forráskódot írni, Java interfészekkel tervezni, JavaDoc-ot írni, és abból visszagenerálni a modellt. Nem, a Spring Roo-ban sem hiszek.&lt;/p&gt;

&lt;p&gt;Nézzük, milyen hatása van a saját keretrendszerek a programozókra. Gyakran láttam, hogy egy-két okos programozó írta a keretrendszert, és a kevésbé okosnak tartott programozók csak használták. Ismerős? Kérdeztétek már meg, mit gondolnak úgy igazán a keretrendszerről? Egyrészt nagyon sok munkával megtanulnak egy olyan dolgot melyet sehol máshol nem tudnak használni, melytől nem lesznek többek, mely nem motiválja őket, nem írható be az önéletrajzukba. Ki vannak zárva egy körből, nem hozhatnak döntéseket, nem tudnak a miértről. Nem kapnak megfelelő szintű támogatást, dokumentációt. Hallottam programozóról, aki úgy kezdi az interjút, hogy kell-e saját keretrendszerben dolgozni. Ha a válasz igen, akkor nem folytatja az interjút.&lt;/p&gt;

&lt;p&gt;A fejlesztők manapság mindig modern, divatos, trendi technológiákkal akarnak dolgozni. Nehéz őket saját keretrendszerrel megfogni.&lt;/p&gt;

&lt;p&gt;Gyakran láttam, hogy a keretrendszer alkotójának elege lett, továbbállt, otthagyta a rendszerét. Olyanoknak kellett átvenniük, akik nem értették, nem látták át teljesen, nem voltak tisztában a döntési folyamatokkal. A keretrendszer alkotókat gyakran nem lehet elég sokáig lekötni, aktív, kreatív emberek, akik nem állapodnak meg, újabb és újabb ötleteket próbálnak ki, és folyamatosan patkolandó dolgokat hagynak maguk után. Mivel pezseg a vérük, nem töltik idejüket olyan haszontalan dolgokkal, hogy a legapróbb részleteket is átgondolják, a legutolsó részt is lefejlesszék és dokumentálják a rendszert.&lt;/p&gt;

&lt;p&gt;Ilyen fejlesztők gyakran abba a hibába esnek, hogy egy problémát túlzottan általánosan próbálnak megvalósítani. Igaz ugyan, hogy most nem kell, de később jól jöhet. Gyakran lehet a YAGNI (You ain't gonna need it) elvet hallani, hogy pontosan azt fejlesszük le, amire szükség van, ne fejlesszünk olyan funkcionalitást, amire azt gondoljuk, hogy majd szükség lehet rá. Vagy nem lesz rá szükség, vagy nem úgy lesz rá szükség. Az ügyfél ilyen szempontból hatalmas kreativitással rendelkezik, hogy olyant kérjen, amire úgysem gondoltunk.&lt;/p&gt;

&lt;p&gt;Milyen lehet egy ilyen rendszer minősége? Gondoljunk bele, hogy olyan keretrendszereknél, mint a Spring, Struts, stb., melyet több ezren használnak, tesztelnek, nézegetik a forrását, milyen gyakran jegyeznek be hibákat, milyen gyakran frissülnek, milyen a fejlesztői aktivitás. Hogy gondolhatjuk, hogy pár fejlesztővel ugyanolyan szintű eszközt képesek vagyunk gyártani? Úgy, hogy nekünk nem ez a fő profilunk, hanem fő munkaidőben az ügyfelek óhajait, problémáit kell megoldanunk. A keretrendszer fejlesztésére, unit tesztelésére, dokumentációjára sosem marad idő. Előbb az égető problémákat kell megoldani, a funkcionalitásra kell összpontosítani, az ügyfél azért fizet.&lt;/p&gt;

&lt;p&gt;Miért jó ez a menedzsmentnek? Örülnek, ha olyanra költik a pénzt, aminek semmi látszatja nincs? Nem lesz tőle több képernyő. Nem tőle lesz több funkció. A keretrendszer implementálásával csak a lehetőségét valósítjuk meg, hogy a felhasználó számára alkalmazást fejlesszünk. De még nem fejlesztettünk egy percet sem. Mennyire felel meg ez a manapság annyira oly divatos agilis módszertanoknak? Mennyire követi a KISS (keep it simple ...) elvet?&lt;/p&gt;

&lt;p&gt;A keretrendszer azért kell, hogy a képernyőket, funkcionalitást gyorsabban ki tudjuk fejleszteni? Hányszor hangzott el, hogy ezt nem tudja a keretrendszer, ezt a keretrendszerben kell kifejleszteni, ez így túl lassú lenne a keretrendszerben, stb.?&lt;/p&gt;

&lt;p&gt;Bizonyos emberekben valamilyen blokk van, hogy más munkáját használják fel. Kritizálják, mindenből sajátot akarnak írni, saját XML parser, saját protokoll, saját formátum, saját keretrendszer. Ismert a jelenség, nem csak informatikában, "Not Invented Here (NIH)", általában pejoratívan használják.&lt;/p&gt;

&lt;p&gt;Ezek a keretrendszerek nem felelnek meg a szabványoknak. Nem széleskörűen elterjedtek. Nem lehet az utcáról felvenni egy olyan programozót, aki értene hozzá. Nagyon drága a betanítás. Hiszen nincsenek képzett oktatók, nincs oktató anyag. Általában elé adják az új fejlesztő elé, és próbálja meg egyedül felfejteni (a vezető programozónak nincs ideje pátyolgatni), próbálja meg az eddigi megoldásokat lemásolni. Csak általában egy keretrendszer használatával is ugyanarra a problémára a fejlesztők három különböző megoldást használtak.&lt;/p&gt;

&lt;p&gt;Nem csak már bevált, működő, széles körben elterjedt keretrendszereket érdemes használni, hanem érdemes (kvázi) szabvány API-k közül választani, ami alatt cserélhetjük az implementációt. Cseréltünk már Hibernate-et EclipseLink-re, mert jobban megfelelt az igényeinknek. Építkezzünk modulárisan, hiszen csak így van lehetőségünk a modulok esetleges későbbi kiváltására, programozzunk interfészekkel, használjunk rétegeket, tartsuk szem előtt a loose coupling, high cohesion elveket.&lt;/p&gt;

&lt;p&gt;Nagyon fontos, hogy az ezzel kapcsolatos viták során mindig eljutunk a szép architektúra, szép kód fogalmához. A szépség szubjektív. Ízlésről nem vitatkozunk. Parttalannak érzem az XML kontra programozott konfiguráció, a NetBeans kontra Eclipse vitákat, az annotációk túlzott használatát elítélő kijelentéseket. Érvek, objektív érvek kellenek. És még sajnos így is beleütközünk abba, hogy minden megoldásnak van jó és rossz oldala is. És ráadásul lehetnek ezek egyensúlyban is. Döntsünk ésszerűen, érveljünk ésszerűen.&lt;/p&gt;

&lt;p&gt;Félreértés ne essék. A postban direkt sarkítok. Próbálok erős érzelmeket kiváltani. Nem azt mondom, hogy ne fejlesszünk saját keretrendszert, mert akkor még mindig assembly kódot írhatnánk. Vannak okos emberek, okos ötletekkel. Sőt, sok esetben nem is kell nagy ötlet, csak egy elegáns megvalósítás. De mindig alaposan gondoljuk át. Ne játszunk a cégünk, vagy a megrendelő pénzével. Saját keretrendszer kifejlesztése nagyon-nagyon drága, a legtöbb projekt ezt nem bírja el. Ne játszunk a kollégáink türelmével. Ne a saját önzésünk vezéreljen, hanem mérlegeljünk. A kreativitásunkat máshol éljük ki, úgy, hogy az ne menjen egy cég, egy csapat, egy projekt rovására. Próbáljunk különböző vérmérsékletű, kvalitású embereket is bevenni a döntési folyamatba. Legyen lelkes, legyen kétkedő, legyen tapasztalt, legyen kezdő.&lt;/p&gt;

&lt;p&gt;Azt hiszem, hogy a legtöbben azért beleestünk abba a hibába, hogy saját keretrendszert fejlesztettünk, vagy kezdtünk fejleszteni. Ne szégyelljük, próbáljunk idejében váltani, tanulni belőle.&lt;/p&gt;

&lt;p&gt;Érezhető, hogy a szoftverfejlesztés során nagyon fontos az emberi tényező. Nagyon kevés mindenki által elfogadott alapelv van, mindenre lehet érvet/példát találni, és annak ellenkezőjére is. Kevés, hogyha jó technológusok vagyunk, néha jobb lenne pszichológusnak lenni. Próbáljuk felismerni és kihasználni az tipikus fejlesztői viselkedésformákat.&lt;/p&gt;

&lt;p&gt;Van a postban olyan, amit ti is gyakran tapasztaltok? Mi a véleményetek?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-7709122161237145798?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/7709122161237145798/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/05/miert-ne-fejlesszunk-sajat.html#comment-form" title="25 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/7709122161237145798?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/7709122161237145798?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/05/miert-ne-fejlesszunk-sajat.html" title="Miért ne fejlesszünk saját keretrendszert?" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>25</thr:total></entry><entry gd:etag="W/&quot;CkcDQngzeyp7ImA9WhZQEEU.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-2002559707916709456</id><published>2011-04-18T00:22:00.008+02:00</published><updated>2011-04-18T00:41:13.683+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-18T00:41:13.683+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Servlet" /><category scheme="http://www.blogger.com/atom/ns#" term="JNDI" /><category scheme="http://www.blogger.com/atom/ns#" term="EJB" /><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><category scheme="http://www.blogger.com/atom/ns#" term="Java EE" /><title>Konfigurációs paraméterek EJB és web rétegben Glassfish alkalmazásszerveren</title><content type="html">&lt;p&gt;Technológiák: Glassfish 3.1, Maven 2.2.1, EJB 3.0 - 3.1, JNDI&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://jtechlog.blogspot.com/2011/02/konfiguracios-parameterek-ejb-retegben.html"&gt;Konfigurációs paraméterek EJB és web rétegben JBoss alkalmazásszerveren&lt;/a&gt; postban leírtam, hogyan lehet JBoss-ban konfigurációs paramétereket felvenni, JNDI segítségével. Ebben a postban leírom, hogy történik mindez Glassfish alatt.&lt;/p&gt;

&lt;p&gt;Az aktualizált példaprojekt &lt;a href="http://dl.dropbox.com/u/7683931/jtechlog/earconfig.zip"&gt;letöltehető.&lt;/a&gt; Ahhoz, hogy lefordítsuk, adjuk ki az mvn package parancsot a főkönyvtárban. Ahhoz, hogy a Glassfish-re telepítsük, a earconfig-ear/target könyvtárban előállt earconfig-ear-1.0-SNAPSHOT.ear kell a Glassfish-re telepítenünk. Persze ezt is megoldhatjuk Maven-ből is, ehhez először indítsuk el a Glassfisht. Az earconfig-ear/pom.xml-ben a glassfish3x profile-ban van definiálva a telepítés, ezért ezzel kell indítani, valamint felül kell definiálnunk jópár paramétert (host, port, stb.). Ehhez átírhatjuk a pom.xml-t, de a -D kapcsolót is használhatjuk a paraméterek felülbírálásához. Tehát adjuk ki a &lt;code&gt;mvn -P glassfish3x cargo:deploy&lt;/code&gt; parancsot a earconfig-ear könyvtárban. Érdemes megjegyezni, hogy Glasshfish 3.1-ben az adminisztrátori felhasználónév admin, és nincs jelszó megadva. Régebben ez admin/adminadmint volt. Valamint figyelni kell arra, hogy az asadmin-nak biztonsági okból már nem lehet paraméterként átadni a jelszót, hanem fájlból olvassa fel. A Cargo nem enged Glassfish-re fájl másolásos telepítést, kizárólag az asadmin-t hajlandó hívni. Ezért eltesz egy állományt a temp könyvtárban, nálam a "C:\Documents and Settings\vicziani\Local Settings\Temp\cargo" helyen. Volt olyan, hogy hiába frissítettem a jelszót a pom.xml-ben, ez a fájl nem változott, így nem sikerült a telepítést. Megoldásaként csak le kellett törölni ezt az állományt. Még egy trükk. Ha nem állítottuk át a jelszót, hanem üresen hagytuk a Glassfish telepítés után, akkor is meg kell adni a Cargo-nak az üres String-et (&amp;lt;cargo.remote.password&amp;gt;${glassfish.password}&amp;lt;/cargo.remote.password&amp;gt;), különben nem sikerül a telepítés. A JBoss-sal ellentétben, itt ha az alkalmazást frissíteni akarjuk, nem elegendő a cargo:deploy parancs, hanem a cargo:redeploy parancs kell, mert a Glassfish jelzi, hogy már van alkalmazás telepítve.&lt;/p&gt;

&lt;p&gt;Glassfish-ben a paraméterek, azaz a rendszer paraméterek (system properties) és a JNDI nevek megadása is háromféleképpen történhet: webes adminisztrátori felületen, parancssori adminisztrátori felületen, vagy konfigurációs állományban.&lt;/p&gt;

&lt;p&gt;A system property megadása a webes felületen a server menüpontban a Properties/System properties képernyőn lehetséges. Itt menet közben tetszőlegesen is át lehet írni.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-6e7EtuGMqJE/TatoRtBeklI/AAAAAAAAGSQ/WFTCrFa_F0A/s1600/jndi_glassfish_0.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 189px;" src="http://2.bp.blogspot.com/-6e7EtuGMqJE/TatoRtBeklI/AAAAAAAAGSQ/WFTCrFa_F0A/s320/jndi_glassfish_0.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5596681615290831442" /&gt;&lt;/a&gt;

&lt;p&gt;&lt;a href="http://download.oracle.com/docs/cd/E18930_01/html/821-2416/ghcjc.html"&gt;Parancssorban is&lt;/a&gt; fel lehet venni, és listázni.&lt;/p&gt;

&lt;pre&gt;
C:\Kaffe\glassfish3\glassfish\bin&gt;asadmin create-system-properties \
 earconfig.system.property="Hello System Property!"
Command create-system-properties executed successfully.

C:\Kaffe\glassfish3\glassfish\bin&gt;asadmin list-system-properties
The target server contains following 1 system properties
earconfig.system.property=Hello System Property!
Command list-system-properties executed successfully.
&lt;/pre&gt;

&lt;p&gt;A konfiguráció a \glassfish3\glassfish\domains\domain1\config\domain.xml XML konfigurációs állományba kerül bele.&lt;/p&gt;

&lt;p&gt;A JNDI megadása a webes felületen a Resources/JNDI/Custom Resources menüpontban lehetséges. Itt vegyünk fel egy új erőforrást a megfelelő JNDI névvel. Több típus közül is választhatunk. Az értékek megadása un. factory-kkal történik, és a Glassfish tartalmaz pár &lt;a href="http://download.oracle.com/docs/cd/E19798-01/821-1752/giyvw/index.html"&gt;előre gyártott factory-t&lt;/a&gt;: JavaBeanFactory, PropertiesFactory, PrimitiviesAndStringFactory, URLFactory. Amennyiben String-et akarunk felvenni, típusnál a "java.lang.String"-et kell kiválasztani, a Factory Class ilyenkor "org.glassfish.resources.custom.factory.PrimitivesAndStringFactory" lesz, és fel kell venni egy property-t value névvel. Legyen az értéke a "Hello JNDI!".&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-XY1WEM1doEM/TatoVkooENI/AAAAAAAAGSY/q21lhPVBunY/s1600/jndi_glassfish_1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 206px;" src="http://4.bp.blogspot.com/-XY1WEM1doEM/TatoVkooENI/AAAAAAAAGSY/q21lhPVBunY/s320/jndi_glassfish_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5596681681758589138" /&gt;&lt;/a&gt;

&lt;p&gt;URL esetén hasonló a helyzet, de a Resource Type java.net.URL és a factory org.glassfish.resources.custom.factory.URLObjectFactory. Itt property-nek a spec-t kell megadni, érték legyen pl. "http://jtechlog.blogspot.com". Properties megadása már érdekesebb. Itt is a Resource Type-nál ki kell választani a java.util.Properties-t (, a factory org.glassfish.resources.custom.factory.PropertiesFactory lesz). Itt a properties-nél megadhatjuk a név és érték párokat is. Amennyiben egy speciálisat adunk meg org.glassfish.resources.custom.factory.PropertiesFactory.fileName néven, az értéknél szereplő properties fájlt fogja betölteni (, szemben a dokumentációval, ami csak fileName-t ír). A fájlnév lehet abszolút, vagy a Glassfish telepítési könyvtárához képest relatív. A properties állományt szerkesztéskor szépen újra is olvassa. Amennyiben a fájlban és a felületen is megadtunk kulcs-érték párokat, a Glassfish összefésüli ezeket. A JBoss-ban definiálható InetAddress típushoz itt nem találtam factory-t.&lt;/p&gt;

&lt;p&gt;A JNDI bejegyzések ugyanúgy &lt;a href="http://download.oracle.com/docs/cd/E18930_01/html/821-2416/gglpq.html"&gt;parancssorból is konfigurálhatóak&lt;/a&gt;. A Glassfish egy régebbi verziójában volt webes JNDI browser felület. Ez most egyelőre csak parancssorból elérhető.&lt;/p&gt;

&lt;pre&gt;
C:\Kaffe\glassfish3\bin&gt;asadmin create-custom-resource \
--restype java.lang.String \
--factoryclass org.glassfish.resources.custom.factory.PrimitivesAndStringFactory \
--property value="Hello JNDI!" earconfig/string
Custom Resource earconfig/string created.
Command create-custom-resource executed successfully.

C:\Kaffe\glassfish3\bin&gt;asadmin list-custom-resources
earconfig/url
earconfig/properties
earconfig/string
Command list-custom-resources executed successfully.
&lt;/pre&gt;

&lt;p&gt;Az értékek ugyanúgy a \glassfish3\glassfish\domains\domain1\config\domain.xml XML konfigurációs állományba kerülnek. Akár saját factory osztályokat is használhatunk.&lt;/p&gt;

&lt;p&gt;Ezeket elvégezve az alkalmazás a http://localhost:8080/earconfig/ címen érhető el, és a következőt kell kiírnia:&lt;/p&gt;

&lt;pre&gt;
A projekt bemutatja, hogy hogyan lehet Java EE alkalmazásból konfigurációs paramétereket beolvasni.

    * System property EJB rétegben (kulcs: earconfig.system.property): Hello \
System Property!
    * Context lookup (JNDI) EJB rétegben (JNDI nevek: earconfig/string, \
 earconfig/url, earconfig/inetaddress, earconfig/properties): [Hello JNDI!, \
http://jtechlog.blogspot.com, null, {key=value, key2=value2, key1=value1}]
    * System property web rétegben (kulcs: earconfig.system.property): Hello System Property!
    * Context lookup (JNDI) web rétegben (JNDI nevek: earconfig/string, \
 earconfig/url, earconfig/inetaddress, earconfig/properties): [Hello JNDI!, \
http://jtechlog.blogspot.com, null, {key=value, key2=value2, key1=value1}]
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-2002559707916709456?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/2002559707916709456/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/04/konfiguracios-parameterek-ejb-es-web.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/2002559707916709456?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/2002559707916709456?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/04/konfiguracios-parameterek-ejb-es-web.html" title="Konfigurációs paraméterek EJB és web rétegben Glassfish alkalmazásszerveren" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-6e7EtuGMqJE/TatoRtBeklI/AAAAAAAAGSQ/WFTCrFa_F0A/s72-c/jndi_glassfish_0.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEYNR3kyfSp7ImA9WhZRGE0.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-2933517858616487299</id><published>2011-04-14T19:45:00.004+02:00</published><updated>2011-04-14T20:36:36.795+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-14T20:36:36.795+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="monitorozás" /><category scheme="http://www.blogger.com/atom/ns#" term="VisualVM" /><category scheme="http://www.blogger.com/atom/ns#" term="glassfish" /><category scheme="http://www.blogger.com/atom/ns#" term="JMX" /><title>VisualVM Glassfish monitorozás</title><content type="html">&lt;p&gt;Technológiák: Java SE 6 Update 23, VisualVM 1.3.2, Glassfish 2.1.1.&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://visualvm.java.net/"&gt;VisualVM&lt;/a&gt; egy vizuális felület, mellyel a Java virtuális gépet monitorozhatjuk. Előnye, hogy a JDK-ba is belekerült, pl. a JDK 6 Update 23-ban a VisualVM 1.3.1 verziója szerepel, a jvisualvm parancs kiadásával azonnal ki is próbálhatjuk. Csatlakozhatunk lokális és távoli virtuális gépekhez is, így akár egy teljes hálózat Java alapú rendszereit monitorozhatjuk. Nem csak külön futtatható, de akár a NetBeans vagy Eclipse fejlesztőeszközbe is plugin-ként telepíthető.&lt;/p&gt;

&lt;p&gt;A virtuális gépről olyan alap információkat szolgáltat, mint a PID, indított osztály, parancssori paraméterek, Java Home, JVM pontos verziószáma, valamint a rendszerváltozók. Olyan teljesítmény adatokat tudhatunk meg vele, mint a CPU felhasználás, memória felhasználás, betöltött osztályok száma, szálak száma, stb. A CPU esetén külön mutatja az alkalmazás és a GC által felhasznált processzor időt. Meghívhatjuk a GC-t is. Memóriánál külön megtekinthetjük a Heap és a Permgen kihasználtságát is (, ez utóbbiba kerülnek az osztálydefiníciók). Kérhetünk Heap Dump-ot, mely egy pillanatfelvételt készít a memóriáról. Megmondja, hogy melyik osztályból hány objektum került példányosításra, és ezeket meg is nézhetjük a grafikus felület segítségével, de akár OQL nyelven lekérdezéseket is végezhetünk. Szálak esetén valós időben nézhetjük a szálak állapotát. Kérhetünk Thread Dump-ot is, melyből kiderül, hogy melyik szál éppen mit csinál, melyik kódsorban áll.&lt;/p&gt;

&lt;p&gt;CPU és memória profiler funkciókkal is rendelkezik. CPU profile esetén megtudhatjuk, hogy a CPU idejének hány százalékát melyik metódusban tölti. Snapshot-okat is kérhetünk, ezeket lementhetjük, és később, vagy akár más gépen is elemezhetjük. Memória profile estén az objektumok számát és területfoglalását figyeli. Itt is kérhetünk snapshot-ot, és ezeket össze is hasonlíthatjuk. Ez egy remek eszköz arra, hogy teszt előtt és után is készítünk egy snapshot-ot, és összehasonlítva azt látjuk, hogy a teszt után mennyivel több objektumunk lett, osztályonként lebontva. A profile azért eléggé megakaszthatja az alkalmazásunkat.&lt;/p&gt;

&lt;p&gt;A JConsole bővíthető, &lt;a href="http://visualvm.java.net/plugins.html"&gt;plugin&lt;/a&gt;-okat lehet hozzá telepíteni. Ezt az alkalmazásból, futás közben is megtehetjük, a Tools/Plugins menüpontban. Érdekes a VisualVM-MBeans plugin, mellyel gyakorlatilag JMX műveleteket tudunk elvégezni. A JMX-ről már írtam a &lt;a href="http://jtechlog.blogspot.com/2009/09/java-monitorozas-es-menedzsment.html"&gt;Java monitorozás és menedzsment&lt;/a&gt; postban, míg a Tomcat JMX adminisztrációjáról a &lt;a href="http://jtechlog.blogspot.com/2010/07/tomcat-jmx-tuzfal.html"&gt;Tomcat JMX tűzfalon keresztül&lt;/a&gt; postban.&lt;p&gt;

&lt;p&gt;Másik érdekes plugin a Visual GC, mely a memóriát memória területekre lebontva monitorozza, külön az Old, Survivor és Eden területeket.&lt;p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-BAiXFoKOr5U/Tac-laUHnMI/AAAAAAAAGRQ/Jb5BhH0Os_o/s1600/visualvm_visualgc.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 233px;" src="http://2.bp.blogspot.com/-BAiXFoKOr5U/Tac-laUHnMI/AAAAAAAAGRQ/Jb5BhH0Os_o/s320/visualvm_visualgc.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5595509874470919362" /&gt;&lt;/a&gt;

&lt;p&gt;Szintén érdekes a Glassfish plugin, mellyel a Glassfishre érkező HTTP kéréseket tudjuk &lt;a href="http://java.dzone.com/articles/monitoring-glassfish"&gt;monitorozni&lt;/a&gt;, valamint a telepített web alkalmazásokat, élő sessionök számát, valamint az egyes servleteket is külön-külön. Ehhez azonban a Glassfishen is &lt;a href="http://qants.wordpress.com/tag/glassfish-plugin-for-visualvm/"&gt;konfigurálnunk kell&lt;/a&gt;. A bal oldali menüben ki kell választani az Application Server menüpontot, ott a Monitor majd Runtime fület választani, majd a Configura Monitoring linkre kell kattintani. Itt a HTTP Service és a Web Container monitorozását kell minimum LOW-ra állítani. Utána nem árt újraindítani a VisualVM-et, a Glassfish-t nem kell. Sajnos csak 2-es Glassfishhel megy, a 3-as sorozattal próbáltam, de nem sikerült.&lt;/p&gt;

&lt;a rel="lightbox" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-kffMx1gHwbQ/Tac-heTHrZI/AAAAAAAAGRI/JUVbWXJl4Bc/s1600/visualvm_glassfish.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 233px;" src="http://2.bp.blogspot.com/-kffMx1gHwbQ/Tac-heTHrZI/AAAAAAAAGRI/JUVbWXJl4Bc/s320/visualvm_glassfish.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5595509806820994450" /&gt;&lt;/a&gt;

&lt;p&gt;A VisualVM a &lt;a href="http://platform.netbeans.org/"&gt;NetBeans Platformra&lt;/a&gt; épül. Természetesen &lt;a href="http://visualvm.java.net/api-quickstart.html"&gt;mi is írhatunk&lt;/a&gt; saját plugineket.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-2933517858616487299?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/2933517858616487299/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/04/visualvm-glassfish-monitorozas.html#comment-form" title="0 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/2933517858616487299?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/2933517858616487299?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/04/visualvm-glassfish-monitorozas.html" title="VisualVM Glassfish monitorozás" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-BAiXFoKOr5U/Tac-laUHnMI/AAAAAAAAGRQ/Jb5BhH0Os_o/s72-c/visualvm_visualgc.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUUNSH0yfCp7ImA9WhdXEUo.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-5695982303749707840</id><published>2011-02-27T23:33:00.010+01:00</published><updated>2011-08-24T11:14:59.394+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-24T11:14:59.394+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="EJB" /><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><category scheme="http://www.blogger.com/atom/ns#" term="JBoss" /><category scheme="http://www.blogger.com/atom/ns#" term="Java EE" /><title>Konfigurációs paraméterek EJB és web rétegben JBoss alkalmazásszerveren</title><content type="html">&lt;p&gt;Technológiák: JBoss AS 5.1 - 6.0.0, Maven 2.2.1, EJB 3.0 - 3.1, JNDI&lt;/p&gt;

&lt;p&gt;&lt;emp&gt;Frissítés:&lt;/emp&gt; 2011. március 6. - az ismertetett megoldás nem felelt meg a szabványnak, JBoss 6-on nem is működött, javítottam. A példa projektet JBossConfig-ról átneveztem EarConfig-ra. Valamint beletettem egy magyarázó leírást az ENC használatáról.&lt;/p&gt;

&lt;p&gt;&lt;emp&gt;Frissítés:&lt;/emp&gt; 2011. április 18. - ugyanezt leírtam Glassfish-sel is egy későbbi &lt;a href="http://jtechlog.blogspot.com/2011/04/konfiguracios-parameterek-ejb-es-web.html"&gt;postban&lt;/a&gt;. Ennek megfelelően kicsit módosítottam a projektet, hogy mindkét alkalmazásszerveren működjön a build.&lt;/p&gt;

&lt;p&gt;Ha az alkalmazás futtatásához szükséges konfigurációkat paramétereket akarunk tárolni, beolvasni, rengeteg lehetőségünk van. Tapasztalatom szerint szinte mindenhol másképp van megoldva. Ha az alkalmazás tartalmazhatja ezeket a beállításokat, akkor belecsomagolhatjuk, de ekkor figyelembe kell venni, hogy a konfiguráció váltásakor újra kell telepítenünk. Ekkor a konfigurációk szerepelhetnek kódban konstansként, properties állományban (melyet classpath-ról töltünk be), Spring esetén az application context xml-ben, EJB-k esetén enviroment variable-ként (ejb-jar.xml-ben definiálva). Ha különböző környezetek vannak, akkor a build folyamat során kell arról gondoskodni, hogy különböző konfigurációs állományok kerüljenek a különböző környezetekre telepítendő alkalmazásokban.&lt;/p&gt;
&lt;p&gt;Ezen megoldások kevésbé flexibilisek, hiszen módosításkor újra kell telepíteni az alkalmazást, valamint sokkal szebb megoldás, ha környezetenként is ugyanaz a telepítendő alkalmazásunk van, és a környezetfüggő dolgok az alkalmazáson kívül szerepelnek.&lt;/p&gt;
&lt;p&gt;EJB vagy web konténer esetén jó megoldás lehet kevés számú paraméter esetén a system property, több paraméter esetén a JNDI használata is. Semmiképp nem szeretem a fájlrendszerben itt-ott elbújó állományokat, hiszen nagyon nehéz a nyomon követésük, verziókezelésük általában el szokott maradni. Ha nagyon muszáj, talán szóba jöhet az, hogy egy system property, vagy egy JNDI bejegyzés tartalmaz egy referenciát a konfigurációs állományra. A JNDI használatánál arra kell különösen figyelni, hogy konténerek között működő, platformfüggetlen megoldást találjunk.&lt;/p&gt;
&lt;p&gt;Állományt esetén kérdés annak formátuma is. Leggyakoribb a standard properties állomány, melyről páran nem tudják, hogy a Java 1.5 óta kezel XML állományokat is, valamint az 1.6-os Java-tól kezdve képes Writer-ből is tölteni, tehát az állomány karakterkódolása lehet bármilyen, nem kell a native2ascii eszközt használni. Java 1.4-ben megjelent a java.util.prefs is, mely már sokkal több mindent tud, még sem terjedt el, és nem is hallottam jókat felőle. Lehet egyedi XML, de ekkor nekünk kell gondoskodni a beolvasásáról, valamilyen XML könyvtár használatával, netalántán XML binding-gal.&lt;/p&gt;
&lt;p&gt;Persze talán a legteljesebb megoldás az adatbázisban történő tárolás, de az itt tárolt értékek szerkesztése koránt sem olyan triviális.&lt;/p&gt;
&lt;p&gt;A konfigurációs paraméterek kezelése esetén a tárolás után a fő gondom az szokott lenni, hogy hogyan lehet azokhoz hozzáférni, azokat szerkeszteni. A fájl esetén a legegyszerűbb a helyzet, hiszen egy egyszerű szövegszerkesztővel el lehet végezni a módosításokat. Lehet saját webes felület, de ezt külön kell fejleszteni, karbantartani, illetve a parancssorhoz szokott adminisztrátoroknak sem szokott tetszeni, plusz egy probléma, cím, amit meg kell jegyezni. Ha a konténer adminisztrációs felületébe épül, akkor talán kicsit jobb a helyzet. Az adatbázisban tárolt konfigurációs paraméterek esetén lehet nekiesni egy SQL klienssel, de szintén ellenérzést válthat ki, valamint kérdés, hogy milyen gyakran olvassa újra az alkalmazás. Java-ban van persze erre is szabvány, a JDK részét képző JMX, de sajnos én nem nagyon hiszek benne, nem láttam még olyan üzemeltetést, amelyet levett volna a lábáról, és minden probléma nélkül használnák. Talán előrelépés lenne, ha a jelenleg létező felügyeleti rendszerekbe egyszerűen lehetne integrálni.&lt;/p&gt;
&lt;p&gt;Kérdés, hogy a változások mikor lépnek életbe. Hiszen nem biztos, hogy a leghatékonyabb minden esetben újra beolvasni. Általában valamilyen cache mechanizmus használható. Persze itt megadhatunk lejáratot, hogy mennyi idő után olvassa újra, vagy megadhatunk eseményeket, melyek hatására biztos újra megtörténik az újra beolvasás. Állomány szerkesztése esetén ez egyáltalán nem triviális, hiszen vagy az állományt mindig ellenőrizni kell, vagy egy szálat kell indítani, ami megnézi, hogy módosult-e. Ez utóbbi EJB környezetben megint problémás. Erre megoldás lehet a Java 7-ben megjelenő, már régóta várt WatchService API, mely operációs rendszer szinten figyeli az állomány hozzáféréseket, és értesíti az eseményre feliratkozókat.&lt;/p&gt;
&lt;p&gt;Minden megoldásnál még bezavar a &lt;emp&gt;cluster-es működés&lt;/emp&gt;, hiszen kérdés esetén minden egyes node-on szerkeszteni kell az állományt (itt az időbeli eltolódás miatt lehet szétcsúszás, illetve érdekes, hogy hogyan lehet a node-okat egyenként címezni), vagy valahogy a node-ok megbeszélik egymás között a módosításokat. Esetleg vannak olyan konfigurációs beállítások, melyek node-onként eltérnek?&lt;/p&gt;
&lt;p&gt;Tehát konfigurációs paraméterek tárolásakor és a hozzáférés szerint a következőket kell mérlegelnünk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Értékeik ismertek-e a build folyamatnál?&lt;/li&gt;
&lt;li&gt;Okoz-e problémát, ha a konfigurációs paraméterek csak az alkalmazás újratelepítésével módosíthatóak?&lt;/li&gt;
&lt;li&gt;Milyen gyorsan kell a változnak?&lt;/li&gt;
&lt;li&gt;Milyen gyorsan kell a változásoknak életbe lépniük?&lt;/li&gt;
&lt;li&gt;Milyen szintű felhasználók fogják használni, és nekik mi a megszokott, kényelmes eszköz (parancssor, állomány, adatbázis, felügyeleti rendszer, webes kliens)?&lt;/li&gt;
&lt;li&gt;Egy vagy több helyről jön? Pl. lehet, hogy bizonyos dolgokat a komponens fejlesztők, az application assembler (aki összerakja az alkalmazást darabokból), a telepítő, üzemeltető, netalántán a végfelhasználó is állíthat?&lt;p&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;Van-e cluster-ezett működés. Okoz-e problémát, ha minden cluster tagot egyenként kell beállítgatni?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Persze vannak keretrendszerek, melyek segíthetnek a megvalósításban, melyek a következő funkciókkal rendelkezhetnek:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Típusosság, bonyolultabb adatstruktúrák támogatása&lt;/li&gt;
&lt;li&gt;Paraméter értékek behelyettesítése már paraméter értékekbe&lt;/li&gt;
&lt;li&gt;Default értékek&lt;/li&gt;
&lt;li&gt;Különböző források támogatása&lt;/li&gt;
&lt;li&gt;Különböző forrásból jövő konfigurációk összefésülése, hierarchikus betöltés&lt;/li&gt;
&lt;li&gt;Módosítások mentése&lt;/li&gt;
&lt;li&gt;Újratöltés&lt;/li&gt;
&lt;li&gt;Observer tervezési minta támogatása, értesítés, ha változik egy paraméter érték&lt;/li&gt;
&lt;li&gt;JMX hozzáférés&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jó ötlet, hogy az alkalmazás rendelkezzen egy default konfigurációval is, amit az alkalmazás tartalmaz, ami a fejlesztői környezetre konfigurált, így egy checkout után azonnal futtatható az alkalmazás, és ezt érdemes teszt és éles környezetben felülbírálni.&lt;/p&gt;
&lt;p&gt;Amennyiben a konfigurációhoz különböző szerepkörrel rendelkező felhasználók is hozzáférhetnek, szükséges lehet bizonyos paraméterek titkosítására is. Ilyen lehet pl. egy adatbázis kapcsolathoz tartozó jelszó. A probléma jellegéből adódóan természetesen nem lehet teljes védelmet elérni, hiszen az alkalmazásnak is hozzá kell férnie valahogy a jelszóhoz, és legdurvább esetben egy kód visszafejtéssel biztos, hogy hozzá lehet férni az érzékeny adatokhoz. Ez inkább csak megnehezíti a visszafejtést. A JASYPT (Java simplified encryption) könyvtárnak van olyan lehetősége, hogy &lt;a href="http://www.jasypt.org/encrypting-configuration.html"&gt;titkosít bizonyos értékeket&lt;/a&gt; a konfigurációs állományban. Ekkor a konfigurációs paraméter értéke valami hasonló lesz: ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm). Képes kezelni properties állományokat, Spring-hez és Hibernate-hez illeszthető.&lt;/p&gt;
&lt;p&gt;Konfigurációs paraméterek kezelésére alkalmas keretrendszerek:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://commons.apache.org/configuration/"&gt;Commons configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jconfig.org/"&gt;jConfig&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jfig.sourceforge.net/"&gt;jFig&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://carbon.sourceforge.net/modules/core/docs/config/index.html"&gt;The Carbon Core Config Subsystem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furcsa, hogy a legfrissebb is 2008-ban frissült utoljára.&lt;/p&gt;
&lt;p&gt;Ti hogyan oldottátok meg a konfigurációs paraméterek tárolását, szerkesztését?&lt;/p&gt;
&lt;p&gt;A következőkben egy olyan megoldást mutatok be, mely JBoss AS specifikus (tesztelve 5.1 és 6 verziókon is). Nem ad választ minden kérdésre, a cikkben kizárólag a JBoss ez irányú egy-két képességét szeretném bemutatni.&lt;/p&gt;
&lt;p&gt;A post-hoz egy példa projekt is &lt;a href="http://dl.dropbox.com/u/7683931/jtechlog/earconfig.zip"&gt;letölthető&lt;/a&gt;. A projekt Maven-nel fordul, és szépen szemlélteti egy Java EE projekt felépítését Maven környezetben, ahol a build terméke egy EAR állomány. Az alkalmazás négy részből áll. Egy parent project, mely a közös beállításokat tartalmazza (pl. Java 6, UTF-8 kódolás, stb.), valamint három modulja:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;earconfig-ejb: EJB réteg&lt;/li&gt;
&lt;li&gt;earconfig-web: web réteg - erre csak azért van szükség, hogy az EJB réteget meg tudjuk hívni&lt;/li&gt;
&lt;li&gt;earconfig-ear: az alkalmazás maga&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Az alkalmazást kicsomagolva, majd a gyökér könyvtárban a &lt;code&gt;mvn package&lt;/code&gt; parancsot kiadva áll elő az earconfig-ear/target/earconfig-ear-1.0-SNAPSHOT.ear állomány. Ahhoz, hogy telepítsük, vagy másoljuk be a JBoss deploy könyvtárába az alkalmazást, vagy az earconfig-ear könyvtárban a pom.xml-ben írjuk át a jboss.server.dir property értékét arra az elérési útvonalra, ahova a JBoss lett telepítve, és adjuk ki a cargo:deploy parancsot. Ezt bekonfigurálhatjuk fejlesztőeszközben is. A &lt;a href="http://cargo.codehaus.org/"&gt;Cargo&lt;/a&gt; egy olyan könyvtár, mely egységes felületet biztosít web konténerek, alkalmazásszerverek kezelésére, elindítására, leállítására, alkalmazások telepítésére. Mi a Maven pluging-jét használjuk.&lt;/p&gt;
&lt;p&gt;Az alkalmazásnak az ejb és war modulja is pontosan ugyanúgy működik. A ejb modulban az EarConfigBean EJB Bean, a war modulban a EarConfigServlet servlet felelős a paraméterek kiolvasásáért.&lt;/p&gt;
&lt;p&gt;Az első metódus system property-t olvas be a következő Java SE-ben is működő módon:&lt;/p&gt;
&lt;pre class="brush: java"&gt;
System.getProperty("earconfig.system.property");
&lt;/pre&gt;
&lt;p&gt;A második metódus Context lookup-pal lekérdezi a globális JNDI-ben lévő értékeket:&lt;/p&gt;
&lt;pre class="brush: java"&gt;
Context context = new InitialContext();
String[] NAMES = new String[]{"earconfig/string", "earconfig/url", "earconfig/inetaddress", "earconfig/properties"};
for (String name: NAMES) {
   Object entry = context.lookup(name);
   System.out.println(entry.getClass().getName() + " " + entry);
}
&lt;/pre&gt;

&lt;p&gt;Nagyon sokat kínlódtam azzal, hogy a paramétereket globálisan definiáljam a JNDI-ben, majd azokat elérhetővé tegyem a bean, vagy a web alkalmazás ENC-jében, ahogyan arról &lt;a href="http://jtechlog.blogspot.com/2009/01/jndi-nevek-ejb-krnyezetben.html"&gt;korábban írtam&lt;/a&gt;, sőt ehhez akár a @Resource annotációval hozzáférjek. Ezt azonban nem sikerült megoldani.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-lERPAF8FaWo/TXQUdpgWqEI/AAAAAAAAGBw/EAZE2IweFB4/s1600/enc_overview.png" rel="lightbox"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 134px;" src="http://3.bp.blogspot.com/-lERPAF8FaWo/TXQUdpgWqEI/AAAAAAAAGBw/EAZE2IweFB4/s320/enc_overview.png" border="0" alt="ENC áttekintés" id="BLOGGER_PHOTO_ID_5581108337809205314" /&gt;&lt;/a&gt;

&lt;p&gt;Klasszikus esetben tehát van az EJB komponens, melyhez a standard deployment descriptor-ban (telepítés leíró) vagy a @Resource annotációval lehet egy lokális nevet az ENC-ben deklarálni. Ehhez az előbbi esetén context lookup-pal, az utóbbi esetén szintén a @Resource annotációval fér hozzá az EJB. Az alkalmazásszerverek gyártófüggő módon engedik az erőforrások felvételét a konténeren belül, és kapnak egy globális nevet. A lokális és a globális neveket a gyártófüggő deployment descriptor-ban lehet összekötni.&lt;/p&gt;

&lt;p&gt;Felmerülhet tehát az igény, hogy az ENC-ben deklaráljuk a logikai neveket, és egy gyártófüggő deployment descriptor-ban rendeljük hozzá a konkrét értékeket. Az ENC-ben való deklarációhoz két eszközünk lehet, vagy a standard deployment descriptor, vagy a @Resource annotáció, mely egymásnak alternatívái (, pontosabban a annotációt a deployment descriptor felülírhatja).&lt;/p&gt;

&lt;p&gt;A standard deployment descriptor-ban (ejb-jar.xml) a következő XML tag-ek használatosak erre:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;resource-ref: Factory-k definiálására, tipikusan DataSource-ra használható. További osztályok: javax.jms.QueueConnectionFactory/javax.jms.TopicConnectionFactory, javax.mail.Session, java.net.URL.&lt;/li&gt;
&lt;li&gt;resource-env-ref: a neten sok példa ide a Queue-t vagy Topic-ot említi, de helytelenül, lásd a következő pont. Amit találtam róla, hogy Connector CCI esetén használható.&lt;/li&gt;
&lt;li&gt;message-destination-ref: valójában ez használandó Queue-t vagy Topic definiálására&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ebből máris látható, hogy a mi egyszerű, JNDI-be bejegyzett értékeinkre nem tudunk mivel hivatkozni. Van ugyan egy env-entry tag, de ennek értékét kizárólag az ejb-jar.xml-ben lehet megadni, és nem lehet felüldefiniálni a JNDI-ben megadott értékkel.&lt;/p&gt;

&lt;p&gt;A Java EE szabvány, csak a következő típusokat engedi @Resource annotációval megjelölni:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SessionContext&lt;/li&gt;
&lt;li&gt;DataSource&lt;/li&gt;
&lt;li&gt;UserTransaction&lt;/li&gt;
&lt;li&gt;EntityManager&lt;/li&gt;
&lt;li&gt;TimerService&lt;/li&gt;
&lt;li&gt;Más EJB-k&lt;/li&gt;
&lt;li&gt;Web szolgáltatások&lt;/li&gt;
&lt;li&gt;Sorok és témák (queue/topic)&lt;/li&gt;
&lt;li&gt;Connection factory objektumok a resource adapter-ek számára&lt;/li&gt;
&lt;li&gt;Környezeti változók: String, Character, Byte, Short, Integer, Long, Boolean, Double és Float&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ebből látható, hogy nem lehet akármilyen típushoz, POJO-hoz hozzáférni, ami már beszűkíti a lehetőségeinket. Ezt a tulajdonságát a Resource annotációnak a Spring közönség igen erősen kritizálja, érthető okokból.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-jb-qsI66nbw/TXQTrHRQeDI/AAAAAAAAGBo/ftdkPUkuO4k/s1600/enc_details.png" rel="lightbox"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 218px;" src="http://3.bp.blogspot.com/-jb-qsI66nbw/TXQTrHRQeDI/AAAAAAAAGBo/ftdkPUkuO4k/s320/enc_details.png" border="0" alt="ENC részletek" id="BLOGGER_PHOTO_ID_5581107469625620530" /&gt;&lt;/a&gt;

&lt;p&gt;Így hát marad az, hogy a globális JNDI nevekhez férjünk hozzá Context lookup segítségével. Jobb esetben erre Service Locator-t használunk. Még jobb estben az előbb említett konfigurációs keretrendszerek valamelyikét.&lt;/p&gt;

&lt;p&gt;De előbb nézzük, hogyan lehet értéket adni egy system property-nek? Vagy parancssorból a Java virtuális gépnek a &lt;code&gt;-D&lt;/code&gt; paraméterrel, vagy kódból a System.setProperty metódussal. A JBoss azonban egy SystemPropertiesService szolgáltatást is biztosít, mely a deploy könyvtárban lévő properties-service.xml-ben van definiálva. Ahhoz, hogy a system property-nek értéket adjunk, a következő sorokat illesszük be a SystemPropertiesService mbean tag alá.&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;attribute name="Properties"&amp;gt;
  earconfig.system.property=Hello System Property!
&amp;lt;/attribute&amp;gt;
&lt;/pre&gt;

&lt;p&gt;A megoldás szépsége, hogy ezt akkor is megtehetjük, ha éppen fut a JBoss, a -service.xml állományokat a JBoss automatikusan újra felolvassa. Nem csak ebben állíthatjuk be a paramétereket, hanem megadhatunk egy properties állományt is, melyet felolvas.&lt;/p&gt;

&lt;p&gt;Hogyan tehetünk értéket a JNDI-be? Megtehetjük parancssori eszközzel, kódbol, de a JBoss erre is biztosít szolgáltatást, méghozzá &lt;code&gt;&lt;a href="http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/Additional_Naming_MBeans-JNDI_Binding_Manager.html#"&gt;JNDIBindingServiceMgr&lt;/a&gt;&lt;/code&gt; néven. Ez alapban nincs konfigurálva a JBoss-ban, ígyhát hozzunk létre egy -service.xml végű állományt, pl. jndi-binding-service.xml, és másoljuk bele a következő tartalmat. (Megtalálható a projektben is a jbossconfig-ear\src\main\jboss\jndi-binding-service.xml állományban.)&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;

&amp;lt;server&amp;gt;

   &amp;lt;mbean code="org.jboss.naming.JNDIBindingServiceMgr"
      name="jboss.jndi:name=JNDIBindingServiceMgr"&amp;gt;
       &amp;lt;attribute name="BindingsConfig" serialDataType="jbxb"&amp;gt;
           &amp;lt;jndi:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                      xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                      xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd"&amp;gt;

               &amp;lt;jndi:binding name="earconfig/string"&amp;gt;
                   &amp;lt;jndi:value trim="true"&amp;gt;
                   Hello, JNDI!
                   &amp;lt;/jndi:value&amp;gt;
               &amp;lt;/jndi:binding&amp;gt;

               &amp;lt;jndi:binding name="earconfig/url"&amp;gt;
                   &amp;lt;jndi:value type="java.net.URL"&amp;gt;http://www.jboss.org&amp;lt;/jndi:value&amp;gt;
               &amp;lt;/jndi:binding&amp;gt;

               &amp;lt;jndi:binding name="earconfig/inetaddress"&amp;gt;
                   &amp;lt;jndi:value editor="org.jboss.util.propertyeditor.InetAddressEditor"&amp;gt;
                       127.0.0.1
                   &amp;lt;/jndi:value&amp;gt;
               &amp;lt;/jndi:binding&amp;gt;

               &amp;lt;jndi:binding name="earconfig/properties"&amp;gt;
                   &amp;lt;java:properties xmlns:java="urn:jboss:java-properties"
                    xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                    xs:schemaLocation="urn:jboss:java-properties
      resource:java-properties_1_0.xsd"&amp;gt;
                       &amp;lt;java:property&amp;gt;
                           &amp;lt;java:key&amp;gt;key1&amp;lt;/java:key&amp;gt;
                           &amp;lt;java:value&amp;gt;value1&amp;lt;/java:value&amp;gt;
                       &amp;lt;/java:property&amp;gt;
                       &amp;lt;java:property&amp;gt;
                           &amp;lt;java:key&amp;gt;key2&amp;lt;/java:key&amp;gt;
                           &amp;lt;java:value&amp;gt;value2&amp;lt;/java:value&amp;gt;
                       &amp;lt;/java:property&amp;gt;
                   &amp;lt;/java:properties&amp;gt;
               &amp;lt;/jndi:binding&amp;gt;

           &amp;lt;/jndi:bindings&amp;gt;
       &amp;lt;/attribute&amp;gt;
   &amp;lt;/mbean&amp;gt;

&amp;lt;/server&amp;gt;
&lt;/pre&gt;

&lt;p&gt;A példa négy értéket illeszt be a JNDI-be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;earconfig/string: String típusú&lt;/li&gt;
&lt;li&gt;earconfig/url: URL típusú&lt;/li&gt;
&lt;li&gt;earconfig/inetaddress: InetAddress típusú&lt;/li&gt;
&lt;li&gt;earconfig/properties: Properties típusú&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mint látható, nem csak String-et lehet használni, hanem vannak beépített &lt;a href="http://community.jboss.org/wiki/PropertyEditor"&gt;beépített PropertyEditor-ok&lt;/a&gt;, de sajátot is lehet használni.&lt;/p&gt;

&lt;p&gt;Amennyiben ezt az állományt is bemásoljuk a deploy könyvtárba, az értékek a JNDI-ben azonnal megjelennek. Szerkesztés esetén is azonnal látszanak az új értékek, ugyanis a JBoss az állományt automatikusan újraolvassa. Az eredmény megtekinthető a JMX Console-on is (/jmx-console címen), és a service=JNDIView MBean-t kell kiválasztani, és meghívni a list(boolean verbose) metódusát. A következőt kell látnunk:&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-PAO7WAPXFXA/TXQGTPYQylI/AAAAAAAAGBQ/U1Ftl8QG1zo/s1600/jboss-jmx.PNG" rel="lightbox"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 224px;" src="http://3.bp.blogspot.com/-PAO7WAPXFXA/TXQGTPYQylI/AAAAAAAAGBQ/U1Ftl8QG1zo/s320/jboss-jmx.PNG" alt="JBoss JMX admin" id="BLOGGER_PHOTO_ID_5581092765834463826" border="0" /&gt;&lt;/a&gt;

&lt;p&gt;Sajnos ezeket az adminisztrációs felületen nem lehet szerkeszteni, kizárólag a fájlokban. Azonban a Glassfish pl. lehetőséget biztosít ezek megadására grafikus adminisztrációs felületen is.&lt;/p&gt;

&lt;p&gt;Így az értékek benne vannak a globális névtérben, lookup-pal már hozzá is tudunk férni. Az alkalmazás az /earconfig címen tekinthető meg, és a következőt kell kiírnia:&lt;/p&gt;

&lt;pre&gt;
A projekt bemutatja, hogy hogyan lehet Java EE alkalmazásból konfigurációs paramétereket beolvasni.

    * System property EJB rétegben (kulcs: earconfig.system.property): Hello \
System Property!
    * Context lookup (JNDI) EJB rétegben (JNDI nevek: earconfig/string, \
 earconfig/url, earconfig/inetaddress, earconfig/properties): [Hello JNDI!, \
http://jtechlog.blogspot.com, 127.0.0.1, {key2=value2, key1=value1}]
    * System property web rétegben (kulcs: earconfig.system.property): Hello System Property!
    * Context lookup (JNDI) web rétegben (JNDI nevek: earconfig/string, \
 earconfig/url, earconfig/inetaddress, earconfig/properties): [Hello JNDI!, \
http://jtechlog.blogspot.com, 127.0.0.1, {key2=value2, key1=value1}]
&lt;/pre&gt;

&lt;p&gt;Persze &lt;a href="http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/Writing_JBoss_MBean_Services-A_Standard_MBean_Example.html"&gt;mi is írhatunk saját MBean-t&lt;/a&gt;, mely pakol a JNDI-be.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-5695982303749707840?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/5695982303749707840/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/02/konfiguracios-parameterek-ejb-retegben.html#comment-form" title="3 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/5695982303749707840?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/5695982303749707840?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/02/konfiguracios-parameterek-ejb-retegben.html" title="Konfigurációs paraméterek EJB és web rétegben JBoss alkalmazásszerveren" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-lERPAF8FaWo/TXQUdpgWqEI/AAAAAAAAGBw/EAZE2IweFB4/s72-c/enc_overview.png" height="72" width="72" /><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;Ck4GR34zcSp7ImA9WhZXEE8.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-7968961481638103983</id><published>2011-02-22T00:18:00.003+01:00</published><updated>2011-04-28T22:02:06.089+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-28T22:02:06.089+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vizsga" /><category scheme="http://www.blogger.com/atom/ns#" term="Oracle" /><category scheme="http://www.blogger.com/atom/ns#" term="Java EE" /><category scheme="http://www.blogger.com/atom/ns#" term="JPA" /><title>EJB és JPA Developer Certified Expert</title><content type="html">&lt;p&gt;&lt;em&gt;Frissítés 2011. április 28.&lt;/em&gt;: ma jöttek meg a bizonyítványok, egy kártya és egy levél társaságában.&lt;/p&gt;

&lt;p&gt;2010. szeptember 2-án és 3-án tettem le a &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=41&amp;p_org_id=1001&amp;lang=US&amp;p_exam_id=1Z0_895"&gt;Java Platform, Enterprise Edition 6 Enterprise JavaBeans Developer&lt;/a&gt;, régi nevén Sun Certified EJB Developer for the Java EE6 Platform (CX-311-093), és a &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=41&amp;p_org_id=1001&amp;lang=US&amp;p_exam_id=1Z0_898"&gt;Java Platform, Enterprise Edition 6 Java Persistence API Developer&lt;/a&gt;, régi nevén Sun Certified JPA Developer for the Java EE6 Platform (CX-311-094) vizsgákat. A Java EE6 esetén vált a kettő külön, előtte egy volt, Sun Certified Business Component Developer (SCBCD) EE5 néven. Mindkettő vizsga béta vizsga, tehát a publikus kiadás előtt lehetett ezekre jelentkezni. Ez azt jelenti, hogy nem véglegesek a kérdések, erős fejlesztés alatt állnak, segíteni lehet az Oracle-nek egyrészt ezek tökéletesítésében, másrészt meg tudják határozni a nehézségi fokozatukat. A kérdések erőssége igen nagy szórású, vannak túl egyszerű, és túl nehéz kérdések is közöttük. Viszonylag alacsony áron lehet hozzájuk jutni (, ez esetemben 50$ volt vizsgánként - a Sun esetében ezek még ingyenesek voltak), viszont rengeteg kérdésere kell válaszolni (175 - 220), és kb. 5 óra van rájuk.&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=41&amp;p_exam_id=1Z0_860"&gt;SCBCD vizsga oldalán&lt;/a&gt; részletesebb listát lehet találni a tematikáról, és itt találhatóak &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=303&amp;p_certName=SQ1Z0-860"&gt;példa kérdések&lt;/a&gt; is.&lt;/p&gt;

&lt;p&gt;A felkészülés során a JPA-t az &lt;a href="http://apress.com/book/view/9781430219569"&gt;Apress kiadó Pro JPA 2 Mastering the Java Persistence API&lt;/a&gt; könyvből tanultam, mely messze a legrészletesebb és legprofibb szakmai könyv, melyet valaha olvastam. Érződik, hogy nem csak azt írja le, hogy hogyan néz ki a szabvány, hanem azt is, hogy miért jutottak a tervezők arra a döntésre, valamint az implementációs különbségekről is lehet olvasni. A szakmai precizitás miatt persze nem mindenütt kellően olvasmányos, 10-15 oldalakon keresztül lazán elkalandozik az ember figyelme. Nálam fejezetek voltak, amik totálisan kiestek. Véleményem szerint a felkészüléshez bőven elegendő könyv. Jó EJB 3.1 könyv szerintem még nem jelent meg, így a &lt;a href="http://www.manning.com/panda/"&gt;Manning kiadó EJB 3 in Action&lt;/a&gt; könyvét ajánlom, valamint az EJB 3.1 felkészüléshez a &lt;a href="http://www.theserverside.com/news/1363656/New-Features-in-EJB-31"&gt;TheServerSide&lt;/a&gt; cikket, az &lt;a href="http://www.oracle.com/technetwork/articles/javaee/javaee6overview-141808.html"&gt;Oracle cikket&lt;/a&gt;, a specifikációt (&lt;a href="http://jcp.org/en/jsr/detail?id=318"&gt;JSR 318&lt;/a&gt;), valamint az &lt;a href="http://apress.com/book/view/9781430219545"&gt;Apress kiadó Beginning Java EE 6 Platform with GlassFish 3&lt;/a&gt; könyvét, nem is azért, mert annyira jó, hanem mert ez az elérhető egyetlen EJB 3.1 könyv. Létezik még EJB vonalon a OReilly Enterprise JavaBeans 3.0 (5th Edition), és az ingyen letölthető Mastering EJB 3.0 (4th Edition) könyv is, lapozgattam őket korábban, de a vizsgára készülésnél nem vettem elő őket. A JavaRanch-on is lehet találni nagyon sok &lt;a href="http://www.coderanch.com/how-to/java/ScbcdLinks#scbcd50"&gt;forrást&lt;/a&gt;, de szerintem ennyi időt már nem éri meg rá áldozni. Ami még sokat számított, az Enthuware's mock simulator, valamint ezúton szeretnék köszönetet mondani Karakó Miklósnak (alias palacsint), többek között a &lt;a href="http://palacsint.hu/blog/20100418/scbcd-jegyzetek"&gt;remek oldala&lt;/a&gt; miatt is. Én nem nagyon gyakorolgattam fejlesztőeszközzel, egy-két dolgot próbáltam ki NetBeans IDE és Glassfish környezetben.&lt;/p&gt;

&lt;p&gt;A körítés ugyanaz volt, mint az SCJP esetén, melyről már &lt;a href="http://jtechlog.blogspot.com/2009/10/scjp.html"&gt;korábban írtam&lt;/a&gt;.

&lt;p&gt;Sajnos a kérdések pontos számát nem tudom, mert nem írták ki előre, hanem a gép témakörönként adta ki, és nem tudtam megjegyezni a témakörönkénti kérdések számát. Érdekes, hogy az eredményen sem a valódi kérdések és helyes válaszok számát írták le, hanem a végleges vizsga 60 és 63 kérdése szerepel rajta, mindkét esetben 60%-ot kell teljesíteni a sikerességhez. Szerintem a JPA vizsga sokkal nehezebb, sokkal több tárgyi tudást és gyakorlatot igényel.&lt;/p&gt;

&lt;p&gt;Nagy negatívuma, hogy megterheli az embert, kb. 200 kérdés 5 órán keresztül nagyon fárasztó tud lenni. Míg az SCJP esetén nagyon sok időm maradt a végén, e kettő vizsgánál minden percet kihasználtam, úgy, hogy arra sem volt időm, hogy átnézzem a válaszokat, csak amiket elhalasztottam, azokon tudtam átrohanni. Igazából akkora engedmény sincs rajta, hiszen 300$ helyett 50$-t kell fizetni érte. Valamint nagy csúszás volt rajta, ugyanis az ígért 12 hét helyett, a 2010. szeptember elején letett béta vizsgák eredményeit 2011. február 4-én és február 11-én kezdték el kipostázni. A végleges vizsgák február 21-én éles üzembe álltak. (&lt;a href="http://blogs.oracle.com/certification/2011/02/0520.html"&gt;Bejelentés itt&lt;/a&gt;, belső technikai problémákra hivatkoznak.&lt;/p&gt;) Érdekes, hogy az &lt;a href="http://www.certmanager.net/sun"&gt;Oracle Certification Database - régebben Sun&lt;/a&gt; oldalon már a levél megérkezése előtt pár nappal fenn volt az eredmény a History-ban, de a Current Certifications panelen még a mai napig nem szerepelnek.&lt;/p&gt;

&lt;p&gt;További Java vizsgák az &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=140"&gt;Oracle Certification Program / Oracle Middleware&lt;/a&gt; oldalon, valamint a &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=42#2"&gt;Oracle Certification Program / Available Certification Exams&lt;/a&gt; oldalon.&lt;/p&gt;

&lt;p&gt;És pár érdekesség, melyekre a vizsgára való készülés közben bukkantam rá, vagy a vizsga közben tapasztaltam:&lt;/p&gt;

&lt;p&gt;EJB&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nagyon sok figyelmet fordít a role responsibility-re. Ez ugye azért meglepő, mert a könyvek szinte alig írnak róla, kizárólag a szabvány említi nagyon nagy pontossággal.&lt;/li&gt;
&lt;li&gt;CreateException, RemoveException, FinderException (ObjectNotFoundException) extends Exception - checked&lt;/li&gt;
&lt;li&gt;EjbException extends (indirect) RuntimeException&lt;/li&gt;
&lt;li&gt;EJBTransactionRolledbackException extends EJBException, megy a lokális klienseknek, ha rollback van, hogy a kliens tudja, hogy ne folytassa, hiszen úgyis rollback lesz - remote klienseknek TransactionRolledbackException megy&lt;/li&gt;
&lt;li&gt;RemoteException checked&lt;/li&gt;
&lt;li&gt;RemoteException-t nem dobhat bean, MDB bármi mást dobhat&lt;/li&gt;
&lt;li&gt;Az env-entry-type nem lehet primitív típus és Date sem&lt;/li&gt;
&lt;li&gt;EJB 3 meghívása 2-ből: PortableRemoteObject.narrow, ezt castolni, majd ezen create&lt;/li&gt;
&lt;li&gt;Never esetén, ha jön tranzakció: EJBException, mely system exception&lt;/li&gt;
&lt;li&gt;Nem feltétlenül lehet EJB-ből JMX-et hívni&lt;/li&gt;
&lt;li&gt;Üzenet kivétele nem része a tranzakciónak bean managed tranzakció esetén, tehát nincs redeliver&lt;/li&gt;
&lt;li&gt;Öröklődésnél a tranzakciós attribútumoknál az örökölt, de nem override-olt metódus tranzakciós attribútuma megmarad&lt;/li&gt;
&lt;li&gt;Interceptor csak olyan kivételt dobhat, mely deklarálva van az üzleti metódusban&lt;/li&gt;
&lt;li&gt;System exception esetén nem hívódnak meg az interceptor-ok&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JPA&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Viszonylag sokat kérdez rá a JPA 3.1 újdonságára, a Criteria API-ra. Nagyon kell ismerni a szintaktikáját, mert általában leír egy EJB QL kifejezést, és meg kell mondani, hogy melyik Criteria API kódnak felel meg. Gyakran egy metódushívás különbség van. Itt gyakorlatilag tippeltem, mert sosem használtam még élesben. Tippjeim kétharmada jött be.&lt;/li&gt;
&lt;li&gt;Sok figyelmet fordít a optimista és pesszimista lockolásra.&lt;/li&gt;
&lt;li&gt;Version attribute nem lehet secondary táblában&lt;/li&gt;
&lt;li&gt;Bármennyi MappedSuperclass lehet a hierarchiában&lt;/li&gt;
&lt;li&gt;Primary key-t a hierarchiában csak egyszer lehet definiálni&lt;/li&gt;
&lt;li&gt;A FETCH a JOIN után van a JPQL-ben&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-7968961481638103983?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/7968961481638103983/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/02/ejb-es-jpa-developer-certified-expert.html#comment-form" title="2 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/7968961481638103983?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/7968961481638103983?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/02/ejb-es-jpa-developer-certified-expert.html" title="EJB és JPA Developer Certified Expert" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;D0QBQnc5cCp7ImA9Wx9UEE0.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-100801776275799553</id><published>2011-02-05T21:11:00.004+01:00</published><updated>2011-02-06T16:15:53.928+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-06T16:15:53.928+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="jce" /><category scheme="http://www.blogger.com/atom/ns#" term="jca" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Elektronikus aláírás és alkalmazása Java-ban, kulcskezelés</title><content type="html">&lt;p&gt;Technológiák: JDK 1.6, JCA, JCE, keytool&lt;/p&gt;

&lt;p&gt;Az aláírás és a titkosítás már jóval a számítógépek megszületése előtt ismert volt. Az aláírással igazoljuk, hogy az aláírt dokumentumot elolvastuk, esetleg mi írtuk, és tartalmával egyetértünk. A titkosítás esetén azon dokumentumot titkosítjuk, melyről azt akarjuk, hogy egy adott célcsoporton kívül senki se férhessen hozzá a tartalmához.&lt;/p&gt;
&lt;p&gt;Mindez igaz az informatika világában is, és jelentőségük a hálózatok elterjedésével egyre fontosabb. Egyrészt felmerülnek ugyanazon problémák, mint a klasszikus esetben (pl. hamisíthatóság), valamint új problémák is megjelennek.&lt;/p&gt;
&lt;p&gt;Az aláírás céljai mindkét esetben a következők:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;hitelesség (authenticity): a dokumentum származásának igazolása&lt;/li&gt;
&lt;li&gt;sérthetetlenség, integritás (integrity): a dokumentum tartalma nem változott annak aláírása óta&lt;/li&gt;
&lt;li&gt;letagadhatatlanság (non-repudiation): az aláíró nem tudja letagadni, hogy ő írta alá a dokumentumot, és az aláíró személy kiléte jogilag is bizonyítható eredjű&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A titkosítás ezen felül biztosítja:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;titkosság (privacy, confidentiality): a kommunikáló feleken kívül más nem szerezhet tudomást a dokumentum tartalmáról&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Ez utóbbival foglalkozó tudományág a kriptográfia, mely az ógörög eredetű  szavakból származik, szó szerinti fordításban "titkosírás". Elsősorban informatikai jellegű, és nagyon erős matematikai háttérrel rendelkező területről van szó.&lt;/p&gt;
&lt;p&gt;Az elektronikus aláírás és a titkosítás két nagyon közel álló terület, ugyanazok a fogalmak, algoritmusok használtak mindkét esetben.&lt;/p&gt;

&lt;p&gt;A titkosítás esetén a feladó és a címzett fél is rendelkezik egy algoritmussal, a dokumentum kódolására és dekódolására. (A feladót a szakirodalomban gyakran Alice-nek, és a címzettet Bob-nak nevezik.) Mivel ilyen algoritmusok (függvény, és annak inverze) kitalálása bonyolult feladat, a matematikusok ezt feloldották azzal, hogy kiemelnek belőle egy részt, mely lehetővé teszi, hogy az algoritmusokat mindenki ismerhesse, de a titkosítás mégis működjön, és ez a rész szükség esetén (pl. ha kiderül), cserélhető is legyen. Ez a rész a kulcs, melyet ha csak a két fél ismer, a titkosítás biztosítva van. A kulcs cseréje gyors művelet, míg egy algoritmus kidolgozása, és helyességének bizonyítása sokkal nagyobb feladat. A titkosításnak azt a formáját, ahol egy közös kulcs van, szimmetrikus titkosításnak nevezzük. A kriptográfia egyik alterülete a nyilvános kulcsú titkosítás (aszimmetrikus titkosítás), mely arra ad megoldást, hogyha a feladó és a címzett fél nem tud személyesen találkozni, egy közös kulcsot egyeztetni. A megoldás az, hogy a feladónak és a címzettnek is van egy kulcspárja, a titkos és a publikus kulcs. A kettő matematikai kapcsolatban van egymással, de a nyilvános kulcs alapján gyakorlatilag nem lehet a titkos kulcsot meghatározni. A publikus kulcs terjeszthető, míg a titkos kulcsra nagyon kell vigyázni. Alice a saját titkos, és Bob publikus kulcsával, ha elkódol egy dokumentumot, azt csak Bob tudja kibontani a saját titkos kulcsával.&lt;/p&gt;

&lt;p&gt;Elektronikus aláírás esetén a előbb a dokumentumból egy lenyomat (hash) készül. A hash függvény egy olyan függvény, mely egy végtelen hosszúságú adatot véges hosszúságra képez le. A hash-ből a dokumentum nem visszanyerhető, már csak hossza miatt sem. A hash algoritmusokkal szemben elvárás, hogy lehetőleg gyorsak legyenek, és amennyiben a dokumentum változik, annak hash lenyomata is szignifikánsan változzon meg (lavinahatás). Valamint egy dokumentumhoz gyakorlatilag lehetetlen vele megegyező hash-ű értelmes dokumentumot legyártani, két dokumentum hash-e nagy valószínűséggel különbözzön (ütközésmentesség). (Megjegyzendő, hogy pl. hash-elést alkalmazunk autentikációnál is, ugyanis nem szükséges a felhasználó jelszavát elmenteni az informatikai rendszerekben, elegendő annak hash-ét. Bejelentkezéskor a jelszóból a rendszer egyből hash-t képez, melyet összehasonlít a tárolttal. Így az adminisztrátorok sem férhetnek hozzá a felhasználó jelszavához.) Az elektronikus aláírás során Alice a saját titkos és Bob publikus kulcsával titkosítja a hash-t. Bob elektronikus aláírás ellenőrzésekor egyrészt megkapja a dokumentumot, melyről ugyanazon hash algoritmussal ő is hash-t készít, és kititkosítja Alice által átküldött aláírást, és összehasonlítja az előbb kapott hash-sel. Amennyiben a kettő megegyezik, a dokumentumot biztos, hogy Alice látta el saját titkos kulcsával elektronikus aláírással, és a dokumentum közben nem változott.&lt;/p&gt;

&lt;p&gt;Gyakran előforduló fogalom még a Public Key Infrastructure (PKI) - nyilvános kulcsú infrastruktúra. Ez minden, mely szükséges a nyilvános kulcsú titkosításhoz. Ide tartozik pl. a háttérintézmények, eljárások, szabványok, szabályzatok, stb. Itt kerül megemlítésre a hitelesítésszolgáltató (certificate authority or certification authority - CA),  &lt;a href="http://jtechlog.blogspot.com/2008/12/minstett-elektronikus-alrs.html"&gt;róluk írtam már korábban&lt;/a&gt;. Ugyanis abban az esetben, ha Bob-nak nem Alice adja oda a publikus kulcsát, hanem egy rosszindulatú harmadik személy adja át a sajátját Alice nevében, akkor az Alice-nak szánt dokumentumokat képes ő kibontani. Ezért egy megbízható harmadik félre van szükség, aki igazolja, hogy az adott publikus kulcs kihez tartozik. Ez tanúsítvány formájában történik, mely tartalmazza az adott személy, vagy informatikai rendszer publikus kulcsát, annak adatait (pl. személy esetében nevét, de web szerver esetén a domain nevet), és a hitelesításszolgáltató ezt elektronikusan aláírja.&lt;/p&gt;

&lt;p&gt;Nézzük, milyen szabványokat, algoritmusokat érdemes ismerni ezzel kapcsolatban. Hash algoritmusok, többek között:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MD5: 2005 óta elektronikus aláírás területen használata nem javasolt, 32 karakter hosszú hexadecimális hash&lt;/li&gt;
&lt;li&gt;SHA-1: 2010 december 31-ével elektronikus aláírás területen használata nem javasolt&lt;/li&gt;
&lt;li&gt;SHA-256&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Szimmetrikus kulcsú titkosító algoritmusok, többek között:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RC2, RC4: RSA cég által kifejlesztett algoritmusok.&lt;/li&gt;
&lt;li&gt;DES (Data Encription Standard): az amerikai kormány szinte "hivatalos" rejtjelező eljárásként minősítette, így rendkívül elterjedt.&lt;/li&gt;
&lt;li&gt;3DES (triple-DES): a DES lassanként megfáradt, törése elérhető közelségbe került, így jelentős számú továbbfejlesztett változata jelent meg, de gyakorlatban a 3DES terjedt el, mely egymás után háromszor használja az algoritmust (encrypt - decrypt - encrypt). Szokták három különböző kulccsal és két különböző kulccsal (első és az utolsó egyezik meg) is használni. Előnye, hogy a DES infrastruktúra maradhat, csupán többször alkalmazzák az algoritmust.&lt;/li&gt;
&lt;li&gt;AES (Advanced Encryption Standard): National Institute of Standards and Technology (NIST) által specifikált, amerikai kormány által elfogadott algoritmus a DES leváltására, eredetileg Rijndael néven pályáztak vele.&lt;/li&gt;
&lt;li&gt;Blowfish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aszimmetrikus kulcsú titkosító algoritmusok, többek között:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RSA: Egyik leggyakrabban használt titkosítási eljárás, de facto szabvány, matematikai alapjait a moduláris- és a prímszámelmélet egyes tételei jelentik, faktorizáción (prím tényezőkre bontáson) alapul. Míg a prím számokkal való szorzás egyszerű, a prím tényezős felbontásra nincs hatékony algoritmus, ha egy szám két igen nagy prímszám szorzata, akkor ennek prímtényezős felbontása rendkívül sokáig tart. 2000-ben lejár a szabadalmi védelme.&lt;/li&gt;
&lt;li&gt;Digital Signature Algorithm (DSA): NIST javasolta, és az USA digitálisaláírás-szabványává vált (Digital Signature Standard (DSS), specifikálva a FIPS 186-ban, azóta FIPS 186-3-ban).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Az aszimmetrikus titkosító algoritmusok hátránya, hogy sokkal lassabbak a szimmetrikus kulcsú titkosító algoritmusokhoz képest. Ezért pl. az SSL azt a trükköt alkalmazza, hogy kapcsolat felvételekor PKI-t használ, de lekommunikálnak egy szimmetrikus kulcsot, és a továbbiakban azzal, szimmetrikus titkosítással történik a kommunikáció.&lt;/p&gt;

&lt;p&gt;Az elektronikus aláírás és titkosítás területének egyik legismertebb szabványosító testülete az RSA Security, mely nemcsak az RSA algoritmust dolgozta ki, de ő hozta létre a széles körben alkalmazott és implementált &lt;a href="http://www.rsa.com/rsalabs/node.asp?id=2124"&gt;PKCS szabványcsaládot&lt;/a&gt;, mely jelenleg 15 tagból áll, bár van közöttük, ami már érvénytelen. Ennek pl. első eleme a PKCS #1, ami az RSA algoritmus, és a RFC 3447 definiál.&lt;/p&gt;

&lt;p&gt;Az X.500 szabvány hálózati szabványok gyűjtője, és része az X.509 szabvány is, mely definiálja többek között a tanúsítvány formátumát is. Ahogy említettem, a tanúsítvány tartalmaz a publikus kulcson kívül leíró adatokat is, pl. itt kell megemlíteni a hagyományos X.500 distinguished name-t (DN), melyet címtár szolgáltatásokban (pl. LDAP esetén elterjedt) használatos egyedi azonosítóként fejlesztettek ki, mellyel hierarchikus struktúrát lehet megadni, ezek közül a leggyakoribbak az ország (C - country), állam vagy tartomány (ST - state or province), város (city or locality - L), szervezet (O - organization), szervezeti egység (OU - organization unit) és általános név (CN - common name). Ezzel lehet megadni a tanúsítány tulajdonosát, de magát a tanúsítványkiadót is. Ezen kívül olyanokat tartalmaz még a tanúsítvány, mint a szabvány verziószáma, algoritmus, kiadó, érvényesség, stb., és ezt írja alá a tanúsítványt kiadó. A tanúsítvány kiadójának szintén lehet tanúsítványa, melyet egy másik tanúsítány kiadó adott ki. Az így összeállt láncot hívják tanúsítványláncnak. Érdemes még írni a visszavonási listáról is. Hogy a rendszer le legyen védve az ellen, hogy egy kulcspárat ellopnak, és visszaélnek vele, bevezették a visszavonási lista fogalmát. Az eltulajdonított tanúsítványokat be lehet jelenteni, ekkor a visszavonási listára kerül. Ami ezen rajta van, az ahhoz tartozó aláírásokat nem lehet elfogadni. Mivel az eltulajdonítás ténye nem derül ki azonnal, bevezették a kivárási idő fogalmát. Aláírás ellenőrzéskor ugyanis nem szabad azonnal elfogadni azt, hanem ki kell várni a kivárási időt. Ha a tanúsítvány utána sem kerül visszavonási listára, az aláírás elfogadható.&lt;/p&gt;

&lt;p&gt;Másik tanúsítvány formátum a PKCS #12.&lt;/p&gt;

&lt;p&gt;Amikor egy https oldalt nézünk, akkor a háttérben ssl vagy tls titkosított protokollon történik a kommunikáció, mely szintén használja a PKI-t, így szintén tanúsítványokkal dolgozik. A böngészőben ezt a tanúsítványt meg tudjuk nézni. Nézzük meg pl. a https://www.netlock.net/ cím tanúsítványát.&lt;/p&gt;

&lt;a rel="lightbox" href="http://3.bp.blogspot.com/_czKgycLvmNo/TU2rQzkwl3I/AAAAAAAAFz4/5AbNizXPqRQ/s1600/netlock_tanusitvany.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 274px; height: 320px;" src="http://3.bp.blogspot.com/_czKgycLvmNo/TU2rQzkwl3I/AAAAAAAAFz4/5AbNizXPqRQ/s320/netlock_tanusitvany.png" border="0" alt="NetLock tanúsítvány" id="BLOGGER_PHOTO_ID_5570296619337815922" /&gt;&lt;/a&gt;

&lt;p&gt;Látható, hogy a lánc két elemből áll, NetLock Uzleti (Class B) tanúsítványkiadó, valamint a www.netlock.hu tanúsítványokból. Mindegyik adatait le lehet kérni. Akkor hiteles egy tanúsítvány, ha a kibocsájtó tanúsítványa is hiteles. Viszont a gyökér elemnél már nincs kiadó (pontosabban a kiadója saját maga), így annak hitelességét más úton kell garantálni. A böngészők esetében alapesetben benne van egy halom hitelesítésszolgáltató, vagy ha nincs benne, manuálisan fogadhatjuk azt el. Figyeljük meg, hogy nem ajánlatos ékezetes karaktereket használni.&lt;/p&gt;

&lt;p&gt;A tanúsítványt ki is exportálhatjuk, különböző formátumokban. Még az X.509 tanúsítványt is több formátumban tárolhatjuk. A Firefox csak Base64 kódolással engedi (általában cer kiterjesztést használunk), de pl. az Explorer engedi binárisan is DER kódolással (der kiterjesztéssel), de már ismeri a másik tanúsítvány szabványt, a PKCS #12-őt is (pfx, p12 kiterjesztéssel). Base64 esetén az állományban valami hasonlót látunk:&lt;/p&gt;

&lt;pre&gt;
-----BEGIN CERTIFICATE-----
MIIGezCCBeSgAwIBAgICGb0wDQYJKoZIhvcNAQEFBQAwgZkxCzAJBgNVBAYTAkhV
...
SC1dNzJmKkqbpBJds7u8YN61AHp+XarUcJgEG6iGWA==
-----END CERTIFICATE-----
&lt;/pre&gt;

&lt;p&gt;Ezt kicsomagolva Bas64-gyel egy bináris DER állományt kapunk. Ezt is ki lehet bontani, pl. &lt;a href="http://certlogik.com/decoder/"&gt;webes szolgáltatás&lt;/a&gt; is van rá. Ekkor láthatjuk a felépítését szövegesen is.&lt;/p&gt;

&lt;a rel="lightbox" href="http://2.bp.blogspot.com/_czKgycLvmNo/TU2r8y-fdRI/AAAAAAAAF0c/ppHsHYHvo08/s1600/netlock_tanusitvany_kibontva.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 266px;" src="http://2.bp.blogspot.com/_czKgycLvmNo/TU2r8y-fdRI/AAAAAAAAF0c/ppHsHYHvo08/s320/netlock_tanusitvany_kibontva.png" border="0" alt="Tanúsítvány tartalma" id="BLOGGER_PHOTO_ID_5570297375091553554" /&gt;&lt;/a&gt;

&lt;p&gt;Látható a használt hash és titkosító algoritmus is: sha1WithRSAEncryption, valamint a kiadó és a tárgy DN-je is.&lt;/p&gt;

&lt;p&gt;Egy egyszeri Java programozó mikor is találkozhat ezzel? Többször, mint gondolnánk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Applet, Java Web Start, JAR aláírása&lt;/li&gt;
&lt;li&gt;Aláírás/titkosítás alkalmazásból&lt;/li&gt;
&lt;li&gt;SSL kommunikáció konfigurálása Web konténerben, szerver oldali tanúsítvánnyal&lt;/li&gt;
&lt;li&gt;Web alkalmazásnál kliens oldali tanúsítványok használata autentikációhoz&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Java-ban az elektronikus aláírás és titkosítás, a Java Cryptography Architecture (JCA), és Java Cryptography Extension (JCE) API-k segítségével történik. Ezek klasszikus értelemben vett API-k, azaz interfészt biztosítanak, provider-based architecture-t valósítanak meg, azaz az alatta lévő implementáció cserélhető, akár csak a JDBC esetén a driver. Egyik eszköze a Factory design pattern, azaz nem kell az objektumot példányosítani, hanem egy Factory végzi el nekünk a különböző konfigurációk alapján (pl. melyik az elérhető és kiválasztott implementáció).&lt;/p&gt;

&lt;p&gt;Ahhoz, hogy megértsük, hogy miért alakult ki a JCA és a JCE is, vissza kell kicsit menni az időben. Régebben a titkosító algoritmusokra Amerikában nagyon szigorú export korlátozások voltak érvényben. A JCA kizárólag aláírásra használható, nem lehetséges vele, és az alapját képző algoritmusokkal titkosítani. Sőt, nem hogy titkosító algoritmusokat nem lehetett exportálni, de olyan keretrendszereket sem, melyekbe ezek beilleszthetőek. Ezért a JCE külön keretrendszer volt (optional package), melyet külön kellett letölteni és telepíteni. A Java 1.4-től kezdve azonban integrálták a JDK-ba, a SunJCE provider-rel együtt. Alapban egy un. restricted policy fájllal együtt települ, mely korlátozza bizonyos algoritmusok és kulcsméretek használatát. Persze a legtöbb országból letölthető az un. unrestricted policy fájl, mely már engedélyezi ezeket. Ez a &lt;a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html"&gt;letöltések között&lt;/a&gt; Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6 néven megtalálható. Ezen kívül telepíthető a JCE alá bármilyen aláírt provider, melyhez van unrestricted policy fájl.&lt;/p&gt;

&lt;p&gt;A Sun-os JDK-ban alapértelmezetten megtalálható egy Sun implementáció is, mind a JCA (SUN), mind a JCE alá (SunJCE). Természetesen alternatív megvalósítást is telepíthetünk, pl. választhatjuk a &lt;a href="http://www.bouncycastle.org/java.html"&gt;Bouncy Castle&lt;/a&gt;-t. Mivel ezt ausztrálok fejlesztették, így nem vonatkozik rá az amerikai export korlátozás. Ami még megragadhatja a figyelmünket ezzel kapcsolatban: Generators/Processors for OpenPGP (RFC 2440).&lt;/p&gt;

&lt;p&gt;Nagy vonalakban a SUN JCA implementáció tartalmazza az MD5 és SHA1 hash-függvényeket, valamint a DSA aláíró algoritmus egy implementációját. Valamint képes kezelni az X.509 tanúsítványláncokat és tartalmazza a JKS kulcsadatbázis implementációt. A SunJCE tartalmazza a DES, 3DES, Blowfish szimmetrikus rejtjelező algoritmusokat, az RSA aszimmetrikus titkosító algoritmust, JCEKS biztonságosabb kulcsadatbázis implementációt, stb. A JCA és JCE dokumentációja is összeolvadt már a Java 6-ban, megtalálható a &lt;a href="http://download.oracle.com/javase/6/docs/technotes/guides/security/"&gt;biztonsággal foglalkozó specifikációkban&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ahhoz, hogy a PKI-t használatba vehessük, először egy kulcspárra van szükségünk. Ezek tárolására a kulcstár szolgál, mely tárolja a privát és publikus kulcsokat, tanúsítványokat, stb. Több implementáció közül is lehet választani, az alapértelmezett a JKS (Java keystore). Ez két szintű jelszóval védett tároló, ugyanis van egy mester jelszó, mellyel a kulcstárhoz lehet hozzáférni, és minden kulcspárhoz is lehet külön jelszót rendelni (ezt akkor kell megadni, mikor a titkos kulcshoz történik hozzáférés). A kulcstárak kezelésére a &lt;a href="http://download.oracle.com/javase/6/docs/technotes/tools/windows/keytool.html"&gt;keytool&lt;/a&gt; eszköz való, mellyel lehet kulcspárokat létrehozni, exportálni, importálni, listázni, törölni, stb. A keytool viszonylag bő paraméterezési lehetőséggel rendelkezik, de rengeteg paraméternek alapértelmezett értéke van, így nem kell mindent megadni. Amennyiben bizonyos paramétereket nem adunk meg, interaktív módon rákérdez.&lt;/p&gt;

&lt;p&gt;A következő paranccsal hozzunk létre egy JKS kulcstárat, és benne egy kulcspárat. Ekkor létrejön egy mykeystore állomány, storepass jelszóval. Benne egy tanúsítvány SHA1withDSA hash és titkosító algoritmussal, mely jtechlog néven elérhető, és a jelszava keypass. A tanúsítvány un. önaláírt (self-signed), ami azt jelenti, hogy a tanúsítványhoz tartozó titkos kulccsal lett aláírva.&lt;/p&gt;
&lt;pre&gt;
keytool -genkeypair -dname "cn=Viczian Istvan, ou=JTechLog, o=Blog, c=HU" -alias jtechlog -keypass keypass -keystore .\mykeystore -storepass storepass -validity 180
&lt;/pre&gt;
&lt;p&gt;Amennyiben ki akarjuk listázni a keystore tartalmát, a következő parancsot adjuk ki, és a következő kimenetet látjuk.&lt;/p&gt;
&lt;pre&gt;
keytool -list -keystore mykeystore -storepass storepass

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

jtechlog, 2011.02.05., PrivateKeyEntry,
Certificate fingerprint (MD5): 8B:FF:C4:FA:38:E7:45:59:64:18:AE:99:F4:F4:80:11
&lt;/pre&gt;
&lt;p&gt;Amennyiben a kiválasztott tanúsítvány részleteit akarjuk kiírni, adjuk ki a következő parancsot:&lt;/p&gt;
&lt;pre&gt;
keytool -list -keystore mykeystore -storepass storepass -alias jtechlog -v

Alias name: jtechlog
Creation date: 2011.02.05.
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Viczian Istvan, OU=JTechLog, O=Blog, C=HU
Issuer: CN=Viczian Istvan, OU=JTechLog, O=Blog, C=HU
Serial number: 4d4d689a
Valid from: Sat Feb 05 16:11:22 CET 2011 until: Thu Aug 04 17:11:22 CEST 2011
Certificate fingerprints:
         MD5:  8B:FF:C4:FA:38:E7:45:59:64:18:AE:99:F4:F4:80:11
         SHA1: 4B:C9:1F:8C:5B:A8:27:44:C8:B5:21:F9:F3:75:8F:E8:A6:07:8A:03
         Signature algorithm name: SHA1withDSA
         Version: 3
&lt;/pre&gt;

&lt;p&gt;Látható, hogy a kiadó és a tulajdonos ugyanaz, tehát tényleg egy önaláírt tanúsítványról van szó. Ezt ki is tudjuk exportálni az X.509 szabványnak megfelelően, akár Base64, akár DER bináris formátumban. Alapértelmezett a bináris, a -rfc kapcsolóval tudjuk kiexportálni a Base64 formátumban.&lt;/p&gt;

&lt;pre&gt;
keytool -exportcert -keystore mykeystore -storepass storepass -alias jtechlog -rfc -file jtechlog.cer
&lt;/pre&gt;

&lt;p&gt;Ezt természetesen ugyanúgy lehet a böngészőbe importálni.&lt;/p&gt;

&lt;a rel="lightbox" href="http://1.bp.blogspot.com/_czKgycLvmNo/TU2sQ84OEYI/AAAAAAAAF0k/eieBV-o0KUA/s1600/jtechlog_tanusitvany.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 274px; height: 320px;" src="http://1.bp.blogspot.com/_czKgycLvmNo/TU2sQ84OEYI/AAAAAAAAF0k/eieBV-o0KUA/s320/jtechlog_tanusitvany.png" border="0" alt="Importált tanúsítvány" id="BLOGGER_PHOTO_ID_5570297721346986370" /&gt;&lt;/a&gt;

&lt;p&gt;Ha hiteles tanúsítványt szeretnénk, akkor a tanúsítványunkat egy hitelesítésszolgáltatónak is alá kell írnia. Ehhez először egy un. kérvényt (csr - &lt;a href="http://en.wikipedia.org/wiki/Certificate_signing_request"&gt;Certificate signing request&lt;/a&gt;) kell készítenünk, és beküldenünk a hitelesítésszolgáltatónak. Ez a PKCS #10 specifikációnak megfelelő formátumban teszi.

&lt;pre&gt;
keytool -certreq -keystore mykeystore -storepass storepass -keypass keypass -alias jtechlog -file jtechlog.csr
&lt;/pre&gt; 

&lt;p&gt;Ennek tartalma szintén egy bináris állomány Base64-gyel kódolva, a következő formátumban:&lt;/p&gt;

&lt;pre&gt;
-----BEGIN NEW CERTIFICATE REQUEST-----
MIICTDCCAgoCAQAwSDELMAkGA1UEBhMCSFUxDTALBgNVBAoTBEJsb2cxETAPBgNVBAsTCEpUZWNo
...
AhQJp7pADvkSv8V5rzZFwv0kj/w+aA==
-----END NEW CERTIFICATE REQUEST-----
&lt;/pre&gt;

&lt;p&gt;Erre a hitelesítésszolgáltató egy felülhitelesített tanúsítványt küld vissza a megfelelő azonosítás és díjfizetés után. Szerencsére lehetőség van a hitelesítésszolgáltatóktól teszt tanúsítványt is igényelni. A NetLock esetén pl. egy &lt;a href="https://www.netlock.hu/index.cgi?lang=HU&amp;amp;tem=ANONYMOUS/online/online_indul.tem"&gt;űrlapon&lt;/a&gt; az e-mail címünket megadni, majd oda kapjuk a további instrukciókat. Első körben le kell tölteni a NetLock Teszt Tanúsítványkiadó &lt;a href="http://www.netlock.hu/index.cgi?raw&amp;amp;ca=teszt3&amp;amp;lang=HU"&gt;tanúsítványát&lt;/a&gt;, majd letölthetjük a kapott teszt tanúsítványt. (Zárójelben megjegyzem, hogy ugyanilyen teszt tanúsítvány a &lt;a href="http://srv.e-szigno.hu/menu/index.php?lap=teszt_igenyles"&gt;Microsec honlapjáról&lt;/a&gt; is letölthető.) A NetLock által kiadott teszt tanúsítvány SHA-256 hash algoritmust és 2048 bit hosszú RSA kulcspárt használ.&lt;/p&gt;

&lt;a rel="lightbox" href="http://4.bp.blogspot.com/_czKgycLvmNo/TU2scTiz2vI/AAAAAAAAF0s/0M9h87Jp_SA/s1600/netlock_teszt_tanusitvany.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 275px; height: 320px;" src="http://4.bp.blogspot.com/_czKgycLvmNo/TU2scTiz2vI/AAAAAAAAF0s/0M9h87Jp_SA/s320/netlock_teszt_tanusitvany.png" border="0" alt="Teszt tanúsítvány" id="BLOGGER_PHOTO_ID_5570297916409764594" /&gt;&lt;/a&gt;

&lt;p&gt;Ez a böngészőbe települ, ahonnan PKCS #12 formátumban tudunk tanúsítványt exportálni. Ebben azonban a titkos kulcs is benne van, hiszen csak így tudjuk megfelelően felhasználni. Szerencsére a keytool már ismeri a PKCS #12 formátumot is, csak a &lt;code&gt;-storetype PKCS12&lt;/code&gt; paramétert kell használnunk. A böngészőből tehát mentsük ki a tanúsítványt PKCS #12 formátumban, jtechlog-netlock-test.p12 néven, és adjunk meg egy jelszót: storepass. Listázzuk ki a tartalmát a keytool segítségével.&lt;/p&gt;

&lt;pre&gt;
keytool -list -keystore jtechlog-netlock-test.p12  -storetype PKCS12 -storepass storepass

Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 1 entry

netlock teszt aláíró tanúsítvány netlock kft. azonosítója, 2011.02.05., PrivateKeyEntry,
Certificate fingerprint (MD5): 92:4F:6A:DA:0F:29:99:F9:73:C5:AF:7E:2E:AF:AC:A8
&lt;/pre&gt;

&lt;p&gt;A tanúsítványt a titkos kulccsal át is importálhatjuk a saját keystore-unkba.&lt;/p&gt;

&lt;pre&gt;
keytool -importkeystore -deststorepass storepass -destkeypass keypass -destkeystore mykeystore -srckeystore jtechlog-netlock-test.p12   -srcstoretype PKCS12 -srcstorepass storepass -alias "netlock teszt aláíró tanúsítvány netlock kft. azonosítója"
&lt;/pre&gt;

&lt;p&gt;Ez után ha kilistázzuk a kulcstárunkat, láthatjuk, hogy benne van. Ahhoz, hogy használatba tudjuk venni, a NetLock Teszt Tanúsítványkiadó tanúsítványát is ki kell mentenünk a böngészőből ("NetLockTeszt(ClassT3)CA.crt") néven, majd azt is importáljuk a kulcstárunkba.&lt;/p&gt;

&lt;pre&gt;keytool -importcert -keystore mykeystore -storepass storepass -alias netlockteszt -file "NetLockTeszt(ClassT3)CA.crt"

Owner: EMAILADDRESS=info@netlock.hu, CN=NetLock Teszt (Class T3) CA, OU=Tanúsítványkiadó, O=NetLock Kft., L=Budapest, C=HU
Issuer: EMAILADDRESS=info@netlock.hu, CN=NetLock Teszt (Class T3) CA, OU=Tanúsítványkiadó, O=NetLock Kft., L=Budapest, C=HU
Serial number: 49ac23040010
Valid from: Mon Mar 02 19:18:44 CET 2009 until: Sat Mar 01 19:18:44 CET 2014
Certificate fingerprints:
         MD5:  47:A8:6B:D3:09:74:60:CD:F4:FF:C1:D6:08:0D:20:BE
         SHA1: 90:AD:6E:9B:6E:EE:DC:10:32:65:A2:8D:AD:8C:D1:D3:E0:E6:A4:58
         Signature algorithm name: SHA256withRSA
         Version: 3

Extensions:

#1: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
  Key_CertSign
  Crl_Sign
]

#2: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
  CA:true
  PathLen:4
]

#3: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 08 8B 02 68 AA 5B 9D BF   2E 11 4B 02 39 34 23 85  ...h.[....K.94#.
0010: 9B B4 95 D6                                        ....
]
]

Trust this certificate? [no]:
&lt;/pre&gt;

&lt;p&gt;Látható, hogy importáláskor megkérdezi, hogy megbízunk-e a tanúsítványba, azaz a beszerzési forrásunk megbízható volt. A JDK alapértelmezetten tartalmazza több hitelesítésszolgáltató tanúsítványát. Egyrészt vannak rendszerszintű tanúsítványok, valamint vannak felhasználóhoz tartozó tanúsítványok. Ezeket a &lt;a href="http://download.oracle.com/javase/6/docs/technotes/guides/deployment/deployment-guide/jcp.html#security"&gt;Java Control Panel-en&lt;/a&gt; is fel lehet venni. A rendszer szintűek a JRE lib\security könyvtárban vannak, jelszava changeit. A felhasználói szintű tanúsítványok a Unix-on a ${user.home}/.java/deployment/security könyvtárban, Windows-on a ${deployment.user.home}\security könyvtárban vannak (pl. "C:\Documents and Settings\vicziani\Application Data\Sun\Java\Deployment\security\trusted.certs"), ezeknek nincs jelszavuk.&lt;/p&gt;

&lt;a rel="lightbox" href="http://1.bp.blogspot.com/_czKgycLvmNo/TU2sqJcZwNI/AAAAAAAAF00/aFYq-jdOZmk/s1600/java_control_panel.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 233px;" src="http://1.bp.blogspot.com/_czKgycLvmNo/TU2sqJcZwNI/AAAAAAAAF00/aFYq-jdOZmk/s320/java_control_panel.png" border="0" alt="Java Control Panel" id="BLOGGER_PHOTO_ID_5570298154216702162" /&gt;&lt;/a&gt;

&lt;p&gt;Kilistázva a kulcstárunkat láthatjuk, hogy már három tanúsítvány van a kulcstárunkban:&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;netlock teszt aláíró tanúsítvány netlock kft. azonosítója: NetLock hitelesítésszolgáltató teszt tanúsítvány&lt;/li&gt;
 &lt;li&gt;jtechlog: önaláírt tanúsítvány, privát kulccsal&lt;/li&gt;
 &lt;li&gt;netlockteszt: netlock által számomra kiosztott teszt tanúsítvány, privát kulccsal&lt;/li&gt;
 &lt;/ul&gt;

&lt;pre&gt;
keytool -list -keystore mykeystore -storepass storepass

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 3 entries

netlock teszt aláíró tanúsítvány netlock kft. azonosítója, 2011.02.05., PrivateKeyEntry,
Certificate fingerprint (MD5): 92:4F:6A:DA:0F:29:99:F9:73:C5:AF:7E:2E:AF:AC:A8
jtechlog, 2011.02.05., PrivateKeyEntry,
Certificate fingerprint (MD5): 8B:FF:C4:FA:38:E7:45:59:64:18:AE:99:F4:F4:80:11
netlockteszt, 2011.02.05., trustedCertEntry,
Certificate fingerprint (MD5): 47:A8:6B:D3:09:74:60:CD:F4:FF:C1:D6:08:0D:20:BE
&lt;/pre&gt;

&lt;p&gt;Próbáltam keresni GUI-t a keytool-hoz, de ami bíztató volt, csak egyet találtam &lt;a href="http://ssltools.sourceforge.net/"&gt;Elysian Keytool Advanced GUI&lt;/a&gt; néven ( 2009. februárjában került ki az utolsó - 2.0 alpha - verzió). Sajnos a példa kulcstárat nem sikerült megnyitnia, kivételt dobott. Így marad a parancssor.&lt;/p&gt;

&lt;p&gt;Megjegyzem, hogy az openssl is képes X.509 és PKCS #12 tanúsítványokat, valamint PKCS #10 Certificate signing request-eket használni, melyek kezelhetők a keytool-lal.&lt;/p&gt;

&lt;p&gt;Az, hogy hogyan használjuk fel ezeket a kulcsokat, egy későbbi post témája lesz.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-100801776275799553?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/100801776275799553/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2011/02/elektronikus-alairas-es-alkalmazasa.html#comment-form" title="6 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/100801776275799553?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/100801776275799553?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2011/02/elektronikus-alairas-es-alkalmazasa.html" title="Elektronikus aláírás és alkalmazása Java-ban, kulcskezelés" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_czKgycLvmNo/TU2rQzkwl3I/AAAAAAAAFz4/5AbNizXPqRQ/s72-c/netlock_tanusitvany.png" height="72" width="72" /><thr:total>6</thr:total></entry><entry gd:etag="W/&quot;CUcDR3c7fip7ImA9Wx9WFkQ.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-70696356624550932</id><published>2010-12-18T09:04:00.010+01:00</published><updated>2011-01-22T11:44:36.906+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-22T11:44:36.906+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Community" /><title>Legjobb fejlesztő 2010 verseny tapasztalatok</title><content type="html">2010. szeptemberében került kiírásra a &lt;a href="http://java2010.legjobbfejleszto.com/"&gt;Legjobb fejlesztő 2010&lt;/a&gt; verseny, melyről már korábban is &lt;a href="http://jtechlog.blogspot.com/2010/09/legjobb-fejleszto-2010-java-programozo.html"&gt;hírt adtam&lt;/a&gt;. Az &lt;a href="http://www.ipsystems.hu/"&gt;IP Systems Kft.&lt;/a&gt; szervezte, és egy &lt;a href="http://java2010.legjobbfejleszto.com/feladat"&gt;valós probléma&lt;/a&gt; leegyszerűsített változatát kellett megoldani egy konkrét alkalmazás kifejlesztésével.
&lt;p&gt;Az IP Systems Kft. engem is meghívott a zsűritagok közé, és megoldások értékelésnél egy bonyolult szempontrendszert sikerült kidolgoznunk. Három fő szempont alapján pontoztuk a megoldásokat, melyeket további alszempontokra bontottunk. A három fő szempont az üzleti funkciók kidolgozottsága és az ergonomikus felhasználói felület, a technológiai megoldás, valamint a forráskód minősége. Ezen szempontok közül én a technológiai megoldást pontoztam, mely során a következőket értékeltem:
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Java SE ismerete (a versenyző mennyire ismeri és használja jól a standard API-t, milyen interfészeket, osztályokat választ, és azokat hogyan használja, nem rekedt-e meg az 1.4-es Java-nál)&lt;/li&gt;
&lt;li&gt;Szabványoknak való megfelelőség&lt;/li&gt;
&lt;li&gt;3rd party komponensek, könyvtárak kiválasztása és használata&lt;/li&gt;
&lt;li&gt;Rétegekre bontás (hiszen főleg webes alkalmazásokkal indultak a versenyzők), milyen az alkalmazás belső szerkezete, mennyire moduláris, a modulok saját, jól körülhatárolt feladattal rendelkeznek-e, és milyen függőségben vannak egymással&lt;/li&gt;
&lt;li&gt;Hiba és kivételkezelés&lt;/li&gt;
&lt;li&gt;Van-e az alkalmazásban szűk keresztmetszet, első ránézésre performancia problémát okozó kódrészletek&lt;/li&gt;
&lt;li&gt;Mennyire lehet információkat megtudni az alkalmazás futásáról, mennyire támogatja a hibakeresést, naplózás technikai megvalósítása és tartalma&lt;/li&gt;
&lt;li&gt;Hogyan épül fel a projekt és a build folyamat, mennyire alkalmazkodik a konvenciókhoz.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A verseny hírlevelére közel 300-an regisztráltak, végül 14-en adtak be megoldást (ebből sajnos egyet nem sikerült elindítani, hisz nem felelt meg a feltételeknek), illetve egyvalaki versenyen kívül.&lt;/p&gt;
&lt;p&gt;Technológiai megkötés nem volt, lényeg, hogy Java-ban legyen implementálva. Nem volt kötelező a webes alkalmazás, csak preferált. Kiemeltük, hogy egy paranccsal build-elni lehessen a projektet, és egyszerűen telepíthető legyen. A teszt környezet Windows, Internet hozzáféréssel, Internet Explorer-rel (bekapcsolat JavaScript-tel). Build-eléshez Ant és Maven előre telepített volt. Web konténer az Apache Tomcat, alkalmazásszerver GlassFish volt. Nem volt kötelező adatbázist használni, amennyiben mégis szükség volt rá, MySQL, PostgreSQL és Oracle Express Edition állt rendelkezésre. Ezekhez csak DataSource-on keresztül lehetett hozzáférni, ez és a szükséges driver előre telepített volt. Adatbázis sémát létrehozni és azt kezdő adatokkal feltölteni az alkalmazásnak kellett. Mindenkit bíztattunk a proaktivitásra, hogy kérdezzen.&lt;/p&gt;
&lt;p&gt;Már a technológiai kérdések között is feltűnő volt, hogy a legtöbben a build-re és a deploy-ra kérdeztek rá, ez utóbbival kapcsolatban is speciálisan a DataSource használatára, úgy látszik, koránt sem olyan evidens. Többen féltek attól, hogy mi van, ha nem sikerül a build vagy a deploy folyamat (mint később kiderült, jogosan). Valaki rákérdezett, hogy az előfordítási folyamatok is a build részét képezzék-e (pl. GWT compile). Kérdés volt, hogy a Maven kap-e internet hozzáférést, és milyen repository-k vannak bekonfigurálva. Volt, aki a build folyamat részeként szerette volna a deploy-t is elvégezni, akár a DataSource konfigurációval, akár az adatbázis séma létrehozással egyetemben. Páran fennakadtak azon, hogy az adatbázist és bele a rekordokat az alkalmazásnak kell létrehoznia. (Igaz, hogy ez éles környezetben nem javasolt, itt csak a saját dolgunkat akartuk megkönnyíteni.) Volt valaki, aki már látott olyant, hogy az alkalmazás és az adatbázis között tűzfal van, ami elvághatta a kapcsolatot, megbolondítva ezzel a connection pool-t, így arra kérdezett rá, hogy fel kell-e erre készülni, JDBC URL-ben ki lesz védve, vagy manuálisan kell vizsgálnia a kapcsolat érvényességét. (Amúgy nem volt tűzfal, de ha van, akkor mi a DBCP pool esetén a validation query-t szoktuk használni.) Többen próbálták a határokat kitolni, pl. Flex-ben fejleszteni a felületet (végül nem jött ilyen megoldás), Scala használata, vagy az üzleti logika letolása PL/SQL rétegbe, triggerekbe (ezt nem támogattuk, hiszen a Java tudásra voltunk kiváncsiak). Csak egy kérdező volt, akinek nagyobb rendszerben szerzett üzemeltetési tapasztalata lehetett, és méretezésre, rendelkezésre állásra kérdezett rá, valamint arra, hogy egyenletes-e a terhelés (sajnos ő később nem adott be megoldást). Egy kérdés érkezett arra, hogy mennyire kell optimalizálni, adatbázis indexeket használni, cache-elni. Szintén egy kérdező volt, akinek portál tervezési tapasztalatai lehettek, így felmerült az xhtml, kikapcsolt cookie-k, captcha, többnyelvűség, akadálymentesítés (egyik sem volt követelmény). Több kérdés volt a böngésző kompatibilitásra is. Volt kérdés az autentikációval (pl. egy felhasználónak több session-je) és jogosultságkezeléssel (JAAS), valamint a konkurrenciával kapcsolatban is (meglepően kevés). Egy kérdés érkezett, hogy https lesz-e, illetve egy ember kérdezte, hogy a SQL injection-re fel kell-e készülni. Az is kiderült, hogy a fejlesztők nem maguknak szeretnek megjegyzéseket használni, hanem rákérdeznek, hogy kötelező-e. Itt is volt olyan hang, aki nem 3rd party framework-öt használt, hanem saját fejlesztésűt kívánt bevetni. &lt;/p&gt;
&lt;p&gt;És akkor jöjjön néhány adat, hogy ki és mit használt, valamint néhány tapasztalat ezzel kapcsolatban.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="http://chart.apis.google.com/chart?chs=400x200&amp;amp;cht=p&amp;amp;chd=s:CDBC&amp;amp;chl=Eclipse+%284%29%7CNetBeans+%285%29%7CIDEA+%281%29%7CIsmeretlen+%284%29&amp;amp;chtt=IDE&amp;amp;chts=676767,12.5" alt="IDE" /&gt;&lt;/p&gt;
&lt;p&gt;A fejlesztőeszköz területén nem volt nagy meglepetés, a NetBeans és Eclipse fej-fej mellett, valamint egy IDEA felhasználó. A többi projektről nem derült ki, pl. Maven-nel fordult, és csak a Maven-es pom.xml volt a projektben.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="http://chart.apis.google.com/chart?chs=400x200&amp;amp;cht=p&amp;amp;chd=s:EBCBB&amp;amp;chl=MySQL+%287%29%7CPostgreSQL+%282%29%7COracle+%283%29%7CEmbedded+-+H2+%281%29%7CNincs+%281%29&amp;amp;chtt=Adatb%C3%A1zis&amp;amp;chts=676767,12.5" alt="Adatbázis" /&gt;&lt;/p&gt;
&lt;p&gt;Adatbázisok közül egyértelműen a MySQL volt a legnépszerűbb. Meglepő volt számomra, hogy beágyazott adatbázist csak egy versenyző használt. Az ő munkája ilyen szempontból kiemelkedő volt, Maven-nel Jetty-t indított, és H2 beágyazott adatbáziskezelőt. Ez a megoldást nagyon kényelmes volt, hiszen nem kellett telepíteni, konfigurálni, hanem azonnal indult. Jó lett volna, ha több ilyen megoldást kapunk. Érdekes még, hogy nem vártunk el adatbázis kapcsolatot, és csak egy versenyző merte ezt mégis megrizikózni. Természetesen nem kapott ezért kevesebb pontot, hiszen nem volt követelmény. Egyszerűen Java Collections Framework-kel oldotta meg a tárolást.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="http://chart.apis.google.com/chart?chs=420x200&amp;amp;cht=p&amp;amp;chd=s:ECBC&amp;amp;chl=Tomcat+%286%29%7CGlassfish+%284%29%7CJetty+%281%29%7CVastag+%283%29&amp;amp;chtt=Alkalmaz%C3%A1sszerver&amp;amp;chts=676767,12.5" alt="Alkalmazásszerver" /&gt;&lt;/p&gt;
&lt;p&gt;Alkalmazásszerverek, pontosabban web konténerek és alkalmazásszerverek között a Tomcat volt a favorit, ami nem meglepő. Igaz, hogy csak ezt a két választási lehetőséget adtuk, de a sok alkalmazásszerver engedélyezése nagyban megnehezítette volna az értékelést. Volt érdeklődő, aki pl. JBoss-t is szívesen használt volna, de mivel az nem volt opció, a Seam-et, EJB3-astúl, JSF-estűl rágyógyította a Tomcat-re. Érdekes, hogy a Glassfish választása nem hozta magával az EJB vagy a JSF használatát, volt aki Hibernate-et használt Glassfish-on, volt, aki Spring-et. Hárman nem is webes, hanem Swing-es alkalmazást készítettek.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="http://chart.apis.google.com/chart?chs=400x200&amp;amp;cht=p&amp;amp;chd=s:EDB&amp;amp;chp=0.1&amp;amp;chl=Ant+%287%29%7CMaven+%285%29%7CNincs+%282%29&amp;amp;chtt=Build&amp;amp;chts=676767,12.5" alt="Build" /&gt;&lt;/p&gt;
&lt;p&gt;A legnagyobb csalódást a build folyamatok és a telepítés (deploy) okozták. Különösen úgy, hogy kizárással fenyegettünk, ha valakinek nem fordult egy paranccsal, és nem lehetett a kimenetet azonnal telepíteni, vagy futtatni. Ha ezt betartottuk volna, a pályaművek felét ki kellett volna zárnunk. Látható, hogy még mindig az Ant vezeti a mezőnyt, és volt, aki nem is használt build eszközt (na jó, a Maven több,  project management and comprehension tool). A legtöbben nem tudták, hogy hogyan is érdemes a DataSource-t Tomcat-ben definiálni, vagy hogyan szokás, és hogyan kell használni. (Erről írtam &lt;a href="http://jtechlog.blogspot.com/2009/01/jndi-nevek-tomcat-alatt.html"&gt;korábban&lt;/a&gt;.) Több helyen kellett manuálisan szerkesztenem a context.xml állományt, pedig erre nincs szükség. Erről még részletesebben fogok értekezni egy későbbi bejegyzésben. Volt, akinek problémát okozott, hogy hol érdemes az adatbázist inicializálni, hol lehet az alkalmazás indulását észlelni.&lt;/p&gt;
&lt;p&gt;Sajnos többen is függtek a fejlesztőeszköztől vagy a környezettől, azaz meg kellett adni a NetBeans vagy a Glassfish telepítési mappáját. Sajnos a NetBeans alapból olyan projektet készít, amiben vannak abszolút hivatkozások. Valamint szükség van egy JAR-ra is a fordításhoz. Többen ezt nem vették figyelembe. Volt persze helyes megoldás is, a JAR-t csatolni kell, és build-kor egy környezeti változót felüldefiniálni: -Dlibs.CopyLibs.classpath="lib\org-netbeans-modules-java-j2seproject-copylibstask.jar". Ez persze a NetBeans szégyene, az érdekes, hogy erről több versenyző nem tudott. Javasolt volt pedig egy üres (legalábbis virtuális) gépen kipróbálni a build folyamatot. Összességében látható, hogy a fiatalabb fejlesztők nem fektetnek annyi hangsúlyt a build folyamatra, a hordozhatóság sérült, ezzel pl. egy continuous integration rendszerbe való bekötés lehetősége is.&lt;/p&gt;
&lt;p&gt;Volt olyan aki külön projektbe tette a teszt eseteket. Volt, aki olyan technológiát használt (DataNucleus), melyhez nem volt Maven plugin, így Ant-ot kellett hívni java task-kal. Volt, akinél a build folyamat nem talált megfelelő artifact-ot a Maven repository-ban. Feltehetőleg magának a lokális repository-ba feltelepítette, és erről megfeledkezett. Egy versenyző azon bukott meg sajnos, hogy nem lehetett build-elni, és azonnal telepíteni az alkalmazását.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="http://chart.apis.google.com/chart?chs=400x200&amp;amp;cht=p&amp;amp;chd=s:CCBE&amp;amp;chp=0.1&amp;amp;chl=Log4J+%283%29%7Cjava.util.Logging+%283%29%7CEgy%C3%A9b+%281%29%7CNincs+%287%29&amp;amp;chtt=Napl%C3%B3z%C3%A1s&amp;amp;chts=676767,12.5" alt="Naplózás" /&gt;&lt;/p&gt;
&lt;p&gt;Ismét egy nagy csalódás. A versenyzők java nem naplózott. Aki használta is, az is inkább kötelességből, vagy a fejlesztőeszköz generálta oda. Úgy látszik, hogy nem érezték szükségét az értelmezhető napló állománynak, támogatva ezzel a visszakövethetőséget. Volt AOP-os megoldás is (interceptor-ral), mely azt írta ki, hogy melyik metódus lett meghívva. Ez üzletileg kevés információt tartalmaz, talán érdemes kiegészíteni egyedi napló üzenetekkel is, melyek az üzleti folyamatokról és modellről adnak bővebb információkat.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="http://chart.apis.google.com/chart?chs=400x200&amp;amp;cht=p&amp;amp;chd=s:DBF&amp;amp;chp=0.1&amp;amp;chl=JUnit+%285%29%7CTestNG+%281%29%7CNincs+%288%29&amp;amp;chtt=Teszt+esetek&amp;amp;chts=676767,12.5" alt="Naplózás" /&gt;&lt;/p&gt;
&lt;p&gt;Ez is érdekes, hogy teszt esetek írásával kevesen töltötték az idejüket, dacára annak, hogy mostanában a csapból is ez folyik. Akik mégis írtak ilyeneket, azoknál is volt, ahol keveredett a unit teszt és az integrációs teszt fogalma. Mock keretrendszer is csak egy munkában volt (EasyMock).&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="http://chart.apis.google.com/chart?chs=400x200&amp;amp;cht=p&amp;amp;chd=s:CCCBBB&amp;amp;chp=0.1&amp;amp;chl=JPA+-+Hibernate+%283%29%7CJPA+-+EclipseLink+%284%29%7CJDBC+%283%29%7CJDO+%281%29%7CHibernate+%282%29%7CNincs+%281%29&amp;amp;chtt=Adatb%C3%A1zis+el%C3%A9r%C3%A9s&amp;amp;chts=676767,12.5" alt="Adatbázis elérés" /&gt;&lt;/p&gt;
&lt;p&gt;Dícsérendő, hogy sokan használtak ORM réteget. Látható, hogy a szabvány nagy úr, a JPA használata messze leelőzte a Hibernate-et, és JDO-ból is csak egy volt. Az, hogy a JPA implementációk közül a EclipseLink vagy a Hibernate-e a nyerő, ebből nem megállapítható, hiszen a kiírásban Glassfish alkalmazásszerver szerepelt, melynek a beépített JPA provider-e az EclipseLink, így egy kicsit torzít. Szép megoldások születtek, de a JPA 2 nyomait még nem nagyon találtam.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="http://chart.apis.google.com/chart?chs=400x200&amp;amp;cht=p&amp;amp;chd=s:CBBF&amp;amp;chl=EJB3+%283%29%7CSpring+%282%29%7CSeam+%281%29%7CNincs+%288%29&amp;amp;chtt=%C3%9Czleti+logika+r%C3%A9teg&amp;amp;chts=676767,12.5" alt="Üzleti logika réteg" width="400" height="200" /&gt;&lt;/p&gt;
&lt;p&gt;Szintén egy meglepő eredmény. És az is látszik, hogy a szabvány itt is tarol. Érdekes, hogy a Dependency Injection, Inversion of Control még nincs mindenkinek az eszköztárában, és nem hiányzik, ahogy az interfészekkel való programozás sem valósul meg mindenütt.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="http://chart.apis.google.com/chart?chs=400x200&amp;amp;cht=p&amp;amp;chd=s:EBCBBB&amp;amp;chp=0.1&amp;amp;chl=JSF+%286%29%7CVaadin+%282%29%7CSwing+%283%29%7CSpring+MVC+%281%29%7CGWT+%281%29%7CServlet%2FJSP+%281%29&amp;amp;chtt=UI+r%C3%A9teg&amp;amp;chts=676767,12.5" alt="UI réteg" /&gt;&lt;/p&gt;
&lt;p&gt;Itt már nagyobb a szórás, de itt is az látszik, hogy a szabvány (JSF) szignifikánsan vezet. A számomra oly kedvelt, illetve az oly sokszor emlegetett keretrendszerek (Spring MVC, GWT, Struts, Tapestry, Wicket) sehol sincsenek. Ezen érdemes egy kicsit elgondolkodni, hogy milyen irányba is érdemes menni, ha a piacon lévő fiatalabb fejlesztők ilyen ismeretekkel rendelkeznek. Persze a JSF sem olyan homogén, használt keretrendszerek: RichFaces (hárman is!), Seam, Trinidad, PrimeFaces, Facelets. Mondjuk túl messzemenő következtetéseket ne vonjunk le, hiszen a versenyzők maguk is bevallották, hogy sokan a verseny feladaton próbálták ki a kiválasztott keretrendszert, és nem rendelkeztek sok tapasztalattal.&lt;/p&gt;
&lt;p&gt;Persze a legtöbb webes felület AJAX-os volt, de főleg Java-s keretrendszer biztosította, és nem natívan került felhasználásra, JavaScript-et nagyon kevesen írtak. Egy műben szerepelt alacsony szinten megvalósítva, ebben DWR, JQuery és JAXB is volt. Szerencsére azt is ritkán láttam, hogy Java kód keveredett volna HTML-lel.&lt;/p&gt;
&lt;p&gt;A Swing-es alkalmazásokból hiányoltam a szálkezelést, a konkurencia kezelését.&lt;/p&gt;
&lt;p&gt;Olyan érdekes technológiák, könyvtárak és eszközök is megjelentek, mint az Envers entitások auditálására, JRebel a fejlesztési ciklus gyorsítására, DataNucleus az adatok perzisztálására, Hazelcast elosztott cache.&lt;/p&gt;
&lt;p&gt;Amit még meg kell említeni, az a jogosultságkezelés. Egy Spring Security volt, egy JBoss Rules-zal megvalósított nagyon egyedi megoldás és egy JAAS. A többiek teljesen egyedileg programozták le. Úgy tűnik ezen a területen sincs még joker megoldás.&lt;/p&gt;
&lt;p&gt;A kivételkezelés is ad-hoc módon történt, érződött, hogy sok helyen csak azért van, mert nem lehet kikerülni, általában nem jól átgondolt stratégiával történt, tisztelet a kivételnek.&lt;/p&gt;
&lt;p&gt;Ami számomra hatalmas pozitívum, hogy egyrészt a Java nyelvben otthonosan mozogtak a versenyzők, Java SE programozási hibát, melléfogást nem találtam. Copy-paste-et szintén nem. Bár egyértelmű, hogy az újrahasznosítás Java kódban sokkal szebb volt sokaknál, mint a felhasználói felületben. Valamint a keretrendszerek megtanulásával együtt a fiatal fejlesztők megtanulják az alapvető architektúrális felépítéseket, sőt nagyon sokat alkalmaztak akár GoF, akár J2EE tervezési mintákat is. Az alkalmazásokat viszonylag szépen rétegekre bontották. Érdekes, hogy a GoF tervezési mintákat főleg a vastag kliensekre találták ki, a legtöbb példa is a Swing-ben található Java-ban, mégis a vastag klienses megoldásokra se rétegek, se a tervezési minták használata nem volt jellemző.&lt;/p&gt;
&lt;p&gt;A díjkiosztó is nagyon kellemesre sikeredett, jó volt megismerkedni a versenyzőkkel, megismerni a véleményüket a feladattal kapcsolatban, és hallgatni, hogy mivel gyűlt meg a legtöbb bajuk. Jó hír, hogy nem technológiát mondtak, hanem inkább az üzleti problémán kellett többet gondolkodniuk.&lt;/p&gt;
&lt;a href="http://2.bp.blogspot.com/_czKgycLvmNo/TQxrRC6fUsI/AAAAAAAAFm0/L71Gvu0eJ-A/s1600/dijkioszto.jpg" rel="lightbox"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 214px;" src="http://2.bp.blogspot.com/_czKgycLvmNo/TQxrRC6fUsI/AAAAAAAAFm0/L71Gvu0eJ-A/s320/dijkioszto.jpg" alt="Díjkiosztó" id="BLOGGER_PHOTO_ID_5551930381225120450" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;Összességében elmondható, hogy nagyon tanulságos verseny volt, számunkra, mint zsűri számára, és úgy ítélem, a versenyzők számára is. Én személy szerint egy kicsit több pályaművet vártam, nem tudom, hogy mivel lehetett volna még több versenyzőt elcsábítani, hogy mutassa meg tudását. Szerintetek?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-70696356624550932?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/70696356624550932/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2010/12/legjobb-fejleszto-2010-verseny.html#comment-form" title="18 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/70696356624550932?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/70696356624550932?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2010/12/legjobb-fejleszto-2010-verseny.html" title="Legjobb fejlesztő 2010 verseny tapasztalatok" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_czKgycLvmNo/TQxrRC6fUsI/AAAAAAAAFm0/L71Gvu0eJ-A/s72-c/dijkioszto.jpg" height="72" width="72" /><thr:total>18</thr:total></entry><entry gd:etag="W/&quot;CUAEQX47eip7ImA9Wx9RF0w.&quot;"><id>tag:blogger.com,1999:blog-7370998606556338092.post-4133758495264721147</id><published>2010-11-14T20:58:00.004+01:00</published><updated>2010-12-19T00:08:20.002+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-19T00:08:20.002+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Oracle" /><category scheme="http://www.blogger.com/atom/ns#" term="Java EE" /><category scheme="http://www.blogger.com/atom/ns#" term="Community" /><title>Oracle Java Cafe</title><content type="html">&lt;p&gt;Az Oracle újraszervezte a Java Cafe napot, melynek első eseménye 2010. november 12-én, pénteken volt. Erre kedden kaptam először meghívót, szokatlanul későn. Sajnos az eseménynek sem weblapja nincs, sem azt nem tudom, hogy hogyan lehet a listára feliratkozni.&lt;/p&gt;
&lt;p&gt;Az esemény 13:00-ig tartott, és négy előadás hangzott el. A megnyitót Gere István, az Oracle Oktatási Igazgatója nyitotta, hallottunk a Java múltjáról, az Oracle elkötelezettségéről, valamint arról, hogy az Oracle még több erőforrással kívánja fenntartani a platform fejlődését. Ennek egyik oka, hogy a Java az Oracle egyik legsikeresebb portfóliójának, a Fusion Middleware-nek az alapja. A Fusion Middleware nem más, mint azon Oracle termékek gyűjtője, ami nem adatbázis, és Oracle Applications. A SOA őrületet próbálja megvalósítani, így tartalmazza egy SOA implementációhoz szükséges összes komponenst, kezdve az alap infrastruktúrától (pl. alkalmazásszerver, identity, cache, grid, stb.) egyre feljebb, mint pl. integrációs eszközök (aszinkron üzenetküldés, ESB, BPEL, registry, stb.), folyamat irányítás, üzleti szabályok, egészen a legmagasabb szintig, mint üzleti intelligencia, content management, portál. De magába foglalja a fejlesztőeszközöket és felügyeleti eszközöket is. Sok név ismerős lehet az időközben felvásárol BEA-tól, pl. JRockit, Weblogic, vagy a még régebbi Tuxedo, de itt szerepelnek a tradicionális Oracle termékek is, mint az Oracle Application Server, ADF, JDeveloper, Forms és Reports services, Discoverer, stb.&lt;/p&gt;
&lt;p&gt;Az első előadást &lt;a href="http://blogs.oracle.com/nagy/"&gt;Nagy Péter&lt;/a&gt; tartotta a Java múltjáról, jelenéről és jövőjéről. Itt már több technológiáról esett szó, bár főleg olyan információk hangoztak el, melyek a neten már megtalálhatóak voltak. Az Oracle a felvásárlással most két Java Virtuális Géppel rendelkezik, a Sun-féle HotSpot, és a BEA-féle JRocket. A kettőt össze szeretnék fésülni, hogy csak egy legyen, és természetesen az nyílt forrású &lt;a href="http://openjdk.java.net/"&gt;OpenJDK&lt;/a&gt; projekt keretein belül. (Mellyel kapcsolatban a hét híre, hogy az Oracle és az Applce &lt;a href="http://hup.hu/cikkek/20101114/az_apple_es_az_oracle_openjdk_projektet_jelentett_be_az_os_x-hez"&gt;bejelentette&lt;/a&gt; az OpenJDK Project-et Mac OS X-re. A JDK-nak lesz fizetős változata is, melyhez az Oracle hozzáadott szolgáltatásokat biztosít, pl. előbbi hibajavításokat, valamint support-ot. Az Oracle a JavaFX-et is &lt;a href="http://www.javafx.com/roadmap/"&gt;kiemelt helyen kezeli&lt;/a&gt;. Látszik, hogy tervezik a JavaFX 2.0-t, a JavaFX UI nyílt forráskódú lesz, valamint különös hangsúlyt fordítanak a NetBeans alapú fejlesztő eszközre is. Ingyenes előadás is lesz ezzel kapcsolatban, &lt;a href="http://eventreg.oracle.com/webapps/events/ns/EventsDetail.jsp?p_eventId=116172&amp;src=7038703&amp;src=7038703&amp;Act=49"&gt;OTN Developer Day – Java FX&lt;/a&gt; címmel, mely sajnos már betelt.&lt;/p&gt;
&lt;p&gt;Fejlesztőeszközből szintén nőtt a kínálat. A NetBeans lenne a támogatott, belépő szintű fejlesztőeszköz. Viszont aki ki akarja használni a Fusion Middleware-t, annak JDeveloper-t ajánlott telepítenie. Persze az Eclipse tábor is kap egy Enterprise Pack for Eclipse-t. Az alkalmazás szervereknél sem lesz összefésülés, a GlassFish marad a belépő szintű termék, a referencia implementáció, és ennek is lesz kereskedelmi verziója support-tal, gyorsabb hibajavításokkal, valamint management eszközzel. A GlassFish 3.1 is &lt;a href="http://dlc.sun.com.edgesuite.net/glassfish/3.1/promoted/"&gt;elérhető már&lt;/a&gt; early access-ként, és már támogatja a cluster-ezést. Persze a nagyágyú a WebLogic marad, mely a Fusion Middleware támogatott alapja. Ha nem is lesz egybeolvadás, lesznek az alkalmazásszervereknek közös kódrészletei. Ugyanúgy stratégia irány a mobil fejlesztés is, valamint megjelent egy &lt;a href="http://www.oracle.com/us/products/middleware/exalogic/index.html"&gt;Exadata&lt;/a&gt; megoldás is, melyről &lt;a href="http://blogs.oracle.com/zfekete/2010/11/video_a_sysman_exadata_demo_ce.html"&gt;magyar videó is van&lt;/a&gt;. Ez gyakorlatilag egy összehangolt hardver és szoftver megoldás, mely irgalmatlan teljesítményre képes. Ez most az Oracle zászlóshajója a Cloud Computing témakörben.&lt;/p&gt;
&lt;p&gt;Kérdések között felmerült, hogy mi a helyzet az Oracle Forms, Reports és Discoverer-rel? Az Oracle gondolkozott a kivezetésén, térítve az embereket a Java technológia irányába, azonban ez sikertelen, hiszen rengeteg létező, futó alkalmazás van már megvalósítva ezen technológiákkal. Tehát ezek élnek, fejlődnek (11g), Fusion Middleware részét képzik, &lt;a href="http://www.oracle.com/technetwork/middleware/upgrade-092995.html"&gt;lehet már WebLogic-ra migrálni&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Majd Gere István beszélt az Oracle University SUN Java oktatási portfóliójáról. Érezhető, hogy az Oracle komolyan veszi ezt a területet, négy partnerrel együttműködve végzik az oktatásokat. A tanulási lehetőségek szerteágazóak. Egyrészt a legismertebb a tantermi képzések. Ezen kívül lehetséges az e-learning is, Live Virtual Class néven fut. Lehet self study CD-ket is rendelni, melyek használatával a hallgató maga készülhet fel. Valamint létezik egy Knowledge Center is, melyről előfizetés ellenében lehet mindenféle anyagot letölteni.&lt;/p&gt;
&lt;p&gt;Az oktatási portfóliót is eléggé megvariálták, alkalmazkodtak az Oracle Associate/Professional/Master szintjeihez (, bár ezek korábban is megvoltak a Sun-nál). Az első szint kb. azt jelenti, hogy képben vagy, a második szinten tesztet kell kitölteni, és azt jelenti, hogy ismered a specifikációkat, és a harmadik szint jelenti, hogy képes vagy komplex feladatokat is megoldani. (Itt kapsz egy önállóan megoldandó feladatot, majd igazolnod kell esszékérdésekre válaszolva, hogy te oldottad az meg.) A képzéseket, és a képzéshez tartozó vizsgákat tartalmazó dokumentumot később fogják szétküldeni.&lt;/p&gt;
&lt;p&gt;Következő előadás a Java Master és Oracle Junior képzésről szólt, és Nagy Kálmán (Medusoft Kft.) tartotta. Ennek keretében 2x12 ifjú titánt képeznek 4 (elmélet) + 3 (gyakorlat) hétig. Az elején gyakorlatilag megkapják a hivatalos Oracle tanfolyamokat, majd utána egy projektmunkában vehetnek részt. Itt nem csak a szabvánnyal ismerkedhetnek meg, hanem build, continuous integration eszközökkel, teszteléssel, stb. Nemsokára indul a marketing kampány.&lt;/p&gt;
&lt;p&gt;Az utolsó előadást &lt;a href="http://www.delicious.com/sngeza"&gt;Simon Géza&lt;/a&gt; tartotta (Medusoft Kft.), "JavaEE 6: kevesebb kódolás - több eredmény" címmel. A címet &lt;a href="http://blogs.sun.com/arungupta"&gt;Arun Gupta&lt;/a&gt;: Java EE6=Less Code+More Power előadása alapján választotta, mely hazánkban is &lt;a href="http://www.oracle.com/global/hu/education/eblast/hu_emea_ou_oracle_arungupta_011010_ol.html"&gt;meghallgatható lesz&lt;/a&gt; november 25-26-ig. Az előadás a &lt;a href="http://en.wikipedia.org/wiki/Java_EE_version_history"&gt;Java EE 6&lt;/a&gt; érdekesebb újdonságait villantotta fel, melyek célja a még több automatikus ellenőrzés.&lt;/p&gt;
&lt;p&gt;Az EJB egyik legnagyobb újdonsága a Singleton Session Bean, mellyel megvalósítható, hogy az adott Bean-ből JVM-enként csak egy példány létezzen. Itt problémát első sorban a párhuzamosság okozhat, hiszen ugyanazon objektumhoz több szál is hozzáférhet. Pesze erre is van több megoldás, egyik a @Lock annotáció, konténer által vezérelt szinkronizáció estén, valamint használhatjuk a klasszikus synchronized kulcsszót a bean vezérelt szinkronizáció esetén (ezt inkább ne is használjuk). Másik érdekesség a @Asynchronous annotáció, ilyenkor nem kell JMS-t, sorokat használni az aszinkron híváshoz.&lt;/p&gt;
&lt;p&gt;A Java EE egyik új szabványa a Contexts and Dependency Injection for Java (Web Beans 1.0) JSR 299. A szabvány vezetője a RedHat/JBoss volt. Egyrészt megpróbálja egységesíteni a DI-t, ezzel versenybe szállni azokkal a keretrendszerekkel, melyek ezt magasabb szinten űzték (pl. Spring, Guice, stb.). Másrészt kiterjeszti az EJB-ben szereplő DI-t, ugyanis az nagyon korlátozott funkcionalitással rendelkezett, hiszen csak pár komponensben elérhető. Követi az EJB alapkoncepcióját, hogy legyenek intelligens default értékek, ne kelljen konfigurálni, viszont, ha szükség van rá, akkor legyen lehetőség a testreszabásra, akár külön XML állományban is (beans.xml). A szabvány referencia implementációja a &lt;a href="http://seamframework.org/Weld"&gt;Weld&lt;/a&gt;, mely a Seam keretében lett kitalálva, és ezért remekül integrálható vele. A &lt;a href="http://seamframework.org"&gt;Seam&lt;/a&gt; nem más, mint a JBoss megoldása, nyílt forráskódú keretrendszere RIA alkalmazások fejlesztésére. Integrálja az összes réteget, pl. EJB 3.0, JPA, JSF, AJAX, sőt Business Process Management (BPM), ezáltal egy komplett megoldást nyújtva. A Weld amúgy integrálható a Java EE 5 alkalmazás szerverekbe is. Ezáltal minden rétegben, minden objektumban elérhetővé válik a DI, nem csak EJB-ben, vagy servlet-ben. A context, másképpen scope arra utal, hogy mennyi a bean-ek élettartama, lehet request, session, stb., sőt, saját context-et is definiálhatunk. Szintén ismert benne az események fogalma. Annotációkkal használhatjuk, type safe, és akár saját eseményt is definiálhatunk, méghozzá úgy, hogy nem csak annotációt használunk, hanem saját annotációt hozunk létre.&lt;/p&gt;
&lt;p&gt;Szó esett a RESTful web szolgáltatásokról, hiszen a Java EE már a JAX-RS szabványt is tartalmazza. Erről korábban már &lt;a href="http://jtechlog.blogspot.com/2009/12/restful-web-szolgaltatasok-jersey-vel.html"&gt;itt a blogon is&lt;/a&gt; volt szó, ezt nem részletezném. Remekül illik a Java EE architektúrába, egyszerű, annotációkkal konfigurálható, stb.&lt;/p&gt;
&lt;p&gt;Volt szó még a Bean Validation-ről, mely feladata az olyan kényes kérdés megválaszolása, hogy hol és hogyan ellenőrizzük a beadott adatokat. Közel a felülethez, hogy a felhasználó mielőbb választ kapjon? Vagy az adatbázisnál, hogy ne kerüljön hibás adat mentésre? A válasz, hogy legyen ez az adatot hordozó bean-be, majd itt már az a réteg hívhatja meg, amelyik csak akarja. Deklaratív, annotációval adható meg pár előre definiált ellenőrzés. Saját ellenőrzéseket is bevezethetünk, szintén saját annotációk implementálásával (én itt vesztettem el az érdeklődésemet). Emiatt szintén type safe. Lehetőség van persze feltételes ellenőrzések megadására is.&lt;/p&gt;
&lt;p&gt;Említésre került a JPA 2 két sokak által várt újdonsága, egyrészt a rendezett kollekciók, másrészt a Criteria API. Valamint elhangzott, hogy a GlassFish 3.1 is kipróbálható.&lt;/p&gt;
&lt;p&gt;Lesz december 9-én egy 1 napos szeminárium Swiss knife for Java EE6 címmel is, melynek célja, hogy bemutassanak olyan, a gyakorlatban rendszeresen felmerülő problémákat (és lehetséges megoldásaikat), amelyekhez egy kicsit többre van szükség, mint a JavaEE szabvány ismerete. Lesz szó minél hatékonyabb adatbázis-elérésről, adatbázis séma verziózásról, keretrendszerek összehasonlításáról, tesztelésről, forráskód-kezelésről, automatikus fordításról-csomagolásról. &lt;span style="font-weight:bold;"&gt;Update:&lt;/span&gt; Az eseményről bővebben az &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getCourseDesc?dc=D70301_1397068_HU&amp;p_org_id=8&amp;lang=HU"&gt;Oracle-nél&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7370998606556338092-4133758495264721147?l=jtechlog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://jtechlog.blogspot.com/feeds/4133758495264721147/comments/default" title="Megjegyzések küldése" /><link rel="replies" type="text/html" href="http://jtechlog.blogspot.com/2010/11/oracle-java-cafe.html#comment-form" title="3 megjegyzés" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/4133758495264721147?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7370998606556338092/posts/default/4133758495264721147?v=2" /><link rel="alternate" type="text/html" href="http://jtechlog.blogspot.com/2010/11/oracle-java-cafe.html" title="Oracle Java Cafe" /><author><name>Viczián István</name><uri>https://profiles.google.com/115891152269405230539</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-WO4Mwoq2oFg/AAAAAAAAAAI/AAAAAAAAHkQ/db6vYh-R_6M/s512-c/photo.jpg" /></author><thr:total>3</thr:total></entry></feed>

