2015. január 22., csütörtök

Átállás GitHub Pagesre

Már régóta dédelgetem az ötletet, hogy az egész blogot átállítom a GitHub Pagesre, ezzel is konszolidálva minden tartalmat, melyet megosztok. Az átállás technikai problémákba ütközhet. Ha ilyenekkel találkozol a következő napokban, akkor kérlek jelezd a viczian.istvan címen a gmailen. A sikeres átállásról egy külön posztban fogok beszámolni.

Ha RSS olvasót használsz, és pár napon belül nem jelenik meg az újabb poszt, gondolj arra, hogy valami probléma történhetett, keresd fel a http://www.jtechlog.hu oldalt, és vedd fel újra az RSS olvasódba.

Ez az oldal a http://jtechlog.blogspot.com címen még megmarad egy darabig, majd törlöm.

2015. január 3., szombat

Pre-Authentication Spring Security-vel

Felhasznált technológiák: Spring Security 3.2.5, Jetty 9.1.0.v20131115

Vannak olyan esetek, mikor ugyan Spring Security-t szeretnénk használni, azonban autentikációra meghagynánk a webkonténer, vagy az alkalmazásszerver mechanizmusát. Ilyen eset lehetséges, mikor alkalmazásszerverben van beállítva az X.509 tanúsítványok kezelése, vagy esetleg az SSO-val való integráció.

Ebben az esetben az alkalmazásszerver végzi a bejelentkeztetést, esetleg még a jogosultságok kiosztását is, de a többit a Spring Security végzi. Az alkalmazásszerver a bejelentkeztetett felhasználót és jogosultságait a szabványos módon adja át, lekérdezni a Servlet API HttpServletRequest példányának getUserPrincipal() és isUserInRole(java.lang.String role) metódusaival lehet. A Spring Security-t tehát arra kell rábeszélni, hogy a megfelelő esetekben ide delegálja a hívásait.

A Spring Security használata azért lehet hasznos ebben az esetben is, mert a Servlet API-hoz képest rengeteg plusz funkciót ad, mint pl. URL-ek védelme, amihez a jogosultságokat bonyolult kifejezésekkel adhatjuk meg. Vagy pl. az annotáció alapú deklaratív jogosultságkezelés, stb. A Spring Security-ről bővebben egy előző posztomban olvashatsz, melyet ismét frissítettem, hogy a legfrissebb verziókat tartalmazza.

Jelenlegi poszthoz egy példaprogram is letölthető a GitHub-ról. Az mvn jetty:run paranccsal indítható. Bejelentkezni az admin1/admin1 és a user1/user1 felhasználónév jelszó párosokkal lehetséges. és Egy Jetty beépített webkonténert tartalmaz, melybe fel vannak véve a felhasználók, és a hozzá tartozó szerepkörök. Első körben a Jetty Maven pluginnak kell megmondani, hogy hol található a Jetty-hez tartozó konfigurációs állomány.

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.1.0.v20131115</version>
    <configuration>
            <webAppXml>src/main/webapp/WEB-INF/jetty.xml</webAppXml>
    </configuration>
</plugin>

Amennyiben ez megvan, az src/main/webapp/WEB-INF/jetty.xml konfigurációs állományban kell megadni, hogy mely állomány tartalmazza a felhasználókat és szerepköröket.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Get name="securityHandler">
        <Set name="loginService">
            <New class="org.eclipse.jetty.security.HashLoginService">
                <Set name="name">UserRealm</Set>
                <Set name="config">
                    src/main/webapp/WEB-INF/jetty-realm.properties</Set>
                <Call name="start"/>
            </New>
        </Set>
        <Set name="checkWelcomeFiles">true</Set>
    </Get>
</Configure>

A src/main/webapp/WEB-INF/jetty-realm.properties egy elég egyszerű állomány, elöl a felhasználónév, majd a jelszó (plain-text-ben), majd a szerepkör. Teszteléshez tökéletes.

admin1: admin1,admin
user1: user1,user

Majd megadjuk a web.xml-ben, hogy Basic autentikációt használjon. Ilyenkor a böngésző feldob egy ablakot, és az autentikációs információk a HTTP kérés fejlécében utaznak, plain textben. Ez már szabványos Servlet API megoldás.

<security-constraint>
    <web-resource-collection>
        <web-resource-name>allwebresource</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>user</role-name>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>

<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>UserRealm</realm-name>
</login-config>

<security-role>
    <role-name>user</role-name>
</security-role>

<security-role>
    <role-name>admin</role-name>
</security-role>

Ezután már csak a Spring Security-t konfiguráltam be az applicationContext-security.xml állományban, hogy a web konténertől vegye át a felhasználót és a hozzá tartozó szerepköröket. Nézzük az ehhez tartozó konfigurációt.

<http entry-point-ref="entryPoint" auto-config="false">
        <intercept-url pattern="/index.html" 
            access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <intercept-url pattern="/user.html" 
            access="ROLE_USER,ROLE_ADMIN" />
        <intercept-url pattern="/admin.html" 
            access="ROLE_ADMIN" />
        <custom-filter position="PRE_AUTH_FILTER" 
            ref="preAuthFilter" />
</http>

<authentication-manager alias="authenticationManager">
    <authentication-provider ref="authenticationProvider" />
</authentication-manager>

<beans:bean id="entryPoint"
    class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>

<beans:bean id="authenticationProvider"
        class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <beans:property name="preAuthenticatedUserDetailsService" 
        ref="userDetailsService"/>
</beans:bean>

<beans:bean id="userDetailsService" 
    class="jtechlog.springsecurity.service.JpaAuthenticationUserDetailsService"/>

<beans:bean id="preAuthFilter" 
        class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
    <beans:property name="authenticationManager" 
        ref="authenticationManager"/>
    <beans:property name="authenticationDetailsSource">
        <beans:bean 
                class="org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">
            <beans:property name="mappableRolesRetriever">
                <beans:bean 
                    class="org.springframework.security.web.authentication.preauth.j2ee.WebXmlMappableAttributesRetriever" />
            </beans:property>
            <beans:property name="userRoles2GrantedAuthoritiesMapper">
                <beans:bean 
                        class="org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper">
                    <beans:property name="convertAttributeToUpperCase" 
                        value="true"/>
                </beans:bean>
            </beans:property>
        </beans:bean>
    </beans:property>
</beans:bean>

Ez talán már igényelhet némi magyarázatot. Az entryPoint bean mondja meg, hogy a konténerre van bízva az autentikáció. Az authenticationProvider mondja meg, hogy honnan kell a felhasználót feltölteni. Itt egy PreAuthenticatedAuthenticationProvider példányt használunk, ami azt mondja, hogy az autentikációt már elvégezte a konténer, és ennek eredménye alapján tölthetünk be saját User példányt. Ezt a saját JpaAuthenticationUserDetailsService példányunk teszi, adatbázisból a felhasználónév alapján JPA technológiával. A preAuthFilter bean a web.xml-ben talált szerepköröket mappeli át Spring Security-sra, nagybetűsít, és alapértelmezetten hozzáfűzi a ROLE_ prefixet. tehát az admin és a user szerepkörből csinál ROLE_ADMIN és ROLE_USER szerepköröket, vagy ahogy a Spring Security hívja, granted authority-ket.

A saját JpaAuthenticationUserDetailsService lényeg része a következőképp néz ki.

@Override
public UserDetails 
        loadUserDetails(PreAuthenticatedAuthenticationToken token) 
        throws UsernameNotFoundException {
    try {        
        User user = entityManager
            .createQuery("select u from User u where u.username = :username", User.class)
            .setParameter("username", token.getName())
            .getSingleResult();

        PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details =
            (PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails) token.getDetails();

        user.setAuthorities(details.getGrantedAuthorities());
        return user;
    } catch (NoResultException nre) {
        throw new UsernameNotFoundException("A felhasználó a megadott felhasználónévvel nem található: " + token.getName(), nre);
    }
}

A paraméterként kapott token már tartalmazza az alkalmazásszerver által meghatározott felhasználónév és szerepkör információkat, ez alapján betöltjük adatbázisból a felhasználót, és beállítjuk a szintén megkapott szerepköröket.

2014. november 13., csütörtök

Java ki kicsoda

Ezzel a poszttal azokat az embereket szeretném bemutatni, akiket érdemes követni Java programozóként, hiszen sokat tesznek a közösségért, vagy meghatározó/érdekes gondolataik vannak ebben a témában. Természetesen a lista nem teljes, ezért amennyiben valakit kihagyok, nyugodtan írjátok meg commentben.

James Gosling

Amennyiben történeti sorrendben akarunk haladni, az ő nevét kell először megemlíteni. A Sun alkalmazottjaként alkotta meg a Java nyelvet, és implementálta az első fordítót és virtuális gépet. Mikor a Sunt megvásárolta az Oracle, kicsit ott dolgozott, majd átment a Google-höz, és most a Liquid Roboticsnál van, ahol óceánjáró robothajókkal foglalkozik. Konferenciákon sztárelőadónak hívják meg, munkája miatt főleg a beágyazott eszközök, IoT, Raspberry Pi témakörök érdeklik, de lelkes használója és evangelistája a NetBeans IDE-nek és a JavaFX-nek.

Blog

Jaroslav Tulach

Ha már Oracle és NetBeans, akkor legyen ő a következő a sorban. A NetBeans egyik alapítója, jelenleg architect az Oracle-nél. Ő az írója a Practical API Design könyvnek, mely a NetBeans Platform API-jának kialakítása közben szerzett tapasztalatokat összegzi, alapmű a témában. Legújabb dobása a DukeScript, mely egy olyan új technológia, mely használatával Javaban írt alkalmazásokat lehet több mobil platformon, vastag kliensként és böngészőben is futtatni.

Blog Twitter

Geertjan Wielenga

Az Oracle és NetBeans íven haladva következzen ő. Product Manager az Oracle-nél, és a NetBeanssel foglalkozik. Rettentő sokat bloggol és twitterezik a témában. Nagyon közvetlen személyiség, válaszol a megkeresésekre, minden érdekli, ami a NetBeansszel kapcsolatos. Prágában kezdett el vele foglalkozni, ahonnan a NetBeans is származik, először mint technical writer. Aki NetBeansszel kicsit is komolyan foglalkozik, biztos futott már bele cikkébe, tutorialjába, ha máshol nem, akkor a helpben.

Blog Twitter

Simon Ritter

A Java evangelisták vezetője az Oracle-nél. Minden konferencián ott van, Magyarországon is volt a Java konferencián, mikor még nagy Sunos rendezvény volt. Irigyelni való figura, az a dolga, hogy játszik, mindig menő dolgokról beszél, mindent kipróbál és bejárja a világot. Lego Mindstorms, Raspberry Pi, Minecraft, robotika, a legújabb API-k, stb.

Twitter

Kohsuke Kawaguchi

Ha már játék és Oracle, az ő nevét sem hagyhatjuk ki. Szintén a Sunnál emelkedett ki mint ifjú titán, még a JAX-WS RI forrásában találkozhattunk a nevével, de igazán a Hudson, illetve Jenkins megalkotásával vált híressé. Rettentő sok energiával rendelkezik, iszonyat gyorsan adott ki új verziókat, foglalkozik mindennel, ami érdekes, hímzéstől kezdve a legózáson át az összes érdekes Java technológiával. Jelenleg CTO a CloudBees cégnél, mely a Jenkisre alapozva próbál üzleti modellt építeni.

Blog Twitter

Joshua Bloch

Az API vonalon maradva ismerkedjünk meg vele. A Java nyelv és API bizonyos részeinek kidolgozásával foglalkozott a Sunnál, leghíresebb munkája a Java Collections Framework, melyet minden Java fejlesztő ismer, és a mai napig időtálló. Írója a magyar nyelvre is lefordított Effective Java könyvnek (Hatékony Java), és társszerzője a szintén magyarul is megjelent Java Puzzlers (Java-fejtörők) és a Java Concurrency in Practice (Párhuzamos Java-programozás a gyakorlatban) könyveknek. Egyetemen tanít, Java vezető architect volt a Google-nél.

Twitter

Doug Lea

A fentebb említett Java Concurrency in Practice könyv társszerzője, a téma egyik legnagyobb szakértője, egyetemi tanár. A Java Community Process tagjaként vezetője volt a JSR 166: Concurrency Utilities szabványnak, mely a Java 5 egyik legnagyobb újdonsága.

Homepage

Adam Bien

Szabadúszó Java fejlesztő és architect a kezdetektől. A Real World Java EE Patterns—Rethinking Best Practices és Real World Java EE Night Hacks—Dissecting the Business Tier könyvek szerzője. Főleg Java EE témakörben tart előadásokat és ír, aktív tagja a JCP-nek ezen témákban. A Java EE technológiát gyakorlati oldalról közelíti meg, és alkalmazza rá a modern megközelítéseket, mint pl. a microservices, anélkül, hogy bedőlne a hype-oknak. Elismerendő, hogy a régóta elavult J2EE Patternöket újra feldolgozta a Java EE-nek megfelelően, és nem félt akár ki is dobálni az elavultakat. Akit érdekel a stílusa, javaslom ezt a videót.

Blog Twitter

Arun Gupta

Az Oracle-nél volt Java EE evangelista, a Glassfish hívő, és nagy felbolydulást keltett, mikor 2013 októberében átment a RedHathez, mikor az Oracle bejelentette a Glassfish támogatásának megszüntetését. Azóta fő érdeklődési területe a JBoss és a WildFly. Mostanában a WebSocket Java EE támogatásával foglalkozik, szívesen nyúl bele a Minecraftba, és foglalkozik azzal is, hogy gyerekek figyelmét hívja fel a programozásra. Több könyvet írt Java EE témában.

Blog Twitter

Rod Johnson

Most menjünk el kicsit a keretrendszerek irányába. Ő a Spring Framework megalkotója. Ő írta a Expert One-on-One J2EE Design and Development könyvet, mely arra fókuszál, hogy milyen hibákat követtünk el a J2EE technológia használatakor, és gyakorlati megoldásokat adott, hogyan kellett volna ezeket elkerülni. Következő könyvében, Expert One-on-One J2EE Development without EJB címmel már arról írt, hogy ne használjuk az EJB technológiát, hanem helyette valami pehelysúlyúbb eszközöket, mint pl. a Spring vagy a Hibernate. Jelenleg olyan cégek és szervezetek működésében vesz rész, mint a Typesafe, mely a Scala, a Play Framework és az Akka mögött áll, vagy a Neo4J, az elasticsearch, a Hazelcast vagy a Meteor.

Twitter

Juergen Hoeller

Szintén Spring alapító, de ő még mindig ott van. Időközben a Springet felvásárolta a VMware, mely EMC Corporation tulajdon. Az EMC és a General Electric alapította a Pivotalt, mely egy olyan cég mely szoftverkomponenseket fejleszt és szolgáltatásokat biztosít adatközpontú és adatelemző egyedi szoftverek agilis fejlesztésére felhő-alapú technológiákra építve. A Springen kívül olyan cuccokat pakoltak még bele, mint a Cloud Foundry, a Redis, a RabbitMQ, a Grails, a Groovy, a Hadoop, stb.

Twitter

Jason Van Zyl

A Maven megalkotója, kezdetben a Sonatype-nál dolgozott, mely a Nexus repository manager gyártója. Mivel itt kicsit eltávolodott a fő csapásiránytól, kilépett, és megalkotta a saját cégét Takari néven, mely Maven oktatással, tanácsadással foglalkozik. Jelenlegi projektjei miatt igen nagyszabású fejlesztéssel foglalkozik, képessé akarja tenni a Mavent arra, hogy beilleszthető legyen a continuous delivery-be. Ennek első megnyilvánulás a The Takari Lifecycle, mely egy plugin, mely teljesen lecseréli a meglévő Maven core plugineket.

Twitter

Ceki Gülcü

Független fejlesztő, az The Apache Software Foundation tagja, a Log4j, SLF4J és a Logback megalkotója, valamint írója a The complete log4j manual könyvnek.

John Ferguson Smart

Független fejlesztő, majd megalapította a saját cégét Wakaleo Consulting néven. Mindig sikerült meglovagolnia az aktuális hullámokat, úgymint Maven, continuous integration and delivery, TDD, BDD, agilis fejlesztés. Ezekkel kapcsolatban három könyvet is írt BDD in Action, Jenkins: The Definitive Guide, Java Power Tools, mind rettentő gyakorlatias jellegű. Ezekben a témákban rengeteget publikál, és konferenciákon beszél.

Blog Twitter

Bruce Eckel

Igazi polyglot programozó, otthonosan mozog Scala, Python, Java, C++, stb. nyelvek területén. Azért jegyzem meg itt, mert ő írta a Thinking in Java című könyvet, mely sokáig kötelező olvasmány volt, és ingyenesen letölthető. A 4. kiadást azonban már meg kell vásárolni.

Blog Twitter

Kent Beck

A Extreme Programming és Test Driven Development metodológiák megalkotója, Erich Gammával (igen-igen, a Tervezési minták könyv egyik szerzője, a Gang of Four tagja, az Eclipse régebbi vezető tervezője, jelenleg a Microsoftnál vezető Microsoft Visual Studio témában) együtt fejlesztették a JUnit keretrendszert, mely de facto standard a unit tesztelés területén. Először használta az agilis szoftverfejlesztés kifejezést, és egyik aláírója az Agile Manifestonak, többek között Martin Fowler és Robert C. Martin (“Uncle Bob”) mellett. Jelenleg sok egyéb mellett a Facebooknál dolgozik.

Twitter

Matt Raible

Webes fejlesztéssel foglalkozó szakember, dolgozott a LinkedInnél, mint UI architect, most saját cégét viszi Raible Designs néven. Őt onnan lehet ismerni, hogy nagyon sok konferencián megjelenik, ahol rettentő jó összehasonlító elemzéseket végez UI framework témakörökben. Saját projektje az AppFuse, mely egy induló projekt, melyben olyan technológiákat pakolt össze, mint Bootstrap, jQuery, Spring, Hibernate, Maven és választható web keretrendszerek, úgymint JSF, Struts 2, Spring MVC, Tapestry 5 vagy Wicket. Mindenképp érdemes elolvasni a prezentációit pl. a legfrissebbet az Angular.JS-ről, összehasonlító elemzését a JVM alapú webes keretrendszerekről, vagy a Play és Grails összehasonlítását.

Blog Twitter

2014. október 4., szombat

Java Application Architecture

Már régóta hajtottam a Kirk Knoernschild: Java Application Architecture könyvet, végre hozzájutottam, és nem is csalódtam benne. Mostanában érdekel a modularizáció, különösen Java környezetben, és kíváncsi voltam, hogy elméleti szinten mit tudnak erről írni. Bár a könyv alcíme “Modularity Patterns with Examples Using OSGi”, senki ne rettenjen meg, akit nem érdekel az OSGi, éppen csak érinti, a könyv OSGi ismeretek nélkül is kitűnő olvasmány.

A könyv a Robert C. Martin sorozatban jelent meg, az előszót is ő (“Uncle Bob”) írta. Talán ezért is kerül szóba olyan hamar a SOLID fogalma, mely az öt alapvető szoftverfejlesztési elv rövidítéseinek mozaikszava. A könyv egyetlen melléklete is ezek kifejtését tartalmazza.

Nekem már a könyv felütése is tetszik, hogy rengeteget foglalkozunk a logikai tervezéssel, mikor is OOP elvek mentén interfészeket, osztályokat alakítunk ki (pl. akár az UML nyelv használatával). Szintén sok energiát szoktunk fektetni abba is, különösen a SOA elterjedésével, hogy szolgáltatásokat alakítsunk ki, interfészeket tervezzünk, és erre alakítsunk ki egy architektúrát. Ezek hatalmas irodalommal is rendelkeznek. De közöttük hiányzik valami.

Ugyanez a felhasználhatóság, újrafelhasználhatóság terén is. Az interfészek, osztályok egy finom szemcsézettséget (fine grained/granularity) adnak. Az újrafelhasználhatóságuk nagyon magas, hiszen minden nap használunk String, ArrayList, stb. osztályokat, viszont a használhatóságuk nehézsége magas, ugyanis tapasztalt fejlesztőnek kell lenni, az API ismeretével. Ezen pehelysúlyú komponensek újrafelhasználhatósága azért is magas, mert kevesebb a függőségük, nem függnek a környezetüktől. Azonban a SOA szerinti szolgáltatások a durva szemcsézettségűek (coarse grained), használatuk viszonylag egyszerű az általuk biztosított interfész (pl. WSDL) alapján, de nehéz őket újra felhasználni. Így ismét egy ugrás található. Nincs meg az a szint, mely az optimális könnyű használatot, és az újrafelhasználhatóságot is biztosítja.

Ebből egy olyan triviális állítás is kiesik, hogy ahogy növeljük az újrafelhasználhatóságot, úgy lesz nehezebb használni. Másképp megfogalmazva a flexibilitásával nő a komplexitása.

A könyv szerint a keresett szint nem más, mint a modul szint. Ő ezt fizikai tervezésnek nevezi. A könyv a modulok kialakítására vonatkozóan fogalmaz meg tervezési mintákat. De nézzük, hogy hogyan is definiálja a modul fogalmát:

  • Deployable (külön telepíthető)
  • Manageable (külön indítható, leállítható)
  • Natively reusable (metódushívással)
  • Composable (több modulból egy modul hozható létre)
  • Stateless unit (nem példányosítható, egy verzióból egy és csakis egy létezik)
  • Concise interface (tömör interfész a használói számára)

A Java világban ezek nem mások, mint JAR állományok.

A modularizációt két szempontból vizsgálja. Egyrészt futásközben, másrészt fejlesztés közben. Futás közben nyilván kell egy futtató környezet, mely a modulokat kezeli (Runtime model). Fejlesztés közben két kérdéskörrel kell foglalkozni. Egyrészt hogyan történik az interakció a futtató környezettel (Programming model). A modern környezetek már nem látszanak a modulok számára. A másik kérdés, hogy hogyan alakítsuk ki a modulokat (Design paradigm)? Milyen modulokat kell kialakítani, ezek milyen méretűek legyenek, hogyan viszonyuljanak egymáshoz, stb. A könyvben szereplő tervezési minták ezen kérdésekre adnak választ.

És itt jön be egy kicsit az OSGi, hogy mik azok az elvárások, melyeket alapból nem tud a Java teljesíteni. Egyrészt nem lehet korlátozni JAR szinten, hogy mely csomagok legyenek csak elérhetőek más JAR-okból (export package). Nem lehet futásidőben JAR-t cserélni (dynamic deployment). Nem élhet ugyanazon osztály két különböző verziója egymás mellett (versioning). Valamint nincs függőségkezelés (dependency management).

Sajnos a szoftver architektúra nem egyértelműen definiált. Olyanokat lehet mondani, hogy döntések, elvek és útmutatások a rendszer felépítésével kapcsolatban. Definiálja a rendszert statikus vonatkozásban (elemek, komponensek és a köztük lévő kapcsolatok), és dinamikus vonatkozásban is (együttműködések). Szerinte a modularizálás közelebb hozza a fejlesztőket és architecteket. Az architect tipikusan a szolgáltatás, modul és maximum a csomagszintet látja, míg a fejlesztők a modul, csomag, osztály és metódus szintet. Így van egy közös halmaz, mely megértése mindkét fél számára hasznos.

A könyv első részének végén van egy példa is, mely egy monolitikus rendszerrel indít és ezt tördeli modulokra, természetesen a később kifejtett tervezési mintákat használva. A példa szintén nem tartalmaz OSGi-t. A könyvhöz tartozó példakód letölthető a Google Code-ról.

A könyv második része tartalmazza a tervezési mintákat. Mintánként tartalmazza a minta nevét, egy rövid leírást, egy UML diagramot (rettentő hasznos, segítségével azonnal meglehet érteni a mintát), implementációs megközelítéseket, a minta használatának következményeit, példát, és egy rövid összefoglalást.

A mintákat nem sorolnám itt fel, hanem készítettem egy mindmapet a FreeMind szoftverrel. A mindmap forrása megtalálható a GitHubon, és itt kattinthatóan is elérhető, de lejjebb találtok egy nagyítható képet is. Próbáltam a mintákat lefordítani, de nem szó szerint, hanem a célja alapján.

A könyvhöz tartozó weboldal is felsorolja a mintákat, és rövid leírásukat, valamint mintánként egy ábrát. Jó a hozzá készült refcard is, mely letölthető PDF-ben.

A könyv harmadik része szól az OSGi-ról, ami éppen annyira tömör, hogy felkelti a figyelmet az említett technológiára, és tisztázza az alapfogalmakat.

Mint látható, a könyv nagyon tetszett, szerintem hiánypótló írás. Az olvasása közben többször elgondolkodtam, hogy mi az, amit akár a futó projektjeimen használni tudnék, mit kéne másképp csinálni. Persze a legtöbb mintát az ember már ismeri, de mégis ez a könyv foglalja rendszerbe, és elemzi ki több oldalról is. Úgy érzem, hogy olyan könyv, amit érdemes többször levenni a polcról, és néha-néha újra kinyitni. Bár 2012-es, még egyáltalán nem elavult, szemben más technológiai könyvekkel, és egy darabig még nem is lesz. És talán az OSGi-hez is kedvet kapunk.

2014. október 2., csütörtök

HOUG Szakmai nap 2014 diák

A "A Spring Framework 4.0 és 4.1 verzióinak újdonságai" címmel megtartott előadás diái innen letölthetőek. Ha érdekelnek az érdekesebb újdonságok összegyűjtve, lapozd végig őket.

2014. szeptember 28., vasárnap

HOUG Szakmai nap 2014

A HOUG 2014. október 2-án, csütörtökön egy szakmai napot rendez Budapesten a Magyar Telekom Székházban (1013 Budapest, Krisztina körút 55.). Lesz egy egész napos Java szekció is, melyben olyan érdekes témákról hallhattok előadásokat, mint a Java SE 8 és 9, a Java EE 7 újdonságai, hírek a Sonatype Nexusról, stb. Én is előadok 12:00 - 12:30 között, a Spring Framework 4.0 és 4.1 verzióinak újdonságairól.

A szakmai napon a részvétel ingyenes, de előzetes regisztrációhoz kötött!

2014. augusztus 16., szombat

Spring TestExecutionListener

Használt technológiák: Spring Framework 4.0.4, Joda-Time 2.3, Hamcrest
Date 1.0.1

Ebben a posztban három library három apró de érdekes képességét szeretném bemutatni, és hogy hogyan tudnak ezek együttműködni. A poszthoz tartozó mintakód megtalálható a GitHubon.

Nálunk gyakran van szükség arra, hogy a teszt esetek különböző dátumokkal dolgozzanak. Mivel van, hogy a tesztelendő funkció a mai napot veszi alapul, jól jön egy olyan lehetőség, hogy az aktuális időt be tudjuk állítani, és utána már könnyebb az asserteket megfogalmazni. Időgépnek nevezzük, mellyel ide-oda lehet ugrálni az időben.

A Java Date magában nem alkalmas erre, általában egy factory metódust szoktunk létrehozni, mely lekéri az aktuális időt. Ilyenkor figyelni kell arra, hogy csak ezen metódus meghívásával hozzunk létre dátumot, ne használjuk a Date konstruktorát.

Azonban a Joda-Time, mely kibővíti a Java szerény dátumkezelési képességeit, tartalmaz ilyen lehetőséget.

Amennyiben a DateTimeUtils setCurrentMillisOffset metódusát hívjuk, a rendszeridőhöz mindig hozzáad annyi ezredmásodpercet, mint amennyit paraméterként megadtunk. Így nem mindig egy fix időt ad vissza, hanem az időugrás után gyakorlatilag tovább “jár” az óra. Mivel pl. a DateTime létrehozásakor is a DateTimeUtils currentTimeMillis metódusát használja, annak példányosításakor is már a módosított időt kapjuk. Nézzük tehát, hogy hogy lehet az időugrást elvégezni.

private void engage(DateTime targetTime) {
    DateTime realTime = new DateTime(new Date());
    long offset = targetTime.getMillis() - realTime.getMillis();
    DateTimeUtils.setCurrentMillisOffset(offset);
}

Valahol láttam, és megtetszett, hogy JUnit teszt esetre vonatkozó állításokat deklaratív módon, annotációkkal fogalmaztak meg. Kíváncsi voltam, hogy lehet ezt megvalósítani Spring Framework használatakor.

A megoldás, hogy egy TestExecutionListener kell implementálni. Ez deklarál különböző metódusokat, callbackeket, melyek különböző eseményekkor lefutnak, pl. teszt osztály/metódus előtt/után, stb. Létezik egy AbstractTestExecutionListener absztrakt osztály is, mely az interfész minden metódusát üres implementációval valósít meg, és a leszármazott osztályunknak csak a megfelelő metódust kell felülírnia.

Azt szeretném tehát, ha annotációval tudnám megadni, hogy a teszt eset futtatásakor mennyi legyen az idő. Pl. a következő kódrészlettel:

@Test
@TimeMachine(targetDate = "2014-01-01 10:00")
public void travelToPast() {
    // ...
}

Ehhez implementáljuk a megfelelő listenert. A beforeTestMethod metódust írjuk felül, hogy minden teszt metódus futtatása előtt ellenőrizze, hogy a metóduson van-e @TimeMachine annotáció.

public class TimeMachineTestExecutionListener 
    extends AbstractTestExecutionListener {

    @Override
    public void beforeTestMethod(TestContext testContext) 
            throws Exception {
        TimeMachine timeMachine = testContext.getTestMethod()
            .getAnnotation(TimeMachine.class);

        if (timeMachine != null) {
            DateTimeFormatter formatter = 
                DateTimeFormat.forPattern("yyyy-MM-dd hh:mm");
            DateTime targetTime = formatter
                .parseDateTime(timeMachine.targetDate());
            engage(targetTime);
        }
    }
}

Ezen kívül már csak annyit kell tennünk, hogy a teszt osztályunkra rá kell tenni a @TestExecutionListeners annotációt.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestExecutionListeners(TimeMachineTestExecutionListener.class)
public class TimeMachineTest {
    // ...
}

Most már csak annyit szeretnék, hogy letesztelni, hogy működik-e az időgép. Írtam már a Hamcrestről, így Hamcrest matchert kerestem, és meg is találtam a Hamcrest Date projektet, mellyel hatékonyan tudunk dátumokat összehasonlítani.

Nézzük meg, hogy hogyan is néz ki a teszt metódus, azon belül is koncentráljunk az assertre.

@Test
@TimeMachine(targetDate = "2014-01-01 10:00")
public void travelToPast() {
    // When
    DateTime now = new DateTime();

    // Then
    DateTime expected = new DateTime(2014, 1, 1, 10, 0);
    assertThat(now.toDate(), 
        within(5, TimeUnit.SECONDS, expected.toDate()));
}

A DateMatchers within metódusát használva ellenőrizhetjük, hogy két dátum között mennyi a differencia, itt most max. 5 másodpercet adtunk meg, feltételezve, hogy ennyi idő alatt biztos lefut a teszteset.