čtvrtek 27. prosince 2007

Anotace nahrazující SQL a OQL dotazy (důvody)

V minulém příspěvku jsem psal o tom, jakým způsobem nadefinovat základní DAO vrstvu. Zvolil jsem způsob, který se stal zavislý na Hibernate Session. Tento "vendor" nabízí i jednu z věcí, kterou jsem si pomalu oblíbil, a tím jsou Criteria API.

Psaní základních SQL dotazů jsem nahrazil OQL dotazy. OQL je v podstatě velice podobný SQL s tím rozdílem, že daný dotaz se provádí nad entitami reprezentující data v DB. Díky tomu odpadá nutnost psát ruzné JOIN konstrukce, specifikovat vrácené sloupce a hlavně získávám nezávislost na použitém databázovém systému. Převod z MySQL na Oracle či MSSQL je triviální záležitost spočívající v přepsání pár řádku v persistence.xml či v přepsání JDBC zdroje v aplikačním serveru.

Ale zpět. I když je OQL velice elegantní způsob psaní, stále obsahuje velké omezení, které spočívá v tvorbě dynamických dotazů. Pokud aplikace přistupuje k datům tak, že je získává na základě uživatelského filtru, musím dotaz poskládat z daného Stringu, což je dost otravující záležitost.
K tomuto účelu se velice hodí Criteria API. Nebudu zde popisovat funkci Criteria API, k tomuto účelu slouží referenční příručka. U Criteria API se mi velice zalíbila možnost filtrovat data přes danou entitu. K tomuto účelu zde existuje objekt "Example". Při použití tohoto přístupu mohu velice snadno získat data filtrovaná podle daných sloupců (atributů) v tabulce (entitě).

Jenže....

Pokud si například řeknu: "Chci vybrat všechny záznamy s podmínkou WHERE datum BETWEEN od AND do", dostanu se opět do slepé uličky a musím přistoupit zpět k čistému Criteria API nebo dokonce k OQL.

Toto byl první důvod, proč jsem přistoupil k implementaci vlastního způsobu, který je řízen pomocí anotací. Ještě než přejdu k samotnému způsobu, musím zmínit druhou pozitivní věc.

Pokud začnu tvořit DAO vrstvu, začne se mi každý DAO objekt hemžit metodami jako: findByDatumPrijeti, findByXXX.... Jistě není nic špatného na implementaci daných metod, až na to, že metody obsahují parametry, které již jasně říkají, jaká data mají být výsledkem (návratovou hodnotou).
Uvedu malý příklad (pro pozdější srovnání):

public List findForExample(String zakaznik, Date datumOd, Date datumDo) {

// implementace Criteria API, OQL ci suroveho SQL

}


Jak je z ukázky patrné, metoda vybíra zakázky, které spadají jistému zákazníkovi a jejich datum je v rozmezi datumOd-datumDo.

K odstranění psaní samotných dotazů použiji následující kroky:

  • vytvořím objekt pro filtraci

  • daný objekt anotuji příslušnými "metadaty"

  • zruším metodu findForExample a v DAO vytvořím obecnou metodu: findByCriteria(Object filtr)



Jediné, co mi zůstane je objekt pro filtrování. Sám se svými metadaty je schopen řici, co vlastně chci. Následující ukázka je ekvivalentní předchozímu způsobu:

@Criteria(entity = Zakazky.class)
public class ZakazkyForExampleFiltr {

@Criterion(property="zakaznik.id")
private String zakaznik;

@Criterion(property = "datumPrijeti")
@Between(idf = "dp", property = BetweenDAO.MIN)
private Date datumPrijetiOd;


@Criterion(property = "datumPrijeti")
@Between(idf = "dp", property = BetweenDAO.MAX)
private Date datumPrijetiDo;

// settry, gettry
}

// pouziti
ZakazkyForExampleFiltr filtr = new ZakazkyForExampleFiltr();
// naplneni filtru
List result = dao.findByCriteria(filtr);


Pro lidi nesnášející anotace, bude tento způsob jistě nepoužitelný, pro lidi snažící se o co největší usnadnění a zpřehlednění své práce, naopak přínosem. Věřím, že každý si již ten svůj zpusob nalezl a nehodlá ho měnit, na druhou stranu při pohledu na takovýto kod si pokládám jednu otázku: "Není přece jen efektivnější popsat kod metadaty a nechat zbytek na daném frameworku?".

Jelikož se mi článek rozrostl, rozhodl jsem se ho rozdělit do dvou částí. V první části jsem popsal důvody a uvedl malou ukázku. V druhé části uvedu možnosti a nabídnu danou funkčnost ke stažení. Tedy ten základní "motor", který lze jednoduše "přilepit" do své DAO vrstvy. Navíc uvedu další plány a položím otázky, na které si zatím nedokážu odpovědět.

čtvrtek 13. prosince 2007

DAO pattern + generika pro EJB3

Když jsem se dostal do fáze většího poznávání J2EE, došlo mi, že vrstvení logiky je nedílnou součástí úspěchu při návrhu.
Jistě by nebylo moudré nechat "dolování dat" rozházené po aplikační logice tak, jak ho zrovna potřebuji. Zde nastupuje DAO (Data Access Object), což je návrhový vzor sloužící ke komunikaci mezi persistentní vrstvou a zbytkem světa.

Asi nejvíce mě zaujala možnost, kde DAO vrstvu definuji pomocí generiky a abstraktní třídy. Více než tisíc slov je lepší přímá ukázka kódu.

První věcí je interface, který obsahuje všechny důležité metody, které je třeba pro DAO jednotlivých entit třeba vystavit:
public interface GenericDAO {
public T find(ID id);
public List findAll();
public T create(T entity);
public T save(T entity);
public void remove(T entity);
}

Jednotlivé metody jsou vcelku jasné. Jedná se o základní operace jako: získej data, vytvoř, ulož, smaž. Co se týče generických typů, jedná se o entitu, které přísluší dané DAO a o typ primárního klíče. Typem primárního klíče může být jak základní datový typ jako String, Integer, tak i složený primární klíč, např: ZakazkaPK (obsahuje číslo zakázky a datum vystavení).

Nyní mohu přejít k vlastní implementaci lokálního interface:
@Local
public interface ZamestnanecDAOLocal extends GenericDAO {
}

Samotná EJB beana může vypadat následovně:
@Stateless
public class ZamestnanecDAOBean implements ZamestnanecDAOLocal {
@PersistenceContext(unitName = "myDB")
private EntityManager em;
//... implementace metod
}


Velkou nevýhodou je ovšem fakt, že pokaždé musím implementovat metody, které jsou potřeba ke splnění požadavku z GenericDAO.

Zde nastupuje abstraktní třída, která za nás vyřeší onu potřebnou implementaci.
public abstract class AbstractDAO implements GenericDAO {
private Class entityBeanType;
private EntityManager em;
public AbstractDAO() {
// vytvari, ziskava typ entity pro dane DAO
this.entityBeanType = (Class) ((ParameterizedType)
getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}

public Class getEntityBeanType() {
return entityBeanType;
}

@PersistenceContext(unitName = "default")
public void setEntityManager(EntityManager em) {
this.em = em;
}

protected EntityManager getEntityManager() {
if (em == null) {
throw new IllegalStateException("...");
}
return em;
}

public T find(ID id) {
T entity;
entity = getEntityManager().find(getEntityBeanType(), id);
return entity;
}

// ... implementace zbylych metod
}


Nyní stačí danou abstraktní třídu nechat dědit samotnou implementací EJB beany:
@Stateless
public class ZamestnanecDAOBean extends AbstractDAO implements ZamestnanecDAOLocal {
}


Takto definovaná beana je schopna podědit abstraktní třídu a například anotovaný setter pro entitymanager převzít na svá bedra. Podle specifikace je totiž možné EJB beany nechat dědit mezi sebou, s vyjímkou, že dependency injections a další služby jsou poté managovány potomkem, v našem případě "ZamestnanecDAOBean".

Aby samotné DAO nebylo tak chudé, přidal jsem si několik dalších možností. Některé jsou již specifikovány na danou implementace ORM frameworku. Osobně jsem díky tomu přešel na Hibernate Session a Criteria API.
Tady jsou některé další metody:

/**
*

Vraci vsechny zaznamy z dane tabulky, ktera prislusi entite.
* Navic umoznuje definovat razeni podle Hibernate Criteria API: Order


*

Zpusob pouziti: {@code findAll(Order.asc("jmeno"), Order.desc("prijmeni"))}


*
* @param orderBy definice razeni zaznamu
* @return vsechny zaznamy, pokud zadne neexistuji, vraci null
*/
public List findAll(Order... orderBy);

/**
*

Vraci vsechny zaznamy z dane tabulky, ktera prislusi entite.
* Navic umoznuje definovat omezeny vyber dat, pouzivane napr. pro strankovani.


*

Zpusob pouziti: {@code findAll(0, 20); } Prvni radek je roven 0


*
* @param first prvni radek, od ktereho se vybiraji zaznamy
* @param offset maximalni pocet vybiranych zaznamu
* @return vsechny zaznamy dle definovanych omezenich
*/
public List findAll(int first, int offset);

/**
*

Vraci vsechny zaznamy z dane tabulky, ktera prislusi entite.
* Navic umoznuje definovat omezeny vyber dat, pouzivane napr. pro strankovani
* a definovat razeni podle Hibernate Criteria API: Order


*

Zpusob pouziti: {@code findAll(0, 20, Order.asc("jmeno")); } Prvni radek je roven 0


*
* @param first prvni radek, od ktereho se vybiraji zaznamy
* @param offset maximalni pocet vybiranych zaznamu
* @param orderBy definice razeni zaznamu
*
* @return vsechny zaznamy dle definovanych omezenich
*/
public List findAll(int first, int offset, Order... orderBy);

/**
*

Dohledava zaznamy na zaklade Hibernate Example.


*

Spousti: {@code findByExample(exampleInstance, false, false, false, excludeProperty)}


*

Zpusob pouziti: 15.6. Example queries
*
* @param exampleInstance s naplnenymi vlastnostmi pro vyber
* @param excludeProperty pradavajici vlastnosti pro vyber pres example
* @return dohledane zaznamy
*/
public List findByExample(T exampleInstance, String... excludeProperty);

/**
*

Ziskava pocet vsech radku z tabulky prislusici dane entite


*
* @return pocet vsech radku
*/
public int countAll();

pondělí 3. prosince 2007

Seam & Hibernate Validator

Když jsem přemýšlel nad tím jak validovat (kontrolovat) data od uzivatele, napadlo mě spoustu možností jak to řešit. Jeden je ovšem velice sexy, který stojí za to zmínit.

Mám klasickou webovou aplikaci postavenou pomocí MVC (model-view-controller). Do modelu můžu nacpat entity, do kontroleru jednotlivé akce nad modelem a komunikace mezi view a business logikou. Do view klasické webové stránky.
Jelikož je Java striktně typový jazyk, nutí mě již na základě modelu definovat typ tak, aby odpovídal skutečnosti. Při vystavení modelu do persistentní vrstvy, ode mně navíc očekává popis jednotlivých atributů, podle kterého komunikuje s databází.

Ale zpět k view.
Začnu tvořit klasický formulář, který například obsahuje vlastnosti uživatele. Musím ošetřit, že login nesmí být prázdný, že musí splňovat podmínku, která říká, že použitelné znaky jsou pouze daného výčtu. Podobné vlastnosti budu kontrolovat například u hesla či jména a příjmení. Dané kritéria, které musí uživatel, při vyplňování formuláře, splnit, jsou identická s kritériemi, které musí splnit model (entita), aby byla schopna se persistovat (uložit) do databáze.
Abych se vyhnul duplicitní validaci, existuje možnost tyto věci propojit. Zde právě nastupuje Seam framework a Hibernate Validator. Nejlépe bude, pokud vše vysvětlím na malé ukázce:

Mám entitu uživatele, která může vypadat následovně:
@Entity
@Name("uzivatel")
public class Uzivatel implements Serializable {
@Id
@NotNull
@Length(min=5, max=30)
@Pattern("^\w*$", message="#{message.errorValidateLogin}")
private String login;
@NotNull
@Length(min=6)
private String heslo;
private String jmeno;
private String prijmeni;
// ... settry, gettry
}


Danými anotacemi jsem dal najevo, že model musí splnit tyto požadavky. Pokud se tak nestane, nepodaří se mi mi danou hodnotu uložit do databáze.

Tak a teď k view.
Mám v podstatě 2 možnosti, buď budu znovu psát pravidla pro validaci, nebo nechám vše na frameworku.







Při pokusu odeslání formuláře, dostanu hlášení, že jsem nesplnil daná kritéria. K tomu ale dojde ještě dříve, než se model dostane k persistentní vrstvě. To znamená, že validace se provádí hned při spuštění akce "registrace".
Jednotlivé hlášky, které posílá Hibernate Validator jsou přeložitelné, takže není problém si udělat vlastní definici, která mi jasně řekne: "Nene, máš chybu, chyby jsou... zde a zde...".

Je to jedna z vlastností Seamu, která mě pomalu nutí více používat Hibernate :)

Příjemných vlastností v Seam frameworku mohu nalézt více. Ve zkratce uvedu, pro mne, ty nejzásadnější:

  • Hot deploy - mohu provádět změny nad aplikací, bez nutnosti restartovat server či provádět redeploy aplikace

  • @In, @Out - Jednotlivé komponenty mohu zasazovat do logiky či je dále vystavovat; v ukázce je vidět, že uživatele jako komponentu přímo použiji v xhtml stránce, aniž bych musel používat nějaký controller nad modelem

  • @Scope - výčet životností komponent je mnohem bohatší, než je tomu v JSF

  • @Logger - přímá podpora logování pomocí log4j

  • pages.xml - pageflow, které umožňuje mnohem větší možnosti než je tomu u navigation-rules v JSF

  • No POST - díky Seamu, který umožňuje používat konverzaci, nemusí být view posílán přes POST

  • security - Seam obsahuje docela pěknou práci s rolemi, uživateli a vůbec s restrikcemi; navíc umožňuje ručně definovat práva a jejich chování


  • components.xml, exceptions.xml - konfigurovat se dá snad vše, ať už jsou to komponenty či zachytávání výjimek



Výčet by byl jistě mnohem bohatší. I když s daným frameworkem nemám tolik zkušenností, ihned jsem si ho oblíbil. Důvodem je možná i samotná referenční příručka, která mi odpoví téměř na všechny dotazy.

čtvrtek 29. listopadu 2007

Novinky 2

Jsem tu s další sadou novinek či událostí, které mě v poslední době asi nejvíce zaujaly. Bez dalších řečí, rovnou začnu:

NetBeans:
Jelikož jsem velkým fandou tohoto IDE a i samotné RCP platformy, jsem rád, že se blíží konečné vydání. Nyní je k dispozici NetBeans RC2, která navíc byla uživateli označena za použitelnou a připravenou k releasnutí.

Facelets:
Byl to pro mě trn v oku. Sice již několik měsíců používám NB6, ale bohužel bez podpory, která mi dost usnadňuje život. Nicméně, podpora facelets je na světě! Sice se jedná o testovací verzi, ale i tak jsou již některé věci použitelné.

Seam 2.0:
Jak již psal Petr Ferschmann, Seam 2.0 se konečně dostal do fáze GA. Po přechodu na tuto verzi jsem si zejména liboval v konfiguraci. Pokud projdete referenční příručku (mimochodem takhle si představuji studijní materiál, výborně napsaná), zjistíte, že nyní již není třeba konfigurovat tolik vlastností. Tímto ovšem apeluji na Petra Pišla (všemohoucí díky za podporu facelets), aby oprášil NetBeans plugin pro Seam 2.0. :)

MySQL:
V poslední době mi přijde, že nějak strnul vývoj tohoto produktu. Nyní je k dispozici MySQL 5.0.x, která jako jediná je GA. Zbytek je stále v aplha či RC verzi. Osobně jsem dost zvědavý na Falcon engine, který by měl nastoupit na místo InnoDB a míti rychlost srovnatelnou s MyISAM. Jenže, kde nic tu nic.
Ale proč přidávám toto do novinek? Před nedávnem mě dost vypekl konektor pro Javu. Při použití MySQL Connector/J 5.1.5 společně s Hibernate 3.2.x jsem se dostal do stavu, kdy hibernate nebyl schopen vytvářet "auto_increment", který má nastarosti právě MySQL. Při přechodu zpět na MySQL Connector/J 5.0.x je vše v pořádku. Možná se MySQL rozhodlo MySQL Connector/J verzovat stejně jako své verze Database Serveru.

Video Netbeans RCP vs. Eclipse RCP:
Konečně vyšlo toužebně očekávané video, kterého jsem se osobně zůčastnil. Každému vřele doporučuji. I když zrovna člověk neplánuje využít dané platformy, pro všeobecný přehled nad modulárními systémy, by si měl video prohlédnout.
Malý tip: No a když se dostanete na konec videa, tak mě můžete zahlédnout. Jsem ten poslední a jediný tazající :)

Exceptions for Action:
Poslední novinkou je článek na javaworld.com s názvem Exceptions for Action. Jedná se o hezký popis, jak správně navhovat výjimky uvnitř J2EE. Abych byl upřímný. I když rozumím způsobu práce výjimek, je pro mě velká magie je správně navrhovat a pracovat s nimi.

Tak to by bylo vše. Ještě jedna malá věc pro pobavení: Přáníčka od kofoly.

pátek 23. listopadu 2007

JBoss Seam 2.0 & Hibernate 3.2.5 & Glassfish V2

Když jsem přemýšlel jaký zvolím framework pro webovou aplikaci, naskytly se mi v podstatě dvě možnosti. Buď JSF či Struts. Osobně jsem raději hned sáhnul po JSF. Komponentový framework, navíc tolik dotovaný samotným Sunem.

Po vyzkoušení pár příkladů jsem ihned přešel do vývoje. Zde ovšem nastaly potíže. Psaní stejného kódu stále dokola. Stálá definice přes XML, neexistence použitelného scope pro komponenty. Navíc jsem na vývoj sám a přijde mi příliš těžkopádné vše striktně oddělovat.

Našel jsem Seam. Jedná se o webový framework od JBosse, který tvoří ono lepidlo mezi JSF a EJB3. Samotná definice komponent je plně řízena anotacemi, čímž odpadají mnohé XML definice. Seam navíc obsahuje dosah komponenty „conversation“. Taková komponenta poté existuje od doby vzniku konverzace až do jejího zániku. Odpadá tak potřeba definovat komponenty jako „session“. Další věcí, která mě zaujala byla podpora Hibernate Validatoru. Pokud použiji Hibernate, mám možnost nechat Seam, ať mi jednotlivé hodnoty entit validuje podle definice z Hibernate.

Já se zde nechci zabývat podrobnostmi, jak daný Seam funguje, k tomu slouži referenční příručka. Mimochodem skutečně výtečně napsaná. Spíše se zaměřím na to, jak nainstalovat Seam 2.0 na Glassfish V2.

Seam je primárně určen pro aplikační server Jboss. Pravdou ovšem je, že ho lze použít i na jiném serveru či přímo bez EJB kontejneru (viz. Tomcat). Samotná konfigurace se liší jen nepatrných věcech. Mě ovšem dali pekelně zabrat :)

Takže, nejprve je nutné stáhnout samotný Seam 2.0 a Hibernate. Již přímo v examplech existuje ukázková aplikace s názvem booking (v adresáři jee5). Jedná se o web. aplikaci pro hotel, kde si můžete zamluvit vlastní aparmá. Na aplikaci je vysvětlené jak funguje komunikace mezi Seamem, JSF a JPA.

Při tvorbě vlastní aplikace si musím nejprve zaregistovat dané knihovny.
Pro webovou vstvu to je:

  • el-api.jar

  • el-ri.jar

  • jsf-facelets.jar

  • jboss-seam-ui.jar


Pro EJB modul:

  • jboss-seam.jar

  • jboss-seam-debug.jar

  • hibernate-all.jar

  • thirdparty-all.jar



EJB Modul dále musí obsahovat conf/seam.properties, který může být klidně prázdný. Definice persistence.xml, kde je třeba, aby byla správně nastavena transakce:




org.hibernate.ejb.HibernatePersistence
my/db



value="org.hibernate.cache.HashtableCacheProvider"/>








Webový modul:
Jednak obsahuje web.xml, kde je třeba dodefinovat Seam:



org.jboss.seam.servlet.SeamListener



Seam Filter
org.jboss.seam.servlet.SeamFilter



Seam Filter
/*



Seam Resource Servlet
org.jboss.seam.servlet.SeamResourceServlet



Seam Resource Servlet
/seam/resource/*




A jednak reference na EJB Beany.

For Transaction from EJB3 Container
Irminsul/EjbSynchronizations/local
Session
org.jboss.seam.transaction.LocalEjbSynchronizations
EjbSynchronizations



MyEARName/MyBean/local
Session
ejb.seam.app.MyLocal
MyBean


Je to trochu nevýhoda oproti použití samotného Jbosse, kde reference jsou dohledany automaticky.

Dalšími konfiguračními soubory jsou:

  • components.xml

  • exceptions.xml

  • pages.xml

  • security.drl



V components.xml se definují jednotlivé vlastnosti Seamu jako jndi-pattern, security, atd.






concurrent-request-timeout="10000"
conversation-id-parameter="cid"/>















/WEB-INF/security.drl



Zaregistrování JNDI patternu je potřebné pro referencování EJB Bean. Dále nastavím, že transakce je řízena přes EJB kontejner, kde si Seam dokáže odchytit i exeptions při rollbacku.
Dále se jedná o nastavení časové platnosti konverzace.
Poslední věcí je authentifikace a nadefinovaní pravidel pro práci s rolemi a celkovými pravami nad aplikací.

V exceptions.xml se definuje ruční správa nad výjimkami. Jinymi slovy, pokud dojde k výjimce, mohu nechat aplikaci automaticky někam přesměrovat, odeslat příslušnou správu, atd. Samotná konfigurace může vypadat následovně:

V pages.xml se definuje page-flow. Zde je možnost využít klasický přistup přes navigation-rule v JSF nebo Seam přístup. Osobně se mi více zalíbíl tento přístup, jelikož povyšuje definici mnohem dál než v případě JSF.

V security.drl mám možnost definovat, nastavovat, odebírat, upravovat práva jednotlivých rolí. Jedná se o jakýsi konfigurační skript nad správou rolí. Pokud například chci, aby role admin mohla to samé co role obchodnik, žádný problém takovou věc nastavit.

Pro samotný běh enterprise aplikace je ještě zapotřebí nadefinovat jboss-seam.jar jako ejb modul. Definice se provádí v application.xml.

Pro práci s hibernate je zapotřebí nahrát všechny požadované knihovny do $GLASSFISH_HOME/lib a restartovat server.

Každý, kdo to s webovými aplikacemi v Jave myslí vážně, měl by se na Seam podívat. Už jen z prostého důvodu, že Gavin King se stal hlavním vývojářem pro novou specifikaci WebBeans, která by měla být v Java EE 6. Jak je patrné, tak WebBeans vycházejí právě z konceptu Seamu.

pátek 28. září 2007

NetBeans Platform (díl 2) – Výhody a nevýhody

Důvod, proč jsem zvolil desktop aplikaci vznikl z požadavku vytvořit aplikaci, která by komunikovala přes sériový port a ukládala čísla karet z různých čteček. Moc možností na výběr jsem neměl, jelikož přes webové rozhraní bych nebyl nic takového schopen aplikovat (samozřejmě nebudu zohledňovat aplety, které se mi dost příčí).

V první fázi jsem zvolil vlastní řešení (jako správný PHPčkář), přes Swing. Vše bylo v pořádku, do doby, kdy se aplikace začala rozrůstat. Implementace jednotlivých částí se prostě příliš svazovala mezi sebou a já začal mit v aplikaci chaos. Příčinou je jednak má nezkušenost s podobným druhem aplikací a jednak pouhá okrajová znalost konceptu pro distribuovanou Javu.

Poté jsem zajel na JAG, ve kterém se probírala RCP aplikace (NetBeans vs. Eclipse) a já si uvědomil, kde dělám chybu a jaké jsou výhody těchto řešení.

Asi bych měl znovu uvést, že se jedná o platformu, jinými slovy o „podvozek“, na kterém může běžet cokoli. Nejčastěji je ovšem známá kombinace: platforma + IDE = NetBeans IDE, Eclipse IDE. Dalo by se říci, že samotné vývojové prostředí je pouhý plugin dané platformy, i když je asi nejvýznamějším pluginem obou platforem.

Nyní již k samotným výhodám a nevýhodám tohoto řešení, do kterého zahrnuji kompletní řešení včetně použití dané platformy:

Z pohledu typu aplikace (desktop aplikace)

Výhody:
- možnost vytvořit přívětivé prostředí pro uživatele
- schopnost asynchroního volání bez zásahu nějakých zvláštních featur
- rychlá odezva mezi uživatelem a serverem
- prostředí umožňující přímou vazbu mezi uživatelem a OS (komunikace s periferiemi daného klientského PC)
- uvnitř desktop aplikace možnost používat i webovou aplikaci (vlastní web browser)

Nevýhody:
- distribuce (sice existují řešení jako JWS, ale s web aplikací se to srovnávat nedá)
- instalovana Java na klientském PC
- jisté systémové požadavky na běh aplikace (velikost RAM, atd)


Z pohledu architektury aplikace

Výhody
- swing (funguje kdekoli i s událostmi, na rozdíl od javascriptu u web aplikací)
- modulární systém (platforma stojí na tomto principu, který extrémně zpřehledňuje vývoj aplikace)
- skutečné OOP bez nutnosti statických view (HTML)
- Lookup (jedná se o hledání „služeb“ uvnitř kontextu NetBeans RCP)
- Services (služby, které lze registrovat a pomocí nich kominukovat mezi jednotlivými moduly, kteří o sobě vůbec nevědí, nemusí byt na sebe vázány)
- NetBeans API (při využívání tohoto API si navíc dokáži usnadnit práci a přímo ovlivňovat chování aplikace bez nutnosti přímého psaní swing komponent)
- podpora pluginů (pokud ve své aplikaci potřebuji nejakou funkčnost, kterou obsahuje plugin napsaný třetí stranou, mohu ho klidně využít a ušetřit si práci)
- celý koncept platformy, který je navržen tak, aby nejlépe odpovídal potřebám při psaní uživatelsky přívětivé aplikace

Nevýhody:
- náročná studie celého NetBeans API
- vzdálené volání EJB (spousta problémů při prvním setkání)
- v mnoha případech se jedná o kanón na vrabce

Asi by se dalo nalézt více kladů či záporů, ale v mém osobním pohledu, spatřuji tyto vlastnosti jako nejzásadnější.

V současné době se navíc musím vrátit k web aplikaci (osobně volím JSF), jelikož stojím před neřešitelným problémem: distribuce aplikace, s tím spojená i přímá aktualizace aplikace; a hardwarová náročnost aplikace, která mi neumožňuje distribuovat aplikaci mezi uživatele (velké fabriky holt nemají zájem tolik investovat do informatiky, kterou asi považují za nepotřebný subjekt).

I přes tuto velkou bariéru, mohu pokračovat na obou klientských verzích. Jak desktop, tak web, jelikož business logika (EJB kontejner) zůstává pro obě řešení stejná.

úterý 28. srpna 2007

NetBeans Platform 1. - Úvod

O co půjde?

Již podle názvu je jasné, že jsem se rozhodl psát o samotných NetBeans jako o platformě. V současné době se věnuji vývoji aplikace postavené právě na tomto "podvozku", a proto s tím souvisí i má snaha získat co nejvíce informací a zkušeností s touto platformou.

Předem bych rád upozornil, že nejsem žádný specialista v oblasti RCP aplikací, a proto se spíše budu zabývat menšími oblastmi při vývoji.

Často se mi stávalo, že jsem se v některé z pasáží natolik zasekl, že mi trvalo i několik dní, než jsem přišel na správné řešení. Jelikož jsem člověk, který rád pomáhá druhým, rozhodl jsem se, že touto formou pomohu některým lidem při jejich potížích.

Sám se budu snažit o zpětnou vazbu a pokud někdo bude znát lepší způsob implementace dané věci, budu rád, když ji poskytne ostatním.

Co byste si měli přečíst...

Jak už to tak bývá, tak i zde je třeba někde začít. Jistým předpokladem je znalost Javy, základní znalost swingu a znalost používání NetBeans jako vývojového nástroje.
Pokud všechny tyto znalosti mám, mohu se pustit do vývoje. Osobně jsem začal krátkými tutoriály na www.netbeans.org/, poté by měla být na řade kniha Rich Client Programming: Plugging into the NetBeans Platform.
Následuje Geertjan's Weblog, který popisuje jednotlivé postupy a nabízí srozumitelnější výklad než samotný javadoc.

Další zdroje se dají samozřejme nalézt pomocí googlu či na stránkách netbeans.org. Já se zaměřím spíše na základní popis.

NetBeans RCP

NetBeans IDE

Jako základní API jsem si zvolil NetBeans 6.0 M10. I když se jedná pouze o milestone, domnívám se, že se až tolik změn v API konat nebude. Proto všechny příklady budou předpokládát, že máte tuto verzi, či verzi vyšší, nainstalovánu.
Jelikož je spousta komponent přímo svázána (děděno z komponent Swingu ) se swingem, nebudu se příliš zaobírat jejich funkčností a budu předpokládat základní znalost těchto komponent.


Nakonec bych ještě jednou rád podotkl, že ne všechna řešení jsou v souladu se spravným použitím. Dost často se může stát, že bude existovat novější, efektivnější či odlišný způsob řešení daného problému. Proto mě prosím nekamenujte za tyto postupy, ale raději se pokuste přispět svými nápady v diskuzi.

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...