pátek 28. července 2006

Odložené nahrávání dat v ORM nástrojích

Odložené nahrávání dat, takzvaný lazy fetching, patří k základním vlastnostem pro zvýšení výkonu v ORM nástrojích jako Hibernate či iBatis SQL Maps. Představme si případ kdy máme dvě entiy entity ve vztahu 1:* např. osoba a auto.

public class Osoba {
  private Set<Auto> auta;

  public Set<Auto> getAuta() {
    return auta;
  }

  public void setAuta(Set<Auto> auta) {
    this.auta = auta;
  }  
}

Odložené nahrávání může být v tomto případě použito na kolekce automobilů a to následujícím způsobem. Kolekce automobilů je z databázé dotažena teprve ve chvíli kdy je volána metoda getAuta(). Díky odloženému nahrávání je tak možné data načíst teprve ve chvíli kdy je to opravdu potřeba.

Otázka je jak výše uvedený getter zajistí nahrání dat z databáze? Samozřejmě, že nezajistí, to co ho zajistí se jmenuje dynamický proxy objekt. ORM framework totiž nikdy nevrací přesně objekt dané třídy nýbrž v runtime čase dynamicky vytvořeného potomka dané třídy. Díky dědičnosti je pro vás práce s objektem, v našem případě Auto, transparentní. Potomek pak slouží jako proxy objekt, který realizuje odložené nahrání dat.

Pro lepší znázornění výše popsaného, kód který vznikne semanticky odpovídá následujícímu kódu.

public class OsobaProxy extends Osoba {
  public Set<Auto> getAuta() {
    Set<Auto> auta = ... //volani logiky pro nacteni dat
    setAuta(auta);
    return super.getAuta();
  }  
}

Hibernate tak iBatis používá na vytváření proxy objektů v runtime framework zvaný CGLIB. Jak je jednoduché s CGLIBem pracovat si ukážeme na následujícím příkladu, třeba se vám to bude hodit. Vytvoříme jednoduchou beanu a k ní v runtime proxy objekt, který při každém volání metody naší beany vypíše název této metody.

Vlastní beana

/**
 * Klasicka Java bean
 */
public class Bean implements Serializable{
  
  private int foo;
  
  public int getFoo() {
    return foo;
  }
  
  public void setFoo(int foo) {
    this.foo = foo;
  }  
}

Interceptor, třída která bude zavěšená na volání metod beany. V interceptoru se nejdříve vypíše název volané metody a následně se nechá vykonat původní metoda beany.

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * Interceptor, ktery je zavesen na volani jakekoliv metody {@link cz.sweb.pichlik.examples.lazyinit.Bean}
 */
public class Interceptor implements MethodInterceptor {
  
  /**
   * Vypise nazev volane metody
   */
  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxythrows Throwable {
    System.out.println("Volana metoda:" + method.getName());
    return proxy.invokeSuper(obj, args);
  }

}

Ukázka vytvoření dynamické proxy beany a jejího volání. Všimněte si zavěšení interceptoru.

import net.sf.cglib.proxy.Enhancer;

/**
 * Demonstruje instrumentaci Java beany viz {@link cz.sweb.pichlik.examples.lazyinit.Interceptor}
 *
 */
public class LazyInitExample {


  public static void main(String[] args) {
    Bean instrumentedBean = (BeancreateNewInstrumentedBean(Bean.class);    
    instrumentedBean.setFoo(10);
    instrumentedBean.getFoo();
  }
  
  /**
   * Vytvori rozsirenou instanci objektu dane tridy.
   
   @param clazz trida
   @return instance
   */
  private static Object createNewInstrumentedBean(Class clazz){
    Interceptor interceptor = new Interceptor();
    Enhancer e = new Enhancer();
    e.setSuperclass(clazz);
      e.setCallback(interceptor);
    Object instrumentedBean = e.create();
    return instrumentedBean;
  }

}

středa 26. července 2006

Systinet resp. Mercury koupena firmou Hewlett-Packard

Když jsem dělal pohovor do současné firmy, byla to ještě firma Systinet. Když jsem nastoupil, byl Systinet již jednou z divizí Mercury, no a dneska ráno jsem našel v poště email, že Mercury byla koupena firmou Hewlett-Packard. Celková výše transakce byla 4.5 miliardy dolarů.

Další informace

pondělí 24. července 2006

Třívrstvá architektura v kostce II. - design střední vrstvy

Osobní poznámka na začátek: k sepsání tohoto článku jsem se hotovil nejméně rok a půl. Na určité věci musí mít člověk náladu a chuť, ale že tento článek resp. jeho základ vznikne na koleni v autobuse z Prahy do Písku při pátečním podvečeru, tak to jsem opravdu nečekal.

Pokud jsme se bavili o třívrstvé architektuře, bylo zdůrazněno, že největší pozornosti by se mělo věnovati designu střední vrstvy (někdy též nazývané aplikační vrstvou či middle tier). Střední vrstva by aplikace by měla být horizontálně strukturovaná do takzvaných subvrstev (pro další části článku používám pro subvrstvu označení vrstva).

Vazby mezi jednotlivými vrstvami by měly být na úrovni rozhraní a v budoucnu umožňovat snadnou změnu implementace. Izolace vrstev přináší další výhodou v podobě snazšího testování v rámci jednotkových testů. V podstatě jsou definovány tři základní vrstvy.

  • UI/RPC vrstva
  • Service vrstva
  • DAO vrstva

Konceptuální schéma architektury střední vrstvy
Plná velikost obrázku (29 KB)

UI vrstva/RPC bridge

UI vrstva/RPC bridge je prostředník mezi komunikačním protokolem klienta a vnitřní strukturou aplikace. Přímo používá pouze Service vrstvu a to tak, že převede požadavek na vnitřní volání a získaná data vrátí zpět v patřičném formátu.

UI vrstva

Část určená pro spolupráci s webovým prohlížečem, výsledek požadavku je vrácen jako HTML data. UI vrstva by měla být implementována podle návrhového vzoru MVC (Model-View-Controller).

RPC bridge

Tato vrstva slouží jako prostředník, pro danou implementaci RCP. V podstatě exportuje Service vrstvu pro vzdálené volání například jako webovou službu.

Service vrstva

Service vrstva též nazývaná jako Business vrstva slouží pro implementaci logiky aplikace. V podstatě jsou v ní realizovány jednotlivé aplikační algoritmy. Tato vrstva přímo spolupracuje pouze s nejbližší nižší vrstvou, která poskytuje data.

Data access vrstva

Data access vrstva slouží pouze a jedině k práci s úložištěm dat. Úložiště dat může být například relační databáze, souborový systém a nebo jiný systém. V této vrstvě je tedy pouze naimplementovaná logika pro zacházení s daným datovým zdrojem. V případě relační databáze je tato vrstva implementována pomocí klasického JDBC API a nebo pomocí objektově-relačního API.

Domain model

Lepidlo jednotlivých vrstev je představeno v podobě domain modelu aplikace. Domain model je objektové vyjádření vztahů mezi jednotlivými entitami systému. Na příkladu elektronického obchodu, máme entity jako objednávka, objednávající, zboží, faktura. Tyto entity převedené na objekty představují domain model aplikace.

Všechny vrstvy pracují s domain modelem podle svého určení. DAO vrstva může výsledky dotazu do relační databáze převádět na graf objektů. Service vrstva získaný graf objektů zpracuje například zkontroluje jestli je dané zboží na skladě a odešle email. UI vrstva zobrazí uživateli výsledek požadované akce.

Společné aspekty

Transakce, autorizace, logování to všechno jsou aspekty, které se prolínají přes jednotlivé vrstvy. Není proto vhodné je zakódovat hluboko do střev aplikace. Daleko výhodnější je použití ne invazivních metod jako jsou metadata (anotace, popisné XML) a AOP (Aspektově Orientované Programování).

Transakce

Transakce je možné zadefinovat na úrovní Service vrstvy a nebo DAO vrstvy a propagovat je směrem dolu. Transakce muže být zadefinována programově voláním transakčního API přímo z vlastního kódu a nebo pomocí metadat, tomuto způsobu se říká deklarativní. Deklarativní definice transakce postačuje pro 95% případů, na ten zbytek je možné použít přímo transakční API.

Autorizace

Autorizace na úrovni volání jednotlivých metod je dalším klasickým příkladem aspektu, který lze deklarativně nadefinovat na úrovni metadat, bez nutnosti modifikace vlastního kódu aplikace. Na druhou stranu autorizace na úrovni volání metod nemusí být vždy nutná.

Logování

Logování na úrovni jednotlivých vrstev aplikace je obdobný příklad jako autorizace co do nutnosti. V případě logování na úrovní vrstev (audit logování) lze úspěšně použít AOP. Samozřejmě pro logování na úrovni trasování programu se nikdy nevyhnete zanesení logovacího API do vlastního kódu aplikace.

Volba technologie

Při volbě technologie pro realizaci střední vrstvy by mělo platit základní pravidlo a to, že použitá technologie nesmí v žádném případě diktovat architekturu aplikace. Nechci zde protěžovat nějakou technologii, protože tenhle článek není o konkrétních technologiích, ale o architektuře. Ostatně použitá technologie je jenom implementační detail schovaný za business rozhraním...