<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Xis' blog &#187; Do zapamiętania</title>
	<atom:link href="http://xis.schowek.net/category/do-zapamietania/feed/" rel="self" type="application/rss+xml" />
	<link>http://xis.schowek.net</link>
	<description>Mój wirtualny schowek</description>
	<lastBuildDate>Thu, 10 Mar 2011 18:41:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Grails i kompozytowe klucze w Hibernate</title>
		<link>http://xis.schowek.net/2009/01/24/grails-i-kompozytowe-klucze-w-hibernate/</link>
		<comments>http://xis.schowek.net/2009/01/24/grails-i-kompozytowe-klucze-w-hibernate/#comments</comments>
		<pubDate>Sat, 24 Jan 2009 16:30:06 +0000</pubDate>
		<dc:creator>xis</dc:creator>
				<category><![CDATA[Do zapamiętania]]></category>
		<category><![CDATA[grails]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://xis.schowek.net/?p=202</guid>
		<description><![CDATA[Grails to bardzo ciekawy framework przygotowany dla języka Groovy. Od razu zdobył moją sympatię za to, że &#8211; nie tylko nazwą &#8211; przypomina architekturę Ruby on Rails, czy też Symfony dla PHP, realizując najważniejsze polityki nowoczesnych frameworków: Convention Over Configuration i Do Not Repeat Yourself. Zawsze ubolewałem (i w sumie nadal ubolewam) nad brakiem takiego [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://grails.org/">Grails</a> to bardzo ciekawy framework przygotowany dla języka <a href="http://groovy.codehaus.org/">Groovy</a>. Od razu zdobył moją sympatię za to, że &#8211; nie tylko nazwą &#8211; przypomina architekturę <a href="http://rubyonrails.org/">Ruby on Rails</a>, czy też <a href="http://www.symfony-project.org/">Symfony</a> dla <a href="http://php.net">PHP</a>, realizując najważniejsze polityki nowoczesnych frameworków: <a href="http://en.wikipedia.org/wiki/Convention_over_Configuration">Convention Over Configuration</a> i <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">Do Not Repeat Yourself</a>. Zawsze ubolewałem (i w sumie nadal ubolewam) nad brakiem takiego rozwiązania dla &#8216;czystej&#8217; Javy (może Ty znasz jakiś przykład?), dlatego tym chętniej zainteresowałem się tajnikami Grails.</p>
<p>Przyznam, że raczej sceptycznie reaguję na różne &#8216;liberalne&#8217; języki programowania, np. fakt, że jakąś operację można wykonać używając różnych konstrukcji języka (bo wg mnie zaciemnia to nieco obraz samego kodu i utrudnia jego pielęgnację), albo dynamiczcne typowanie (zawsze przeklinałem PHP za tę &#8216;przypadłość&#8217;), jednak dałem Groovy&#8217;emu szansę, za jego główną zaletę: pełną kompatybilność z Javą &#8211; Groovy jest de facto wykonywany przez maszynę wirtualną Javy, więc kompatybilność ta jest oczywista.</p>
<p>Umówmy się &#8211; należę do tych bardziej konserwatywnych programistów wierzących w &#8216;twardą&#8217; składnię, a w Groovy nie umiem (jeszcze) nic poza &#8222;Hello World&#8221;, toteż bardzo zależało mi na frameworku, w którym będę mógł wykorzystać już istniejące ziarenka Javy.  Samego Groovy&#8217;ego też chętnie zgłębię, ale najpierw chcę zobaczyć co mogę zrobić z Grailsami wykorzystując istniejący już kod Javy.</p>
<p>Grails &#8211; jak RoR, czy Symfony &#8211; posiada własny mechanizm <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">mapowania obiektowo-relacyjnego</a> (gdzieś tam głęboko napędzany przez <a href="http://www.hibernate.org/">Hibernate</a>), zwany <a href="http://grails.org/GORM">GORM</a>, pozwalający na mapowanie klas Groovy&#8217;ego z bazą danych. Ja jednak, przez założenie, chcę mapować ziarna encji Hibernate napisane w Javie. Grails pozwala na to bez problemów, kilka prostych czynności i już możemy wykorzystać przygotowane wcześniej encje w Grails.</p>
<p>No, może nie całkiem bez problemów.</p>
<p>Aby zmapować klasy encji wystarczy, zgodnie z <a href="http://grails.org/Hibernate+Integration">opisem na stronie Grails</a>, wyedytować plik <strong>DataSource.groovy</strong>, dodać mapowanie w <strong>hibernate.cfg.xml</strong> i wreszcie skopiować swoje klasy javy do katalogu <strong>src/java</strong>. Po wykonaniu tych czynności możemy już wygenerować na podstawie encji nowy kontroler i widok, wklepując w konsoli:</p>
<pre>grails generate-all pelna.nazwa.naszej.Klasy</pre>
<p>Grails wygeneruje dla nas wszystkie niezbędne klasy kontrolerów (w języku Groovy, rzecz jasna), elementy widoku (strony GSP), słowem mamy już cały <a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a>.  Problem jednak pojawia się w przypadku, gdy nasza encja wyposażona jest w klucz złożony, a schemat naszej bazy danych &#8211; jak w moim przypadku &#8211;  nie może zostać zmodyfikowany, bo jest wykorzystywany przez inne programy.</p>
<p>Grails teoretycznie pozwoli na mapowanie takich encji, wygeneruje też dla nich kontrolery i pliki widoków, jednak nie bedą one działały. Rozważmy poniższy przypadek.</p>
<p>Mamy encję Produkt (mapowaną  na tabelę &#8222;PRODUKTY&#8221;), encję Cennik (mapowaną na tabelę &#8222;CENNIKI&#8221;) i encję Cena (tabela &#8222;CENY&#8221;) .  <a href="http://www.netbeans.org/">NetBeans</a>, na podstawie istniejącego schematu bazy danych, wygenerował mi takie klasy (po drobnej korekcie nazw własności):</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">net.schowek.grailsapp</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// importy</span>
&nbsp;
@<span style="color: #003399;">Entity</span>
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;PRODUKTY&quot;</span><span style="color: #009900;">&#41;</span>
@NamedQueries<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>@NamedQuery<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Produkt.findAll&quot;</span>, query <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT p FROM Produkt p&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Produkt <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399;">Serializable</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">long</span> serialVersionUID <span style="color: #339933;">=</span> 1L<span style="color: #339933;">;</span>
&nbsp;
    @Id
    @Basic<span style="color: #009900;">&#40;</span>optional <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
    @Column<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;pr_id&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Integer</span> id<span style="color: #339933;">;</span>
&nbsp;
    @Basic<span style="color: #009900;">&#40;</span>optional <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
    @Column<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;pr_nazwa&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> nazwa<span style="color: #339933;">;</span>
&nbsp;
    @Column<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;pr_opis&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> opis<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> Produkt<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> Produkt<span style="color: #009900;">&#40;</span><span style="color: #003399;">Integer</span> prId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">id</span> <span style="color: #339933;">=</span> prId<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// gettery i settery</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> toString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> getNazwa<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">net.schowek.grailsapp</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// importy</span>
&nbsp;
@<span style="color: #003399;">Entity</span>
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;CENNIKI&quot;</span><span style="color: #009900;">&#41;</span>
@NamedQueries<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>@NamedQuery<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Cennik.findAll&quot;</span>, query <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT c FROM Cennik c&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Cennik <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399;">Serializable</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">long</span> serialVersionUID <span style="color: #339933;">=</span> 1L<span style="color: #339933;">;</span>
&nbsp;
    @Id
    @Basic<span style="color: #009900;">&#40;</span>optional <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
    @Column<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;cn_id&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Integer</span> id<span style="color: #339933;">;</span>
&nbsp;
    @Column<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;cn_nazwa&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> nazwa<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> Cennik<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> Cennik<span style="color: #009900;">&#40;</span><span style="color: #003399;">Integer</span> cnId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">id</span> <span style="color: #339933;">=</span> cnId<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// gettery i settery</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> toString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> getNazwa<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">net.schowek.grailsapp</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// importy</span>
&nbsp;
@<span style="color: #003399;">Entity</span>
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;CENY&quot;</span><span style="color: #009900;">&#41;</span>
@NamedQueries<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>@NamedQuery<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Cena.findAll&quot;</span>, query <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT c FROM Cena c&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Cena <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399;">Serializable</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">long</span> serialVersionUID <span style="color: #339933;">=</span> 1L<span style="color: #339933;">;</span>
&nbsp;
    @EmbeddedId
    <span style="color: #000000; font-weight: bold;">private</span> CenaPK id<span style="color: #339933;">;</span>
&nbsp;
    @JoinColumn<span style="color: #009900;">&#40;</span> name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;ce_pr_id&quot;</span>, referencedColumnName <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;pr_id&quot;</span>, insertable <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span>, updatable <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span>  <span style="color: #009900;">&#41;</span>
    @ManyToOne
    <span style="color: #000000; font-weight: bold;">private</span> Produkt produkt<span style="color: #339933;">;</span>
&nbsp;
    @JoinColumn<span style="color: #009900;">&#40;</span> name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;ce_cn_id&quot;</span>, referencedColumnName <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;cn_id&quot;</span>, insertable <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span>, updatable <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span>  <span style="color: #009900;">&#41;</span>
    @ManyToOne
    <span style="color: #000000; font-weight: bold;">private</span> Cennik cennik<span style="color: #339933;">;</span>
&nbsp;
    @Column<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;ce_cena&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">BigDecimal</span> cena<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> Cena<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> Cena<span style="color: #009900;">&#40;</span>CenaPK cenaPK<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">id</span> <span style="color: #339933;">=</span> cenaPK<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// gettery i settery</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> toString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> getId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>I wreszcie klasa określająca nasz klucz złożony:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">net.schowek.grailsapp</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// importy</span>
&nbsp;
@Embeddable
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> CenaPK <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399;">Serializable</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    @Basic<span style="color: #009900;">&#40;</span>optional <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
    @Column<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;ce_pr_id&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> cePrId<span style="color: #339933;">;</span>
&nbsp;
    @Basic<span style="color: #009900;">&#40;</span>optional <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
    @Column<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;ce_cn_id&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> ceCnId<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> CenaPK<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> CenaPK<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> cePrId, <span style="color: #000066; font-weight: bold;">int</span> ceCnId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">cePrId</span> <span style="color: #339933;">=</span> cePrId<span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">ceCnId</span> <span style="color: #339933;">=</span> ceCnId<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> getCePrId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> cePrId<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setCePrId<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> cePrId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">cePrId</span> <span style="color: #339933;">=</span> cePrId<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> getCeCnId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> ceCnId<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setCeCnId<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> ceCnId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">ceCnId</span> <span style="color: #339933;">=</span> ceCnId<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> toString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #0000ff;">&quot;net.schowek.grailsapp.CenaPK[cePrId=&quot;</span> <span style="color: #339933;">+</span> cePrId <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;, ceCnId=&quot;</span> <span style="color: #339933;">+</span> ceCnId <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;]&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Tak przygotowanesą podstawą wygenerowanej aplikacji.  Po uruchomieniu aplikacji za pomocą komendy grails run-app mogę już eksplorować zasoby cen i produktów. Problem jednak zaczyna się, gdy chcę przejrzeć listę cen. Już na liście (http://localhost:8080/GrailsApp/cena/list) widać, że odnośniki do rekordów cen nie przypominają standardowych odnośników do rekordów tabel o prostych kluczach. Przykładowy link do ceny wyglądał tak:</p>
<p><a href="http://localhost:8080/GrailsAppl/cena/show/net.schowek.grailsapp.CenaPK%5BcePrId%3D63%2C+ceCnId%3D2%5D">http://localhost:8080/GrailsAppl/cena/show/net.schowek.grailsapp.CenaPK%5BcePrId%3D63%2C+ceCnId%3D2%5D</a></p>
<p>a strona, którą można pod nim zobaczyć wygląda tak:</p>
<p><img class="aligncenter size-full wp-image-211" title="err" src="http://xis.schowek.net/wp-content/uploads/2009/01/err.jpg" alt="err" width="770" height="407" /><br />
Jak widać, Grails w miejsce <strong>id</strong>, podstawia wartość obiektu klasy <strong>CenaPK</strong>, a ten reprezentowany jest przez swoją metodę <strong>toString()</strong>.  Po odwołaniu się do serwera i zapytaniu o cenę o podanym kluczu, serwer &#8211; co oczywiste &#8211; częstuje nas wyjątkiem.</p>
<p>Oto prosty sposób, w jaki można temu zaradzić (zakładając, że klucz złożony składa się z pól typu numerycznego).</p>
<p>Przede wszystkim, zmieniłem kod klasy <strong>CenaPK</strong> na taki (zmieniłem <strong>toString() </strong>i dodałem jeden konstruktor):</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> KEY_SEPARATOR<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;_&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> toString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> cePrId<span style="color: #339933;">+</span>KEY_SEPARATOR<span style="color: #339933;">+</span>ceCnId<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> CenaPK<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> k<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> keys <span style="color: #339933;">=</span> k.<span style="color: #006633;">split</span><span style="color: #009900;">&#40;</span> KEY_SEPARATOR <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">cePrId</span> <span style="color: #339933;">=</span> <span style="color: #003399;">Integer</span>.<span style="color: #006633;">parseInt</span><span style="color: #009900;">&#40;</span>keys<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">ceCnId</span> <span style="color: #339933;">=</span> <span style="color: #003399;">Integer</span>.<span style="color: #006633;">parseInt</span><span style="color: #009900;">&#40;</span>keys<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Jak widzisz, połączyłem w jeden string dwa klucze oddzielone od siebie separatorem. Oznacza to, że ponowne wygenerowanie widoków komendą:</p>
<pre>grails generate-views net.schowek.grailsapp.Cena</pre>
<p>poskutkuje nową listą cen, zawierającą odnośniki do rekordów podobne do tych:</p>
<p><a href="http://localhost:8080/GrailsAppl/cena/show/63_2">http://localhost:8080/GrailsAppl/cena/show/63_2</a></p>
<p>Aby wszystko grało, musiałem jeszcze przerobić kontroler cen (plik <strong>CenaController.groovy</strong> w katalogu <strong>controllers/</strong>) i zmienić wszystkie linie ładujące pojedynczy rekord ceny z</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">def</span> cenaInstance <span style="color: #66cc66;">=</span> Cena.<span style="color: #663399;">get</span><span style="color: #66cc66;">&#40;</span> params.<span style="color: #006600;">id</span> <span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>na</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">def</span> cenaInstance <span style="color: #66cc66;">=</span> Cena.<span style="color: #663399;">get</span><span style="color: #66cc66;">&#40;</span> <span style="color: #000000; font-weight: bold;">new</span> CenaPK<span style="color: #66cc66;">&#40;</span>params.<span style="color: #006600;">id</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Od tej pory mogłem się już cieszyć działającą aplikacją obsługującą klucze złożone.</p>
<p>Aha, separatorem klucza może być w zasadzie dowolny znak, jednak są tu wyjątki &#8211; np. nie zadziała na pewno <em>slash</em>, ponieważ jest on interpretowany przez <strong>UrlMappera</strong> grails. Warto zatem sprawdzić co zadziała, a co nie.</p>
]]></content:encoded>
			<wfw:commentRss>http://xis.schowek.net/2009/01/24/grails-i-kompozytowe-klucze-w-hibernate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zen Cart w zgodzie z WAMP</title>
		<link>http://xis.schowek.net/2009/01/06/zen-cart-w-zgodzie-z-wamp/</link>
		<comments>http://xis.schowek.net/2009/01/06/zen-cart-w-zgodzie-z-wamp/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 21:24:05 +0000</pubDate>
		<dc:creator>xis</dc:creator>
				<category><![CDATA[Do zapamiętania]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wamp]]></category>
		<category><![CDATA[zen cart]]></category>

		<guid isPermaLink="false">http://xis.schowek.net/?p=174</guid>
		<description><![CDATA[Ostatnio miałem okazję wykonać kilka modyfikacji dla platformy sklepowej Zen Cart zainstalowanej na serwerze mojego klienta. Zen Cart to platforma sklepowa oparta o darmowy osCommerce. Istnieje dla niego dość sporo rozszerzeń i wtyczek, ale moje zlecenie było tak specyficzne, że niestety nie obyło się bez potrzeby modyfikacji kodu sklepu (czego, mówiąc szczerze, bardzo starałem się [...]]]></description>
			<content:encoded><![CDATA[<p>Ostatnio miałem okazję wykonać kilka modyfikacji dla platformy sklepowej <a href="http://www.zencart.pl/">Zen Cart</a> zainstalowanej na serwerze mojego klienta. Zen Cart to platforma sklepowa oparta o darmowy <a href="http://pl.wikipedia.org/wiki/OsCommerce">osCommerce</a>. Istnieje dla niego dość sporo rozszerzeń i wtyczek, ale moje zlecenie było tak specyficzne, że niestety nie obyło się bez potrzeby modyfikacji kodu sklepu (czego, mówiąc szczerze, bardzo starałem się uniknąć).</p>
<p>Wersja produkcyjna sklepu działa pod kontrolą systemu <a href="http://pl.wikipedia.org/wiki/Unix">UNIX</a>&#8216;owego, a specyfika zlecenia polegała na tym, że musiałem dokonać kilku poważnych poprawek &#8211; co najważniejsze &#8211; działając na różnych platformach (czasem musiałem pracować na domowym Linuksie, czasem na Windows).</p>
<p>Przygotowanie środowiska roboczego pod Linuksem zajęło mi naprawdę niewiele czasu; szybko napisałem skrypty automatycznie pobierające bazę danych i synchronizujące pliki kodu z wersją produkcyjną. Gorzej, gdy zacząłem potrzebować możliwości modyfikacji kodu sklepu spod Windows. Muszę przyznać, że był to mój debiut w pisaniu czegokolwiek w php na tym systemie, ale w końcu postanowiłem dać mu szansę. Jako środowiska programistycznego użyłem <a href="http://www.aptana.com/">Aptana Studio</a> (choć mam wrażenie, że wystarczyłby sam <a href="http://www.eclipse.org/">Eclipse</a> z <a href="http://www.eclipse.org/pdt/">PDT</a>), a całość zamierzałem postawić na &#8211; znanym mi ze słyszenia &#8211; <a href="http://pl.wikipedia.org/wiki/WAMP">WAMP</a>ie. Instalacja WAMP odbyła się bardzo sprawnie, pierwsze <em>Hello World</em> &#8211; również bez niespodzianek. Problem jednak zaczął się po instalacji &#8211; a jakże &#8211; Zen Carta.</p>
<p>Pobrałem zrzut bazy danych i pliki z kodem sklepu i zainstalowałem je w WAMP wykorzystując do tego możliwość tworzenia aliasów.  Okazało się jednak, że instalacja ta nie działa, WAMP serwuje mi tylko komunikaty błędów, albo jakieś krzaki zamiast polskich znaków. Oto lista czynności, które musiałem wykonać, aby zacząć normalnie pracować nad zmianami dla klienta:</p>
<p><strong>Problem 1</strong> &#8211; <a href="http://www.apache.org/">Apache</a> częstuje mnie błędem <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_Server_Error">500</a> (Internal Server Error) przy jakimkolwiek odwołaniu.</p>
<p>Problem ten spowodowany był wyłączoną domyślnie obsługą <a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html">modułu rewrite</a> przez WAMPowego Apacza. Pomogła zwykła edycja <strong>httpd.conf</strong> i odkomentowanie linijki:</p>
<pre>LoadModule rewrite_module modules/mod_rewrite.so</pre>
<p>(oczywiście po tym procesie należy wyedytować odpowiednio plik <strong>.htacces</strong> &#8211; zgodnie z potrzebami i ścieżkami)</p>
<p><strong>Problem 2</strong> &#8211; Kodowanie polskich znaków bazy danych</p>
<p>Zen Cart niespecjalnie zwraca uwagę na różne możliwości kodowania znaków diakrytycznych bazy danych &#8211; na serwerze produkcyjnym była jakaś domyślna konfiguracja i taką też wgrałem u siebie. Niestety, okazało się, że WAMPowe domyślne ustawienie kodowania UTF8 pozwala na wczytanie bazy bez problemów (wpisy są dobrze widoczne z poziomu <a href="http://www.phpmyadmin.net/home_page/index.php">PhpMyAdmina</a>), jednak sam sklep wyświetla znaki zapytania zamiast polskich literek.  Tu nie obyło się bez modyfikacji kodu Zen Carta i tak  w pliku <strong>/includes/init_includes/init_database.php</strong> dodałem na końcu pliku linijki:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> HTTP_SERVER <span style="color: #339933;">==</span> <span style="color: #0000ff;">'http://localhost'</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #000088;">$db</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Execute<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SET NAMES 'latin2'  COLLATE 'latin2_general_ci'&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>i wreszcie zobaczyłem polskie znaki na moim <em>localhost</em>. Powyższy <em>ifcheck</em> wstawiłem po to, by system działał z innymi znakami tylko na konfiguracji roboczej &#8211; w wersji produkcyjnej niech zostanie bez zmian. Później i tak usunę te linijki, toteż opatrzyłem je łatwymi do odnalezienia komentarzami. Dodam, że Zen Cart jest tak napisany, że połączenie z bazą danych odbywa się w jeszcze kilku innych miejscach,  należy więc mieć na względzie potencjalną potrzebę dodania powyższych linijek do innych plików, zawierających linijkę:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$db</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>connect<span style="color: #009900;">&#40;</span> DB_SERVER<span style="color: #339933;">,</span> DB_SERVER_USERNAME<span style="color: #339933;">,</span> DB_SERVER_PASSWORD<span style="color: #339933;">,</span> DB_DATABASE<span style="color: #339933;">,</span> USE_PCONNECT<span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>Problem 3</strong> &#8211; Puste listy produktów</p>
<p>Kiedy już zażegnałem problemy &#8216;techniczne&#8217;, okazało się, że sklep działa, ale listy produktów są w nim puste. Nie dostawałem komunikatów błędów, ale mimo to strona główna zawierała jedynie boczne <em>sideboksy</em>, a w środku nic. Okazało się, że problemem tutaj był fakt, że domyślna konfiguracja php w WAMP ma wyłączoną opcję<strong> Short Tags</strong>, co powoduje, że wszelkie<em> template&#8217;y</em> zawierające znacznik otwarcia kodu php <strong>&lt;?</strong> zamiast <strong>&lt;?php</strong> nie były interpretowane przez parser php. Włączenie powyższej opcji w pliku <strong>php.ini</strong> spowodowało prawidłowe wyświetlanie produktów.</p>
<p>Po tych poprawkach i restarcie wszystkich usług WAMPa mogłem wreszcie zacząć prace nad sklepem. Wydaje mi się jednak, że &#8211; gdybym chciał oprzeć na takiej konfiguracji wersję produkcyją sklepu &#8211; musiałbym się jeszcze sporo natrudzić, by uznać to rozwiązanie za stabilne.</p>
]]></content:encoded>
			<wfw:commentRss>http://xis.schowek.net/2009/01/06/zen-cart-w-zgodzie-z-wamp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Skrypty dla MS SQL i polskie znaki</title>
		<link>http://xis.schowek.net/2007/12/12/skrypty-dla-ms-sql-i-polskie-znaki/</link>
		<comments>http://xis.schowek.net/2007/12/12/skrypty-dla-ms-sql-i-polskie-znaki/#comments</comments>
		<pubDate>Wed, 12 Dec 2007 08:21:33 +0000</pubDate>
		<dc:creator>xis</dc:creator>
				<category><![CDATA[Do zapamiętania]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Kodowanie znaków]]></category>
		<category><![CDATA[MS SQL Server]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://xis.schowek.net/2007/12/12/skrypty-dla-ms-sql-i-polskie-znaki/</guid>
		<description><![CDATA[Zawsze myślałem, że problemy dotyczące kodowania polskich znaków nie dotyczą użytkowników Windows. W końcu to taki spójny i jednolity system, posiadający nawet swój własny &#8216;standard&#8217; kodowania. Jakież było moje rozczarowanie, gdy prosty skrypt batchowy pozwalający na wczytanie skryptu SQL do bazy daanych zainstalowanej w MS SQL Server: set OSQL="c:\\Program Files\\MS SQL Server\\80\\Tools\\Binn\\osql.exe" %OSQL% -E -d [...]]]></description>
			<content:encoded><![CDATA[<p>Zawsze myślałem, że problemy dotyczące kodowania polskich znaków nie dotyczą użytkowników Windows. W końcu to taki spójny i jednolity system, posiadający nawet <a href="http://pl.wikipedia.org/wiki/Windows-1250">swój własny &#8216;standard&#8217; kodowania</a>. Jakież było moje rozczarowanie, gdy prosty <a href="http://en.wikipedia.org/wiki/.bat">skrypt batchowy</a> pozwalający na wczytanie skryptu <a href="http://pl.wikipedia.org/wiki/SQL">SQL </a>do bazy daanych zainstalowanej w <a href="http://en.wikipedia.org/wiki/Microsoft_SQL_Server">MS SQL Server</a>:</p>
<pre><code>set OSQL="c:\\Program Files\\MS SQL Server\\80\\Tools\\Binn\\osql.exe"
%OSQL% -E -d moja_baza &lt; skrypt.sql
</code></pre>
<p>&#8230;wczytał, i owszem, moje wypociny w SQL, ale&#8230; zupełnie zniekształcił polskie znaki. Dostałem w ich miejsce jakieś <a href="http://pl.wikipedia.org/wiki/Mazovia_(kod)">dziwaczne krzaki</a>, przypominające czasy źle skonfigurowanych Linuksów ;)<br />
Nie pomaga  w tej sytuacji zmiana kodowania pliku wejściowego (skrypt.sql), ani cudaczne opcje, z którymi można uruchomić &#8216;osql&#8217;.<br />
Okazuje się, że winą za ten stan rzeczy obarczać możemy&#8230; <a href="http://en.wikipedia.org/wiki/Windows_command_line">windowsowy wiersz poleceń</a>. Otóż &#8216;cmd.exe&#8217;, w środowisku którego wykonywane są wszystkie skryptu batchowe w Windows, pracuje używając innego kodowania znaków niż reszta systemu. Dlaczego? Nie mam pojęcia, pewnie ze względu na kompatybilność z <a href="http://en.wikipedia.org/wiki/MS-DOS">DOS&#8217;em</a>.<br />
Sposobem obejścia tego problemu jest rezygnacja z windowsowej możliwości <a href="http://pl.wikipedia.org/wiki/Standardowe_strumienie">przekierowania strumieni</a> na wejścia/wyjścia programów (bo to właśnie tam powstaje nieszczęsna konwersja znaków do DOS&#8217;owych krzaków). Na szczęście znalazła się w opcjach &#8216;osql&#8217; (czyli trochę jednak skłamałem pisząc kilka linijek wyżej, że &#8216;osql&#8217; nie miał pomocnej w tej sytuacji opcji ;) ) możliwość wykonania polecenia z plikiem zadanym na wejściu.<br />
Rozwiązaniem jest zapisanie skryptu w kodowaniu, którego używa MS SQL Server (u mnie <a href="http://pl.wikipedia.org/wiki/UTF-8">UTF-8</a>) i wykonanie poniższego poleconka (uprzednio oczywiście ustawiając zmienną OSQL):</p>
<pre><code>%OSQL% -E -d moja_baza -i skrypt.sql
</code></pre>
<p>Od tej pory znaki ze skryptu wędrują nienaruszone prosto do mojej bazy :)</p>
]]></content:encoded>
			<wfw:commentRss>http://xis.schowek.net/2007/12/12/skrypty-dla-ms-sql-i-polskie-znaki/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Konsola w windows? Da się!</title>
		<link>http://xis.schowek.net/2007/06/04/konsola-w-windows-da-sie/</link>
		<comments>http://xis.schowek.net/2007/06/04/konsola-w-windows-da-sie/#comments</comments>
		<pubDate>Mon, 04 Jun 2007 18:55:12 +0000</pubDate>
		<dc:creator>xis</dc:creator>
				<category><![CDATA[Do zapamiętania]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[cygwin]]></category>
		<category><![CDATA[konsole]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://xis.schowek.net/2007/06/04/konsola-w-windows-da-sie/</guid>
		<description><![CDATA[Wszyscy sympatycy np. Basha (i chyba nie tylko ci), którzy mieli kiedykolwiek do czynienia z windowsowym cmd.exe, zgodnie przyznają, że produkt z Redmond nie przyniósł rewolucji w dziedzinie obsługi wiersza poleceń. Mimo, że w windowsach linii NT sytuacja polepszyła się diametralnie, to możliwości skryptowo-konsolowe okien są wciąż, delikatnie mówiąc, marne i nawet nie umywają się do potęgi duetu Bash+Konsole. Znalazłem [...]]]></description>
			<content:encoded><![CDATA[<p><img SRC="http://xis.schowek.net/wp-content/uploads/2007/06/konsole.png" ALT="konsole.png" ALIGN="left" />Wszyscy sympatycy np. <a HREF="http://www.gnu.org/software/bash/">Basha</a> (i chyba nie tylko ci), którzy mieli kiedykolwiek do czynienia z windowsowym <em>cmd.exe</em>,  zgodnie przyznają, że produkt z Redmond nie przyniósł rewolucji w dziedzinie obsługi <a HREF="http://en.wikipedia.org/wiki/Command_line_interface">wiersza poleceń</a>. Mimo, że w <a HREF="http://en.wikipedia.org/wiki/Windows_NT">windowsach linii NT</a> sytuacja <a HREF="http://luktom.net/blog/136-ciekawe-komendy-linii-polecen-windows-xp---czesc-1">polepszyła się diametralnie</a>, to możliwości<em> skryptowo-konsolowe</em> okien są wciąż, delikatnie mówiąc, marne i nawet nie umywają się do potęgi duetu Bash+<a HREF="http://konsole.kde.org/">Konsole</a>.</p>
<p>Znalazłem jednak ostatnio kilka sposobów by sobie z tą sytuacją poradzić. Pierwszym z rozwiązań jest oczywiście <a HREF="http://www.cygwin.com/">CygWin</a>,  dzięki któremu można już cieszyć się dobrodziejstwami SH w windows. Teraz <a HREF="http://wykop.pl/link/18378/masz-dosc-cmd-exe.html">znalazłem</a> też i sam konkretny <a HREF="http://sourceforge.net/projects/console/">emulator terminala</a> &#8211; otwarty i dużo mniej toporny.<br />
Z tymi narzędziami praca w tym, niezbyt lubianym przeze mnie, systemie staje się od razu mniej męcząca :)</p>
]]></content:encoded>
			<wfw:commentRss>http://xis.schowek.net/2007/06/04/konsola-w-windows-da-sie/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>QStringList w DCOP &#8211; Firefox i Akregator razem</title>
		<link>http://xis.schowek.net/2007/05/01/qstringlist-w-dcop-firefox-i-akregator-razem/</link>
		<comments>http://xis.schowek.net/2007/05/01/qstringlist-w-dcop-firefox-i-akregator-razem/#comments</comments>
		<pubDate>Tue, 01 May 2007 07:38:36 +0000</pubDate>
		<dc:creator>xis</dc:creator>
				<category><![CDATA[Do zapamiętania]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[akregator]]></category>
		<category><![CDATA[dcop]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[kde]]></category>
		<category><![CDATA[rss]]></category>

		<guid isPermaLink="false">http://xis.schowek.net/2007/05/01/qstringlist-w-dcop-firefox-i-akregator-razem/</guid>
		<description><![CDATA[Niejeden pewnie zna zalety mechanizmu DCOP. Jeszcze więcej osób używa go z pasją nawet o tym nie wiedząc. Dzięki niemu np. możliwa jest komunikacja wielu aplikacji KDE ze sobą, a także komunikacja użytkownika z aplikacjami (np. z poziomu skryptów). Mechanizm, dzięki temu, że jest dobrem ogólnym KDE, jest niesamowicie potężny. Zwłaszcza wsadowa komenda dcop. W [...]]]></description>
			<content:encoded><![CDATA[<p><img align="left" title="Akregator" alt="Akregator" id="image27" src="http://xis.schowek.net/wp-content/uploads/2007/05/g1147.png" />Niejeden pewnie zna zalety mechanizmu <a href="http://developer.kde.org/documentation/other/dcop.html">DCOP</a>. Jeszcze więcej osób używa go z pasją nawet o tym nie wiedząc. Dzięki niemu np. możliwa jest komunikacja wielu aplikacji KDE ze sobą, a także komunikacja użytkownika z aplikacjami (np. z poziomu skryptów). Mechanizm, dzięki temu, że jest <em>dobrem ogólnym KDE</em>, jest niesamowicie potężny. Zwłaszcza wsadowa komenda <em>dcop</em>.<br />
W moim <a href="http://metamonitor.sf.net">MetaMonitorze</a> na przykład możesz &#8216;zdalnie&#8217; uruchomić okno konfiguracyjne, pokazać komunikat, zamknąć go itd. Możesz wymusić sprawdzanie poczty w <a href="http://kontact.kde.org/kmail/">KMail</a> jednym poleceniem (wpisanym np. do <a href="http://pl.wikipedia.org/wiki/Cron_(Unix)">Crona</a>), jeśli oczywiście chcesz, bo KMail ma własny mechanizm sprawdzania poczty co jakiś czas. ;) Możesz napisać skrypt, który wyświetla użytkownikowi pytanie o to czy np. chce przejść na stronę domową projektu, a gdy ten się zgodzi, wykonać:</p>
<blockquote><p>dcop konqueror KonquerorIface createNewWindow http://moja.strona.net</p></blockquote>
<p>Generalnie reklamować DCOP nie trzeba (może warto tylko dodać, że w <a href="http://en.wikipedia.org/wiki/KDE_4">KDE 4</a> będziemy mieli jeszcze lepiej za sprawą nowocześniejszego i jeszcze bardziej powszechnego <a href="http://www.freedesktop.org/wiki/Software/dbus">D-Bus</a>, który nie jest ograniczony tylko do KDE).</p>
<p>Było jednak coś, co nie pozwalało mi wykorzystywać dobrodziejstw polecenia dcop w pełni. O ile przekazywanie argumentów numerycznych było proste (wystarczy wpisać liczbę), argumentów tekstowych dość intuicyjne (stringi piszemy w apostrofach jeśli zawierają kilka słów, lub niekoniecznie z nimi, jeśli to tylko jedno słowo), o tyle przekazanie argumentu <em>QStringList</em> było dla mnie czarną magią.<br />
Jak to się robi? Kombinowałem ze wszystkimi znanymi mi sposobami i nic&#8230;</p>
<p>Dopiero <a href="http://michelle.schowek.net">Michelle</a> sprawiła, że zająłem się tym nieco konkretniej. Michelle używa <a href="http://www.mozilla-europe.org/pl/products/firefox/">Firefoksa</a>, a &#8211; jak wszyscy wiemy &#8211; jego wbudowany czytnik kanałów <a href="http://pl.wikipedia.org/wiki/RSS">RSS</a> jest, delikatnie mówiąc, dość ubogi. Więc jak tylko zaraziłem Ją <em>RSSoManią</em>, natychmiast pożałowałem, bo przygniotła mnie sterta pytań &#8216;A jak ustawić, żeby&#8230;&#8217; ;) Na pomoc przyszedł mi <a href="http://akregator.kde.org/">Akregator</a> &#8211; niesamowity czytnik. Wygodny, konfigurowalny, szybki i&#8230; <em>KDE&#8217;owy</em> :) Pozostał tylko jeden problem. Jak przekazać Akregatorowi informację o <a href="http://pl.wikipedia.org/wiki/Uniform_Resource_Locator">URL</a> kanału z poziomu Firefoksa? Na szczęście FF ma możliwość wykonania komendy z adresem kanału. No, ale tu właśnie pojawił się problem. Interfejs DCOP Akregatora pozwala wprawdzie na dodanie do niego kolejnego URL kanału RSS, jednak postać polecenia jest taka:</p>
<blockquote><p>xis@hedera ~ $ dcop akregator AkregatorIface<br />
QCStringList interfaces()<br />
QCStringList functions()<br />
void openStandardFeedList()<br />
void fetchFeedUrl(QString)<br />
void fetchAllFeeds()<br />
void saveSettings()<br />
<strong>void addFeedsToGroup(QStringList,QString)</strong><br />
void exportFile(KURL url)<br />
void addFeed()</p></blockquote>
<p>Łatwo się domyślić, że pierwszy parametr to lista URLi, a drugi to grupa, do jakiej mają być kanały dodane. I jak tę listę przekazać? Ano tak:</p>
<blockquote><p>#!/bin/bash<br />
dcop akregator AkregatorIface addFeedsToGroup [ $1 ] Michelle</p></blockquote>
<p>Taki skrypcik zapisujemy pod postacią np. &#8216;addrss&#8217;, dajemy prawa wykonania, umieszczamy gdzieć na naszej $PATH i już możemy konfigurować Firefoksa wskazując mu komendę addrss do wykonania przy dodawaniu kanału informacyjnego.</p>
<p>Działa super :)</p>
<p>Dodam tylko, że aby przekazać w QStringList większą ilość stringów, wystarczy oddzielić je przecinkami.</p>
]]></content:encoded>
			<wfw:commentRss>http://xis.schowek.net/2007/05/01/qstringlist-w-dcop-firefox-i-akregator-razem/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>KDE takie, jak chcesz</title>
		<link>http://xis.schowek.net/2007/03/30/kde-takie-jak-chcesz/</link>
		<comments>http://xis.schowek.net/2007/03/30/kde-takie-jak-chcesz/#comments</comments>
		<pubDate>Fri, 30 Mar 2007 07:36:54 +0000</pubDate>
		<dc:creator>xis</dc:creator>
				<category><![CDATA[Do zapamiętania]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[kde]]></category>

		<guid isPermaLink="false">http://xis.schowek.net/2007/03/30/kde-takie-jak-chcesz/</guid>
		<description><![CDATA[KDE to naprawdę elastyczne i konfigurowalne środowisko. Wielu na nie narzeka, bo &#8216;ciężkie&#8217;, &#8216;wolne&#8217;, bo &#8216;przeciążone wodotryskami&#8217;, ale chyba każdy, kto go używał przyzna, że trudno o bardziej wygodne w kwestii dopasowania do potrzeb użytkownika środowisko graficzne. Jeśli jednak wszystkie te edytory i wizardy to dla Ciebie za mało &#8211; zerknij na Wiki KDE, by [...]]]></description>
			<content:encoded><![CDATA[<p align="left"><img style="border: 1px solid white; display: block; float: left" alt="images1.jpeg" id="image20" src="http://xis.schowek.net/wp-content/uploads/2007/03/images1.jpeg" /><a href="http://kde.org">KDE</a> to naprawdę elastyczne i konfigurowalne środowisko. Wielu na nie narzeka, bo &#8216;ciężkie&#8217;, &#8216;wolne&#8217;, bo &#8216;przeciążone wodotryskami&#8217;, ale chyba każdy, kto go używał przyzna, że trudno o bardziej wygodne w kwestii <em>dopasowania do potrzeb użytkownika</em> środowisko graficzne.</p>
<div align="center">
<p align="left">
<p align="left">
<p align="left">
<p align="left">Jeśli jednak wszystkie te edytory i wizardy to dla Ciebie za mało &#8211; zerknij na <a href="http://wiki.kde.org/">Wiki</a> KDE, by poczytać o jego <a href="http://wiki.kde.org/tiki-index.php?page=Hidden%20configuration">ukrytych opcjach konfiguracji</a>.</p>
<div align="center">
<p align="left">Mi najbardziej podoba się możliwość <a href="http://wiki.kde.org/tiki-index.php?page=Hidden%20configuration#Disabling_Category_Titles_in_K_Menu">wyłączenia podziału na kategorie w KMenu</a>, oraz szereg usprawnień dla <a href="http://www.konqueror.org/">Konquerora</a> w zarządzaniu kartami.</p>
<div align="center">
<p align="left">Jeszcze kilka  informacji o wyciskaniu <em>dwustu procent normy</em> z KDE <a href="http://canllaith.org/?page_id=15">tutaj</a>.</p>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xis.schowek.net/2007/03/30/kde-takie-jak-chcesz/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Obrazki w PHP i .htaccess</title>
		<link>http://xis.schowek.net/2007/02/02/obrazki-w-php-i-htaccess/</link>
		<comments>http://xis.schowek.net/2007/02/02/obrazki-w-php-i-htaccess/#comments</comments>
		<pubDate>Fri, 02 Feb 2007 11:18:41 +0000</pubDate>
		<dc:creator>xis</dc:creator>
				<category><![CDATA[Do zapamiętania]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://xis.schowek.net/2007/02/02/obrazki-w-php-i-htaccess/</guid>
		<description><![CDATA[Napisałem kiedyś skrypcik, w PHP, który generował dla mnie losowe obrazki na zawołanie. Pomysł nie mój, dość oklepany, ale wykonanie było moje. :) Używałem go do wszelkich avatarów, sygnaturek i wszystko byłoby pięknie, gdyby nie jego rozszerzenie &#8211; php. Większość forów internetowych &#8211; ze względów bezpieczeństwa &#8211; nie zezwala na umieszczanie w avatarze, czy sygnaturce [...]]]></description>
			<content:encoded><![CDATA[<p>Napisałem kiedyś <a href="http://schowek.net/stuff/ee.php">skrypcik</a>, w <a href="http://php.net">PHP</a>, który generował dla mnie losowe obrazki na zawołanie. Pomysł nie mój, dość oklepany, ale wykonanie było moje. :) Używałem go do wszelkich avatarów, sygnaturek i wszystko byłoby pięknie, gdyby nie jego rozszerzenie &#8211; php.</p>
<p>Większość forów internetowych &#8211; ze względów bezpieczeństwa &#8211; nie zezwala na umieszczanie w avatarze, czy sygnaturce obrazka z rozszerzeniem &#8216;php&#8217;, i nic w tym dziwnego.<br />
Ze względu na to, że serwer, na którym trzymam skrypt nie daje mi możliwości modyfikacji konfiguracji (nie mogę przekonfigurować <a href="http://apache.org/">apacza</a>, by &#8216;interpretował&#8217; np. pliki o rozszerzeniu &#8216;png&#8217; jak skrypty php) nie mogę po prostu zmienić rozszerzenia pliku z kodem skryptu.<br />
Pomocna okazała się technologia <a href="http://httpd.apache.org/docs/1.3/howto/htaccess.html">.htaccess</a>. Jesli serwer wspiera ten mechanizm, wystarczy w katalogu, w którym znajduje się skrypt umieścić pliczek <em>.htaccess</em>, a w nim:</p>
<blockquote><p>Options +FollowSymlinks<br />
RewriteEngine on<br />
RewriteRule ^ja.png$ ee.php [nc]</p></blockquote>
<p>Od tej pory mogę wskazywać na mój skrypt adresem <a href="http://schowek.net/stuff/ja.png">http://schowek.net/stuff/ja.png</a>. Więcej o samym .htaccess <a href="http://corz.org/serv/tricks/htaccess.php">tutaj</a> i <a href="http://corz.org/serv/tricks/htaccess2.php">tutaj</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://xis.schowek.net/2007/02/02/obrazki-w-php-i-htaccess/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ładny OpenOffice.org</title>
		<link>http://xis.schowek.net/2007/01/20/ladny-openofficeorg/</link>
		<comments>http://xis.schowek.net/2007/01/20/ladny-openofficeorg/#comments</comments>
		<pubDate>Sat, 20 Jan 2007 18:08:46 +0000</pubDate>
		<dc:creator>xis</dc:creator>
				<category><![CDATA[Do zapamiętania]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[czcionki]]></category>
		<category><![CDATA[open office]]></category>

		<guid isPermaLink="false">http://xis.schowek.net/2007/01/20/ladny-openofficeorg/</guid>
		<description><![CDATA[Po ostatnich zabawach z fontami stwierdzam z zadowoleniem, że praca na moim ślicznym desktopie stała się dużo przyjemniejsza. Dzięki zastosowaniu QtCurve &#8211; jednolitego motywu widgetów, aplikacje Qt/KDE oraz GTK mają podobny jednolity wygląd. Jedynymi &#8216;czarnymi owcami&#8217; w tym okienkowym stadzie były aplikacje wchodzące w skład pakietu OpenOffice.org. Interfejs pakietu biurowego &#8211; mimo, że zainstalowany z [...]]]></description>
			<content:encoded><![CDATA[<p>Po ostatnich <a href="http://xis.schowek.net/2007/01/18/linuksowe-literki/">zabawach z fontami</a> stwierdzam z zadowoleniem, że praca na moim ślicznym desktopie stała się dużo przyjemniejsza. Dzięki zastosowaniu<em> </em><a href="http://www.kde-look.org/content/show.php?content=40492">QtCurve</a> &#8211; jednolitego motywu <em>widgetów</em>, aplikacje<a href="http://www.trolltech.com/products/qt"> Qt</a>/KDE oraz <a href="http://gtk.org/">GTK</a> mają podobny jednolity wygląd. Jedynymi &#8216;czarnymi owcami&#8217; w tym okienkowym stadzie były aplikacje wchodzące w skład pakietu <a href="http://www.openoffice.org/">OpenOffice.org</a>.<br />
Interfejs pakietu biurowego &#8211; mimo, że zainstalowany z opcją <em>USE=&#8221;kde gtk&#8221;</em> &#8211; sprawiał wrażenie zupełnie niewrażliwego na ustawienia mojego pulpitu. Szybko <a href="http://www.openoffice.org/FAQs/fontguide.html#9">znalazłem</a> sposób, w jaki uporałem się z tym problemem. Wystarczy wybrać z menu np. <em>Writera</em>:</p>
<blockquote><p>Narzędzia -> Opcje -> OpenOffice.org -> Czcionki</p></blockquote>
<p>Następnie zaznaczyć checkbox <em>Zastosuj tabelę zmian</em>, a w poniższej tabeli wprowadzić zmianę czcionki<em>  Andale Sans UI</em> na np. <em>Arial</em>. Ważne jest, żeby wprowadzić nazwę czcionki Andale Sans UI nawet jeśli nie było jej na liście czcionek.</p>
<p>Po tej operacji wszystkie aplikacje OpenOffice.org będą już wyglądały tak ładnie jak inne aplikacje naszego pulpitu :)</p>
<div class="gallery"><img id="image13" alt="oo_good.png" src="http://xis.schowek.net/wp-content/uploads/2007/01/oo_bad.png" />Writer przed liftingiem</div>
<div class="gallery"><img id="image12" alt="oo_bad.png" src="http://xis.schowek.net/wp-content/uploads/2007/01/oo_good.png" />Writer po liftingu</div>
<p>Przy okazji warto też wyłączyć antialiasing czcionek edytowanych dokumentów; z</p>
<blockquote><p>Narzędzia -> Opcje -> OpenOffice.org -> Widok</p></blockquote>
<p>odznaczyć checkbox <em>Wygładzanie czcionek ekranowych</em> (lub ustawić dolny pułap wygładzania na np. 18 pikseli). Operacja ta sprawia, że praca z dokumentami staje się wygodniejsza, bo Writer działa dużo szybciej nie &#8216;tracąc&#8217; czasu na wygładzanie czcionek.</p>
]]></content:encoded>
			<wfw:commentRss>http://xis.schowek.net/2007/01/20/ladny-openofficeorg/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Linuksowe literki</title>
		<link>http://xis.schowek.net/2007/01/18/linuksowe-literki/</link>
		<comments>http://xis.schowek.net/2007/01/18/linuksowe-literki/#comments</comments>
		<pubDate>Thu, 18 Jan 2007 18:36:51 +0000</pubDate>
		<dc:creator>xis</dc:creator>
				<category><![CDATA[Do zapamiętania]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[czcionki]]></category>

		<guid isPermaLink="false">http://xis.schowek.net/2007/01/18/linuksowe-literki/</guid>
		<description><![CDATA[W Linuksie denerwuje mnie naprawdę niewiele rzeczy. Ale, jeśli już coś mnie wkurza, to naprawdę bardzo mocno. Jedną z takich rzeczy są, albo właściwie były, czcionki systemowe. Kiedyś bardzo drażnił nierówny hinting czcionek i tak np. w Fedorze czcionki wyglądały bardzo ładnie, byly równe i gładkie, podczas gdy np. w Gentoo domyślne fonty były dziwnie [...]]]></description>
			<content:encoded><![CDATA[<p>W Linuksie denerwuje mnie naprawdę niewiele rzeczy. Ale, jeśli już coś mnie wkurza, to naprawdę bardzo mocno. Jedną z takich rzeczy są, albo właściwie były, czcionki systemowe.</p>
<p>Kiedyś bardzo drażnił nierówny <em>hinting</em> czcionek i tak np. w <a target="_blank" href="http://fedora.redhat.com/">Fedorze</a> czcionki wyglądały bardzo ładnie, byly równe i gładkie, podczas gdy np. w <a target="_blank" href="http://www.gentoo.org/">Gentoo</a> domyślne fonty były dziwnie koślawe. Pomocna wtedy okazywała się <a href="http://www.cs.mcgill.ca/~dchest/xfthack/">łatka do Xft</a>, która sprawiała, że hinting fontów był dużo równiejszy. Dziś łatka ta jest niepotrzebna, bo chyba wszystkie wersje <a href="http://x.org/">Xorg</a> stosują poprawny hinting czcionek. Mój linuksowy desktop wyglądał istnie jak <a href="http://www.apple.com/macosx/">Macintosh</a>. Oczywiście całej sprawie ukryty był pewien haczyk &#8211; fonty były ładne, ale pod warunkiem używania antialiasingu. Kiedy tylko wyłączałem wygładzanie, mój ekran wypełniała cała banda koślawych i poszarpanych liter. Nie przeszkadzało mi to dopóki uzywałem monitora CRT, ale  zaczęło denerwować gdy kupiłem matrycę LCD. Czcionki wygładzane nie podobały mi się zbytnio na nowym monitorze, dlatego zdecydowałem się używać wszędzie czcionek <em>Helvetica</em> firmy <a href="http://www.adobe.com">Adobe</a>, co pozwoliło mi na wyłączenie antialiasingu. Było jednak coś, co strasznie mnie drażniło &#8211; pytanie &#8216;Jak to jest, że w Windows wszystkie czcionki  tak ładnie wyglądają, a moje <a href="http://kde.org/">KDE</a> jest <em>skazane</em> na Helveticę?&#8217;. Udało mi się jednak zaradzić i temu problemowi. Mimo, że  <a href="http://www.theregister.co.uk/2002/10/25/fabulous_fonts_in_linux/">artykuł</a>, który znalazłem w Sieci jest dość leciwy, jego treść i rady, jakie niesie są wciąż aktualne. Po zastosowaniu się do rad autora i zrekompilowaniu pakietu <a href="http://www.freetype.org/">freetype</a> mogę cieszyć się równymi czcionkami czy to z antialiasingiem, czy bez niego. Ponadto, postanowiłem skorzystać z opcji włączania antialiasingu przy czcionkach większych niż 10 pikseli, dzięki  czemu teraz wygładzane są tylko te duże czcionki (np. nagłówki stron WWW).</p>
<p>Przy okazji poruszania tematu czcionek załączam plik z bitmapowym fontem <em><a href="http://xis.schowek.net/wp-content/uploads/2007/01/console8x16pcf.zip">Console</a></em>, dzięki któremu mój emulator terminala wygląda naprawdę fajnie (używam go też w edytorach tekstowych).</p>
]]></content:encoded>
			<wfw:commentRss>http://xis.schowek.net/2007/01/18/linuksowe-literki/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

