pátek 18. prosince 2009

Jak neztratit hlavu při řešení problémů

     Řešení velkých a komplexních úkolů není často snadná cesta. Ať se jedná o celý projekt nebo úkol realizující část, častokrát se do problematiky tak zamotáme, že nevíme kudy kam. Nemůže za to bludný kámen ani zlý rarach, který nás svede na špatnou cestu. Býváme to my, kdo se nechá příliš unést podrobnostmi a ztratí tak přehled nad tím, co vlastně dělá. Pokud tento stav zamotanosti identifikujeme včas, lze s tím pracovat, aniž bychom zbytečně ztráceli man-days a ušetřili si tak nepříjemné chvíle, kdy nám stojí projekťák za zády a ptá se, kdy že to už bude hotové.
    Úspěch tkví v tom, že si problém na začátku rozdělíme na úkoly a podúkoly. Tuto "osnovu" však budeme po celou dobu vývoje udržovat v aktuálním stavu, především se jedná o další rozdrobení podúkolů vedoucí k atomizaci celkového problému. Nyní se můžeme pustit do samotného vývoje. Budeme postupně řešit body osnovy a kdykoliv se ztratíme, koukneme o úroveň výš, případně o tolik úrovní kolik bude potřeba, abychom se zorientovali nad tím, jaký vůbec má smysl naše počínání. Mozek toto dělá do určité míry sám, ale pokud něco řešíte měsíc, je opravdu lepší si napsat osnovu a udržovat mysl v tom, co právě děláte.

pátek 11. prosince 2009

Java databáze HSQLDB

    Relační databáze HSQLDB je celá napsaná v jave. Je malá, rychlá, s podporou mnoha vláken, umožňující použití LOBů (large objects) a transakcí. Je velice jednoduchá na použití a hodí se jak na vývoj API, začátky projektu (kdy ještě nejsou přesně definovány specifikace db a nejsou připravené prostředí pro vývoj) nebo třeba pro JUnit testy.

    Asi nemá cenu probírat dopodrobna specifikace tohoto maličkého nástroje, odkážu vás na domovské stránky projektu http://hsqldb.org/, případně na http://sourceforge.net/projects/hsqldb/.

    S tímto nástrojem mám dobré zkušenosti, proto jsem se rozhodl, že zde ukážu jednoduchou ukázku použití :). Budeme pracovat s verzí 1.8.0.7 a pomůže nám orm framework Hibernate verze 3.3.1.GA a Spring container verze 2.5.6.

    Nejdříve si definujeme ve spring kontextu dataSource (zde využijeme knihovny jakarta-commons modulu dbcp pro DataSource holder). Nadefinujeme property driver, url, username a password. V případě, že bychom potřebovali in-memory databázy, nastavíme url na hodnotu jdbc:hsqldb:mem:db_test.

    <bean id="dataSource" scope="singleton" destroy-method="close"
            class="org.apache.commons.dbcp.BasicDataSource">

        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:db_test"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
    </bean>

    Vytvoříme si hibernateFactory.

    <bean id="hibernateFactory"
            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                <prop key="hibernate.cache.provider_class">
                    net.sf.ehcache.hibernate.EhCacheProvider
                </prop>

                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
            </props>
        </property>
        <property name="dataSource" ref="dataSource"/>
        <property name="schemaUpdate" value="true"/>
        <property name="mappingLocations" value="classpath*:project/**/*.hbm.xml"/>
    </bean>

    Vytvoříme si domain objekty s mapováním podle specifikace hibernate a cestu uvedeme do hodnoty property mappingLocations, pokud nastavíme propertě schemaUpdate true, tak se při inicializaci této beany vytvoří v db tabulky automaticky.

    Teď máme v podstatě databázy připravenou pro použití, db pracuje s daty, které má na filesystemu.

    Pří používání jsem narazil na problém, že se neuvolňuje spojení s db. Vyřešil jsem to abstraktní třídou, z které všechny testy dědí. Je potřeba zavolat příkaz SHUTDOWN (podle specifikace HSQLDB), který connectionu uvolní.

    @ContextConfiguration(locations = {"classpath:spring/*.xml"})
    public abstract class AbstractTest
        extends AbstractTransactionalJUnit4SpringContextTests {


        @Autowired
        private BasicDataSource dataSource;

        @After
        public void afterTest() throws SQLException {
            Statement statement = dataSource.getConnection().createStatement();
            statement.execute("SHUTDOWN");
            statement.close();
        }
    }

    Pro vyzkoušení této technologie by to mělo být vše. Tak s požehnáním do toho! :)


Publikování příspěvků pomocí google docs

Dnes jsem zjistil, jak snadno a efektivně publikovat na tento blog příspěvky. Stačí začít používat aplikaci http://docs.google.com/. Napíšete dokument v požadovaném formátu a uložíte. Zvolíte volby Sdílet > Publikovat jako webovou stránku... > Odeslat příspěvek do blogu. Vyplníte náležité přihlašovací údaje, odfajfkujete a systém vás v brzku notifikuje o úspěšném publikování vašeho příspěvku. Prostě paráda, máte takovou radost jako já? :o)

MSSQL - funkce ROW_NUMBER() aneb číslování řádků


Konstrukce pro číslování vrácených řádků by vypadala následovně:

    select
    ROW_NUMBER() over (order by SLOUPEC)
    from TABULKA

Pro bližší ukázku:
  • máme tabulku LOG se sloupci DATE a DESCRIPTION

  • obsahuje data
    '11.12.2009 12:05', 'Inicializace'
    '11.12.2009 12:25', 'Chyba'
    '11.12.2009 13:00', 'Dalsi hlaska'

  • použijeme následující konstrukci
    select
        DESCRIPTION,
        ROW_NUMBER() over (order by DATE desc) as ORDER
    from LOG

  • select vrátí   
    DESCRIPTION        ORDER
    'Dalsi hlaska'     1
    'Chyba'            2
    'Inicializace'     3

čtvrtek 23. dubna 2009

PropertyPlaceholderConfigurer - jak na property v aplikačním kontextu

Ve springu v modulu beans je velice šikovná třída org.springframework.beans.factory.config.PropertyPlaceholderConfigurer. Umí z property filu podle klíče vložit hodnotu do aplikačního kontextu.

Použití v javadocu springu -> PropertyPlaceholderConfigurer.

Díky za reakci :)
Definice beany by vypadala následovně:

<bean id="localPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>cfg/localContext.properties</value>
</list>
</property>
</bean>

Nyní kdekoliv v kontextu se řetězec ${...} nahradí hodnotou z property souboru.

středa 22. dubna 2009

Systémové datum pomocí hibernate dialectu

Na našem projektu jsme potřebovali mechanismus, který by zjišťoval systémové datum. Pro každou db jsme implementovali třídu, kde byl natvrdo napsán JDBC select. Kupříkladu, v Oraclu "select sysdate from dual", pro MSSQL byla obdoba "select getdate()". Nakonec se ukázalo daleko příjemnějším řešením hibernate dialect.

Hibernatu musíte dát vědět, s jakou db má tu čest a to tak, že mu docpete konkrétní dialect. Hlavní předek je abstraktní třída
org.hibernate.dialect.Dialect. Obsahuje metodu getCurrentTimestampSelectString(), kterou implementují konkrétní dialecty. V této metodě se nachází náš hledaný JDBC select.

Teď k samotnému řešení.


public Calendar getSysDate() {
Calendar sysDate = Calendar.getInstance();
if (sessionFactory instanceof SessionFactoryImplementor) {
Session session = SessionFactoryUtils.getNewSession(sessionFactory);
Dialect dialect = ((SessionFactoryImplementor) sessionFactory).getDialect();
String queryString;
try {
queryString = dialect.getCurrentTimestampSelectString();
} catch (UnsupportedOperationException un) {
return sysDate;
}
Query query = session.createSQLQuery(queryString);
Object result = query.uniqueResult();
if (result != null && result instanceof Date) {
sysDate.setTime((Date) result);
}
}
return sysDate;
}

V případě, že pro daný dialect není přepsána metoda
getCurrentTimestampSelectString(), vyhodí se vyjímka UnsupportedOperationException a metoda getSysDate() vrací Calendar.getInstance(). Určitě by jste to tak neměli nechat a měli by jste si přepsat váš potřebný dialect a implementovat výše uvedenou metodu :).