pátek 7. ledna 2011

Od Netbeans 6.9 k IntelliJ IDEA 10

Když jsem poprvé začal používat plnohodnotné IDE, nejvíce jsem si zamiloval NetBeans. Důvodem bylo zejména to, že pro začátečníka byl tento nástroj asi nejsnáze pochopitelný. Postupem času si člověk vytvoří určité návyky a jen težko je schopen přejít na jiné prostředí.

NetBeans jsem používal posledních 5 let. Což už je dost dlouhá doba na to, abych věděl co od tohoto nástroje můžu očekávat. Nicméně v poslední době se mi zdá, že více než na práci se vývoj tohoto nástroje soustředí na to, jak vytvořit demo aplikaci. Ta je poté slavnostně prezentována ve formě videotutoriálu na stránkách netbeans.org. Ovšem při práci na větším projektu se často dostávám do potíží se samotnou stabilitou tohoto prostředí. Proto jsem se rozhodl vyzkoušet IntelliJ IDEu, kterou všichni její  uživatelé tak slavně opěvují.

Při prvním spuštění je jasné, že i když oba nástroje použiji na tu stejnou věc (programování Java, PHP), tak přesto jsou dost rozdílné, abych hned věděl kde začít.

Projekty a moduly

První velký zádrhel je mezi porovnání projektů a modulů. v NetBeans vytvořím nový projekt a rovnou můžu pracovat. Onen projekt můžu například zabalit do EAR projektu a přidávat další a další. IDEA na to jde jinak. Projektem je zde spíše něco jako skupina, do které vlkádám dané projekty (ehm, tedy moduly). Modulem je tedy onen projekt a projekt je spíše celé okno IntelliJ IDEy. Trošku zmatek, nicméně se mi podařilo tímto prokousat a pochopit logiku tohoto nástroje. :)

PHP Projekt (nebo modul?)

Projekty a moduly pro Javu jsem vcelku pochopil. Horší je to ovšem s PHP. IntelliJ IDEA má slušnou podporu PHP a proto jsem chtěl vyzkoušet i tu. Problém ovšem je, že neexistuje nabídka jak vytvořit čistě PHP modul. Jediný způsob je vytvořit "projekt ze zdroje" a poté do něj java modul bez vytvoření src adresáře. Tento způsob je přímo popisovaný i v nápovědě tohoto nástroje. Asi nemá příliš cenu komentovat, proč tento způsob vývojáři trošku neupraví. Nicméně, chceš-li pracovat s PHP, vytvoř Java Modul :)

Přenos projektu z NetBeans do IntelliJ IDEy

Po menším prozkoumání tohoto nástroje jsem hledal způsob, jak rozumně převést projekt z NetBeans do IDEy. Jelikož jsem v NetBeans projekt sestavoval pomocí Antu (ano, vím, že už to není moderní :)) nenašel jsem jednoduchý způsob, jak projekt převést. Nezbývalo tedy nic jiného, než použít Maven. Po dvoudenním trápení se mi podařilo sestavovat celý projekt pomocí Mavenu. Kromě toho, že jsem toto měl provést již dávno, tak přenos projektu byl více než snadný. Nyní stačilo otevřít IntelliJ IDEu a pouze projekt "otevřít". Vše začalo fungovat bez problémů.

Nevýhody IDEy

Nemá smysl psát o výhodách tohoto nástroje. Je totiž vážně slušně propracován a navíc splňuje téměř vše, co ke své práci potřebuji. Ovšem i přesto existují určité věci, které stále nejsem schopen překousnout a nutí mě přemýšlet, zda mám tento nástroj skutečně koupit a začít používat.

Logování Glassfish

Při deploy (debugování) aplikace na Glassfish je problém s tím, že nefunguje zobrazování logování v okně. Toto bylo u NetBeans skutečně na mnohem lepší úrovni. Nakonec jsem zjistil, že i když je v nastavení tohoto aplikačního serveru nastavena log console, musím přidat vlastní. Poté základní logování funguje. Ovšem pouze do doby, než se provede "rotate" log, tedy provede se záloha log souboru a vytvoří se nový glassfish log soubor. IDEA ovšem není schopná pokračovat ve výpisu tohoto logu z čistého souboru.

Podpora Mavenu

NetBeans má podporu Mavenu na lepší úrovni. U knihoven je přímo vidět zda se jedná o závislost na jiné, v jaké je "scope", atd. Toto jsem u IDEy opět nenašel v rozumné formě.

Závěrem

Je zde spousta dalších drobností, které potřebuji vyřešit, ale ty považuji spíše za "porodní bolesti" (jako například rozumné formátování kódu, jelikož přes Ctrl+Alt+L se mi formátování provede jen "někdy"). Nicméně dost reálně uvažuji o koupi tohoto IDE. Přeci jen, cena za nástroj, který používám více jak 8 hodin denně je zanedbatelná vůči produktivitě, kterou mi může přinést.

středa 14. října 2009

Apache Wicket - verze 1.4

Apache Wicket zdárně dospěl do verze 1.4, která sebou přináší změny zejména na úrovni podpory generických typů. Tato verze je tedy určena pro javu 1.5 či vyšší.

Po zdravé úvaze jsem se rozhodl přejít na tuto verzi a provést úpravy na stávajícím projektu, který byl psán pro verzi 1.3.x.

Hlavní rozdíly oproti starší verzi

Jak jsem již zmínil, hlavní změnou je podpora generických typů. Bohužel došlo i na změnu v API. Metoda "getModel()" či "getModelObject()" byla nahrazena "getDefaultModel...". Směle jsem se tedy pustil do přeměny pomocí hromadného přepisu (cca 50 výskytů). Naštěstí byla tato změna dostatečná a aplikace je plně kompatibilní s verzí 1.4.

Využitelnost generik

Na jedné straně jsem jásal, že je konečne wicket více typově kontrolovatelný a nemusí docházet k ruzným přetypováním. Na druhou stranu je ovšem dobré poznamenat, že jsou pasáže (viz např. DropDownChoice), které jsou dost neštastně navrženy pro využití generických typů. Problém spočívá zejména v tom, že musím napsat tunu kódu navíc, která nepřináší až tak závratné změny.

Po zhruba měsíční migraci jsem omezil použití generických typů jen na místa, kde to skutečně má smysl (viz např. IModel).

Komponenty třetích stran

To, že je ve Wicketu tvorba znovupoužitelných komponent, hračka, je nepopíratelný fakt. Komponenty třetích stran se tedy spíše soustředí na složitejší věci. Bohužel, v současné době jsem nabyl dojmu, že je vývoj dost chaoticky či vůbec neřízen. Použít některou přídavnou vlastnost z WicketStuff je sázka do loterie. Pokud bych toto porovnal s JSF, je na tom Wicket naprosto žalostně.

Osobně využívám následující přídavné vlastnosti:

  • wicket contrib javaee 1.1 - podpora pro injectování EJB komponent

  • swarm 1.4, wasp 1.4 - pro podporu security management

  • grid - jedná se o "rich" tabulky; kdysi byl projekt vystaven na inmethod.com, poté byl zrušen; pohužel jsem musel udělat vlastní úpravy, aby daná komponenta byla vůbec funkční


Zbylé "projekty" jsem po zběžném otestování raději zahodil. Mrzí mě, že například podpora pro jQuery je dost nestabilní a její použití je dost invazivní (viz. nutnost použít pro Application daného předka, což znemožňuje využít zase například Swarm).

Pokud má někdo zkušenosti z dalšími přídavnými vlastnostmi pro Wicket, nechť se o ně podělí v diskuzi.

I přes zmíněné zápory, které jsem zde popsal, je pro mne Wicket tou nejlepší volbou pro tvorbu web aplikací. Je prostě radost s ním pracovat! :)

úterý 6. ledna 2009

Apache Wicket - Hot Deploy html souborů

Při vývoji javovských webových aplikací nad aplikačním serverem (Glassfish) či jen nad samotným webovým kontejnerem (Tomcat), dochází k jedné nepříjmené situaci a tím je nahrání aplikace na server. Pokud se jedná o malý projekt, je čas strávený nad undeploy/deploy mizivý. Jak ale projekt začne růst, roste s ním i čas, který strávite při nahrávání nové verze na server.

Existuje několik možností, jak se vyhnout co nejčastějšímu nahrávání. Jednou z možností je důsledné psaní JUnit testů, které by mě měly upozorňovat na vzniklé problémy již při vývoji. Další možností je spuštění aplikačního serveru v debug módu. Ten částečně umožňuje provést tzv. hot deploy, kde se na server aktualizuje pouze část, kterou jsem právě změnil. Záměrně používám slovo částečně, protože i tento způsob je dost omezen (tvorba nových tříd, nových metod, EJBs, atd).

Projekt postavený nad Apache Wicket je možné spouštět také v debug řežimu. Tento mód umožňuje využít komplexnější analýzu (logování, ajax výstupy, atd) při vývoji. Pokud je tedy tento projekt spuštěn v debug řežimu a celý aplikační server také v debug módu, je možné za běhu měnit implementaci metod. Problém ovšem nastane s html soubory u wicket komponent. Ty se jen těžko budu snažit dostat do hot deploy řežimu.

Po menším pátrání jsem ovšem objevil možnost jak provést "autodeploy" těchto html souborů. Celý trik spočívá v tom, že si definuji vlastní tzv. "resource folder", který nastavím do místa, kde se vyskytuje můj projekt. Tato funkcionalita se zapisuje do init metody uvnitř vlastní Application Class, která je definována v web.xml jako "applicationClassName".
@Override
protected void init() {
super.init();
// 1
if (Application.DEVELOPMENT.equalsIgnoreCase(getConfigurationType())) {
// 2
getResourceSettings().setResourcePollFrequency(Duration.ONE_SECOND);
// 3
getResourceSettings().addResourceFolder("/home/ales/projekt/src/java");
}
}

1. funkcionalita se spustí jen v případě, že je celý projekt spuštěn v debug modu.
2. pokud ve svém projektu měním html soubor, je tato změna promítnuta v běžícím projektu ihned (1 vteřina)
3. nastavím celou cestu k mému projektu a k jeho balíčkům

Tento "resource folder" umožňuje změnu jak html souborů, tak i dalších vlastností jako je např. lokalizace v properties souborech, css, atd. Tedy vše kromě javovských tříd.

Co se týče samotného hot deploy, doufám, že se situace o dost zlepší s příchodem Glassfish V3, který by měl obsahovat OSGI kontejner.

*Malé rýpnutí:*
Nedávno jsem poslouchal poslední podcast 29 z java.cz, kde Roman Štrobl mluvil o nové funkcionalitě "Compile on Save" v NetBeans. Přiznám se, že se mi zatím nepodařilo tuto funkcionalitu využít při vývoji J2EE aplikace. Mám pocit, že je hot deploy na glassfishi omezen tak, že je to téměř nepoužitelné. Pokud se nemýlím, tak samotná EJB3 komponenta moc dobře takto "aktualizovat" nejde.

pondělí 29. prosince 2008

Apache Wicket - Znovupoužitelné komponenty

Tvorba vlastních komponent je u komponentově orientovaného web frameworku, důležitá vlastnost. Jen težko bych hledal projekt, který by si vystačil s existujícími vlastnostmi a komponenty daného rámce a nesnažil se o vlastní tvorbu.

Pokud bych Wicket srovnával s JSF na této úrovni, musel bych více podrobněji znát tvorbu komponent v JSF. Ať jsem se snažil sebevíc, nikdy jsem úplně neodhalil výhody vlastních komponent v JSF. Ten postup mi přišel natolik složitý a nesmyslný, že v tomto případě jsem vždy sáhnul po něčem existujícím (RichFaces, Tomahawk, atd.). V JSF mám v tomto ohledu jen teoretickou znalost, která mi ovšem stačí k tomu, abych se do nečeho takového, jako je tvorba vlastních komponent, vůbec nepouštěl.

Ve Wicketu je situace naprosto rozdílná. Samotný framework mě v podstatě nutí rozsekávat danou prezentaci do několika menších celků, které se později dají znovu použít. Navíc je situace o to snažší, že není potřeba se učit či používat nové věci. Bohatě stačí znalost základních komponent a jejich využití. Vše ostatní vyplyne samo.

Pro tvorbu nové komponenty je nejčastěji používán "org.apache.wicket.markup.html.panel.Panel", od kterého má vlastní komponenta dědí. Díky tomu získám základní vlastnosti, které bych musel jinak znovu tvořit. Podobnost lze najít u Swingu, kde vlastní komponenty nejčastěji dědí od JPanelu.

Na malém příkladu ukážu, jak vytvořit komponenu, která bude obsahovat základní informace o zaměstnanci. Tuto komponentu poté budu moci využít např. při kliknutí na detail zaměstnance, při výpisu zaměstnanců, apod. Všude, kde budu chtít znát základní informace o daném zaměstnanci.

Nejprve doménový model:
public class Zamestnanec { 
private String idCislo;
private String prijmeni;
private String jmeno;
// set, get
}

Nyní vytvořím wicket komponentu:
<wicket:panel>
<span wicket:id="prijmeni"></span> <span wicket:id="jmeno"></span> (<span wicket:id="idCislo"></span>)
</wicket:panel>

A k danému HTML i Java kod:
public class ZamestnanecPanel extends Panel {
  public ZamestnanecPanel(String id, Zamestnanec z) {
  super(id);
  add(new Label("prijmeni", z.getPrijmeni());
  add(new Label("jmeno", z.getJmeno());
add(new Label("idCislo", z.getIdCislo());
  }
}

Tím mám vlastní komponentu hotovou.

Nyní ji stačí využít. Například při zobrazení detailu zaměstnance:
... hlavicka html stranky ....
<div class="detail">
<span wicket:id="zakladni"></span>
.... další vlasnosti
</div>
... paticka html stranky.....

K danému HTML i Java kod:
public class DetailPage extends WebPage {
  public DetailPage(String idCislo) {
  super();
  add(new ZamestnanecPanel("zakladni", service.findById(idCislo)));
  // dalsi vlastnosti
  }
}

I když je daný příklad triviální, jasně znázorňuje to, že tvorba vlastních komponent je v Apache Wicket velice jednoduchá a hlavně dobře použitelná. Způsob jak navrhovat takové komponenty je stejný jako v případě tvorby objektově orientovaného kódu. Třídy jsou malé a obsahují jen jednu jasně specifikovanou funkcionalitu. Stejné je to i zde.
*Myslím, že tohle je ta nejzásadnější věc, která dělá z Apache Wicketu dobrý framework, ve kterém je radost něco psát. Vytvořit komponenty a pak je skládat jako lego :)*

úterý 23. prosince 2008

JPA 2.0

Nedávno zveřejněná specifikace JPA 2.0 obsahuje asi nejzásadnější posun v možnosti psaní Criteria API. Pokud někdo očekává okopírované Criteria API z Hibernate bude možná trošku zklamán (či potěšen).

Nový způsob je totiž více postaven na "objektovosti" daných entit. Dobrý zdroj a ukázku lze najít na blogu Gavina Kinga.

Osobně toto považuji za správný krok. Samotné JPA (EntityManager) umí pouze JPQL dotazy, které jsou napsané jako jeden String řetězec. To sebou přináší hromadu nevýhod a v mnoha případech nutí, aby si vývojář napsal nějaký ten vlastní "JPQL String Parser". Z tohoto důvodu jsem osobně JPA degradoval na "pouhé" ORM mapovaní, kde mi jasně specifikovaný standard umožňuje být více nezavislý na použitém "provideru pro persistenci". EntityManager jsem vyměnil za "Hibernate Session" a vesele si psal svá Criteria API.

Hibernate Criteria API ovšem nejsou všespásná. V některých případech je tento způsob nepoužitelný. Občas člověk narazí na nějaký ten bug či extrémní složitost psaní dotazu. Jakmile vznikne požadavek na "subquery", je Hibernate Criteria API velká loterie. Samotná podpora poddotazů je totiž žalostná. Podle toho, co jsem zatím viděl, si myslím, že způsob zápisu v JPA 2.0 bude v tomto více přizpůsobivější a umožní plně nahradit jakýkoli JPQL dotaz.

Další věcí je **návratová hodnota dotazu**. Asi nikdo nepředpokládá, že lze pomocí namapovaných entit vše vyřešit. V takových chvílích nastupují DTO objekty, které se časem začnou množit. Způsob, jak výsledek převádět do vlastních objektů, je v JPA 1.0 dost špatně navržen. Psát "new cela.pakaz.az.k.ZakaznikDTO(a, zde, hromada, parametru)" je otřesné. Když k tomu ještě připočítám nutnost tvorby konstruktorů, tak jak jsou tvořeny v JPQL, dostanete se do situace, kdy Vám Java jako staticky typovaný jazyk přestane pomáhat. Budete se muset spoléhat na správnost daných JPQL dotazů i v případech refactoringu (samozřejmě testy mohou pomoci :)).

Proto i zde jsem zvolil Hibernate Criteria API, jelikož způsob návratové hodnoty lze mnohem lépe zapsat pomocí "Hibernate Projections".

Bohužel i tato volba není úplně ideální a opět obsahuje "mouchy". První z nich je asi to, že nelze vytvořit DTO objekt, který bude obsahovat referenci na jiný objekt než ten, který zná Hibernate nad JDBC (String, Integer, atd.). Zde se jaksi ztrácí ono magické OOP a nastupuje hromada primitivních DTO objektů, které mezi sebou nelze propojit jako v případě mapovaných entit. Jediné propojení lze samotřejmě provést pouze na úrovni vlastního Java kódu.

I když jsem novou specifikaci nečetl řádek po řádku, nenalezl jsem v této oblasti žádný posun. Je pravdou, že i "select statement" byl z části vylepšen, ale nikoli tak, aby umožňoval tvorbu vzájemně propojených DTO objektů.

Ale i přesto musím říct, že nové Criteria Query API se mi v JPA dost zamlouvají. Snad bude tento nový způsob zápisu alespoň schopen nahradit Hibernate Criteria API.

*Specifikace pro JPA je dosti rozsáhlá a myslím, že jako čtivo na dlouhé zimní večery bude jistě dobrou volbou :)*

pondělí 13. října 2008

Apache Wicket - IBehavior, Tabulky

Minule jsem psal o možnosti spojení Wicketu s EJB3 a o Wicket Security. Dnes se podívám na další vlastnosti a možnosti tohoto webového frameworku.

IBehavior

Jedná se o interface, který je označován jako druh pluginu wicket komponent. Já jsem dané řešení využil například pro statistiku návštěvnosti či pro zjistění, jak dlouho trvalo vyrendrování wicket stránky.

Příklad, pro zjištění doby trvání vyrendrování wicket stránky:
public class TimeBehavior extends AbstractBehavior {
private long start;

@Override
public void beforeRender(Component component) {
start = System.currentTimeMillis();
}

@Override
public void onRendered(Component component) {
super.onRendered(component);
long dobaBehu = System.currentTimeMillis() - start;
// dalsi zpracovani
}
}


Třída je potomkem AbstractBehavior, což je adaptér pro interface IBehavior. Tuto implementaci stačí poté přiřadit v "BasePage" (základní Wicket Page, která je předkem všech Page). Samozřejmě, pro Wicket je Page komponenta stejně jako např. TextField. Proto je možné daný plugin přiřazovat i daným komponentám uvnitř Page, Panel, atd.

Možností, jak využít toto rozšíření pro komponenty je mnoho. Pomocí této vlastnosti se například dá z klasického input fieldu vytvořit zadávací políčko s kalendářem pro datum, atd. Stačí implementovat metodu "onComponentTag" a tu patřičně upravit. Tato funkcionalita s kalendářem je již přímo implementována (viz. wicket-datetime: DatePicker).

Tabulky

Každý webový intranetový systém se z velké části točí okolo poskytování dat v jasně specifikované formě. Nebo chcete-li: "hromada tabulek s vlastní filtrací". K tomuto účelu poskytuje Wicket přímo vlastní komponenty, viz: repeater example.

Do nedávné doby existoval web: inmethod.com, který danou funkcionalitu rozšiřoval o vlastní druh tabulek. Tato implementace byla zatím asi to nejlepší, co jsem v oblasti webu a webových frameworků viděl.

Tabulky mají statické sloupce a posuvný obsah (ala excel), možnost řazení sloupců, přesun sloupců, změnu velikosti sloupců, atd.

Příliš nechápu proč, byl tento projekt ukončen (zřejmě jako ostatní: nedostatek volného času). Naštěstí je ale možné si přes svn stáhnout zdrojové kódy, které lze použít. Je k dispozicii živá ukázka.

Daný projekt je psán vůči verzi 1.2. Pro verzi 1.3.x není k dispozici alternativa. Osobně danou knihovnu pro verzi 1.3.3 využívám, ovšem s tím, že jsem dané zdrojové kódy musel částečně upravit. Pokud by měl někdo zájem, mohu mu upravenou knihovnu zaslat.

Danou implementaci lze samozřejmě dále rozšiřovat. Stačí se například podívat jak je definována třída: "com.inmethod.grid.column.PropertyColumn".

Příště ukáži, jak lze snadno tvořit znovupoužitelné komponenty v Apache Wicket.

pátek 19. září 2008

Trocha dávky Apache Wicket

Od posledního příspěvku na tomto blogu již uplynula nějaká ta doba. Nebudu tvrdit, že jsem neměl čas. Důvodem byla spíše chuť něco nového napsat. To je ovšem pryč, takže se vrátím zpět ke svému psaní :)

Apache Wicket je zajímavý hned z několika důvodů. Některé z nich jsem prezentoval minule a proto dnes přidám snad jediný důvod: baví mě v něm psát aplikace.

Každý, kdo má alespoň obecnou znalost tohoto frameworku, musí si daný způsob ihned spojit s psaním aplikací ve swingu. Asi bych to vyjádřil slovy: piš to jako ve swingu a přidej k dané třídě html soubor.

Wicket a EJB3

Dají se tyto dvě technologie jednoduše spojit? Repektive dá se snadno zařídit závislost wicket komponenty na EJB servisní beaně? Ano dá. Stačí stáhnout wicket-contrib-javaee.

Pro schopnost provést jednoduché DI (dependency injection) přes anotaci @EJB je třeba definovat referenci ve web.xml.
<ejb-local-ref>
  <ejb-ref-name>cz.irminsul.javaee.ejb3.ServiceLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>cz.irminsul.javaee.ejb3.ServiceLocal</local>
</ejb-local-ref>

Při definici ejb-ref-name používám celý název daného rozhraní. Důvod je ten, že poté nění třeba při definici DI uvádět @EJB(name="reference"). Výsledné DI vypadá následovně:
public class MyPage extends Page {
 @EJB
 private ServiceLocal service;
 ....
}




Wicket a Security

Existuje několik možností, jak definovat security. Já osobně jsem zvolil WASP. Toto řešení je postaveno na rolích (i když spíše záleží na způsobu implementace). Je zde několik důležitých kroků k uspěšnému nasazení.

1. Definovat vlastní .hive soubor

2. Base page musí být potomkem SecureWebPage

3. Wicket Session musí být potomkem WaspSession

4. Application class musí být částečně upravena (viz příklady na daném WASP webu)

5. Musí se definovat vlastní LoginContext a Principal

Nebudu zde rozepisovat jednotlivé kroky. Dané příklady lze najít na odkazovaném webu pro WASP. Uvedu jen to zajímavé:

Definice oprávnění lze použít jak na celou page, tak na danou akci, tak na daný model. Z toho lze usoudit, že daný způsob by měl být dostačující k danému použití v jakémkoli scénáři. Celá tato definice je uvedena v .hive souboru, který je poté nastaven v Application class. Samozřejmě daných .hive souborů může existovat klidně více.

U definice oprávnění v .hive souboru lze nastavit, zda se bude daná definice týkat i potomků daných page tříd. Zda je k nějaké page přístup globální, či pro danou roli, atd.

Daný způsob implementace se mi vcelku zamlouvá. Jediné, co bych danému řešení vytkl je to, že dokumentace je téměř nulová. Jediný zdroj informací jsou proto jen příklady, které si lze stáhnout a poté prozkoumat jejich kód.

Tak to by bylo asi vše. Příště ukáži jak lze využít IBehavior či jak je na tom Wicket s nenáviděnými html tabulkami.

Když programátor založí a řídí firmu

Jako malý jsem chtěl být popelářem. Ani ne tak proto, že bych měl nějaký zvláštní vztah k odpadkům, ale hrozně se mi líbilo, jak...