<?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/"
	>

<channel>
	<title>Undercode</title>
	<atom:link href="http://www.virgo.hu/undercode/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.virgo.hu/undercode</link>
	<description>Virgo Systems Kft. blogja</description>
	<pubDate>Mon, 25 May 2009 11:05:06 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Változások az OpenSocial alapú fejlesztésben</title>
		<link>http://www.virgo.hu/undercode/2009/05/valtozasok-az-opensocial-alapu-fejlesztesben/</link>
		<comments>http://www.virgo.hu/undercode/2009/05/valtozasok-az-opensocial-alapu-fejlesztesben/#comments</comments>
		<pubDate>Mon, 25 May 2009 11:05:06 +0000</pubDate>
		<dc:creator>Bányai Zsolt</dc:creator>
		
		<category><![CDATA[Nincs kategorizálva]]></category>

		<category><![CDATA[data pipelining]]></category>

		<category><![CDATA[iwiw]]></category>

		<category><![CDATA[opensocial-0.9]]></category>

		<category><![CDATA[templating]]></category>

		<guid isPermaLink="false">http://www.virgo.hu/undercode/?p=44</guid>
		<description><![CDATA[Az OpenSocial fejlesztésekkel kapcsolatban több fejlesztő is nehezményezte, hogy körülményes a kialakított, JavaScript központú fejlesztés és ez nagyban nehezíti alkalmazásaik hatékony fejlesztését. Az OpenSocial 0.9-es szabvány erre próbál megoldásokat adni, amit ha jobban áttekintünk, akkor valóban sok-sok fejlesztő életét megkönnyítő megoldást találunk.
Mik is ezek az újdonságok:

Data Pipelinening
továbbfejlesztett OpenSocial Templating
OSML - OpenSocial Markup Language


Nézzünk is pár [...]]]></description>
			<content:encoded><![CDATA[<p>Az OpenSocial fejlesztésekkel kapcsolatban több fejlesztő is nehezményezte, hogy körülményes a kialakított, JavaScript központú fejlesztés és ez nagyban nehezíti alkalmazásaik hatékony fejlesztését. Az OpenSocial 0.9-es szabvány erre próbál megoldásokat adni, amit ha jobban áttekintünk, akkor valóban sok-sok fejlesztő életét megkönnyítő megoldást találunk.</p>
<p>Mik is ezek az újdonságok:</p>
<ul>
<li>Data Pipelinening</li>
<li>továbbfejlesztett OpenSocial Templating</li>
<li>OSML - OpenSocial Markup Language</li>
</ul>
<p><span id="more-44"></span></p>
<p>Nézzünk is pár példát, hogy miben egyszerűsödik az életünk:<br />
<br />
<strong>Proxied Content</strong></p>
<p>Sokan nem szerették, hogy a gadget.xml hordozza magában az alkalmazás alap megjelenését (különböző view-k html fragmentjét). Mostantól azonban lehetőség van arra, hogy az OpenSocial konténert egyszerűen, proxy megoldással emelje be ezeket a tartalmakat is:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Content</span> <span style="color: #000066;">view</span>=<span style="color: #ff0000;">&quot;canvas&quot;</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;http://myserver/canvas&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Content<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Itt annyi történik, hogy a CANVAS nézet meghívásakor a gadget szerver a http://myserver/canvas címen található html-t tölti be, ami természetesen továbbra is keresztül megy a gadget szerver rewrite/cache/stb. mechanizmusain. Ezzel még sokat nem nyertünk, egyedül a fejlesztésünk hatékonyságán javítottunk kicsit. Azonban csavarjunk a dolgon egy kicsit:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Content</span> <span style="color: #000066;">view</span>=<span style="color: #ff0000;">&quot;canvas&quot;</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;http://myserver/canvas&quot;</span> <span style="color: #000066;">authz</span>=<span style="color: #ff0000;">&quot;signed&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Content<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Ezzel a kóddal egy apró csavart raktunk a kiszolgálási mechanizmusba, miszerint a http://myserver/canvas meghívása SignedRequest módon történik, tehát a saját kódunk már pontos információkkal rendelkezik az <strong>@owner</strong> és <strong>@viewer</strong> azonosítóiról.<br />
<i>Természetesen itt egy dologra figyelnünk kell, ahogy SignedRequest módba váltunk kiütjük az OpenSocial container cache megoldásait, tehát itt már bírnunk kell szerveroldalon a felhasználók által jövő lekérdezéseket!</i></p>
<p><strong>Data Pipelinening</strong><br />
Az OpenSocial két féle lehetőséget biztosít nekünk az adott konténer social api-jának elérésére, az egyik a felhasználók böngészőjén keresztül egyszeráen elérhető rpc protokol, a másik pedig a szerveroldali restful interfész (utóbbi az iWiW-en belül egyelőre nem hozzáférhető). A böngészőben futó rpc hívásoknak sok hátránya van, sok esetben a felhasználónak az akár elég lassú internetkapcsolatán keresztül kell nagy adatokat megmozgatni a gadget betöltődése után. Azonban mostantól lehetőség van arra, hogy a felhasználó a renderelt gadgetet már a social adatokkal együtt kaphassa meg.<br/><br />
Nézzük is a példát:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span> <span style="font-weight: bold; color: black;">?&gt;</span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Module<span style="font-weight: bold; color: black;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;ModulePrefs</span> <span style="color: #000066;">title</span>=<span style="color: #ff0000;">&quot;OpenSocial 0.9 Teszt&quot;</span>
                <span style="color: #000066;">title_url</span>=<span style="color: #ff0000;">&quot;http://myserver&quot;</span>
                <span style="color: #000066;">author</span>=<span style="color: #ff0000;">&quot;Bányai Zsolt [bazso]&quot;</span>
                <span style="color: #000066;">author_email</span>=<span style="color: #ff0000;">&quot;banyai.zsolt@virgo.hu&quot;</span>
                <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;Teszteljük az ópenszósölt!&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
                <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Require</span> <span style="color: #000066;">feature</span>=<span style="color: #ff0000;">&quot;opensocial-0.9&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span>
                <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Require</span> <span style="color: #000066;">feature</span>=<span style="color: #ff0000;">&quot;opensocial-data&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/ModulePrefs<span style="font-weight: bold; color: black;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Content</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;html&quot;</span> <span style="color: #000066;">view</span>=<span style="color: #ff0000;">&quot;canvas&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #339933;">&lt;![CDATA[</span>
<span style="color: #339933;">           &lt;script xmlns:os=&quot;http://ns.opensocial.org/2008/markup&quot; type=&quot;text/os-data&quot;&gt;</span>
<span style="color: #339933;">              &lt;os:PeopleRequest key=&quot;vf&quot; userId=&quot;@viewer&quot; groupId=&quot;@friends&quot;/&gt;</span>
<span style="color: #339933;">              &lt;os:ViewerRequest key=&quot;viewer&quot;/&gt;</span>
<span style="color: #339933;">           &lt;/script&gt;</span>
<span style="color: #339933;">        ]]&gt;</span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Content<span style="font-weight: bold; color: black;">&gt;</span></span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Module<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Mi történt itt? Először is a <i>&lt;Require feature=&#8221;opensocial-data&#8221;/&gt;</i> sorral jeleztük, hogy használni szeretnénk az OpenSocial Data Pipelining megoldását. A Gadget szerver a renderelési fázisban látja, hogy két adatlekérdezést is szeretnénk (viewer ismerőseinek lekérdezése, valamint magának a viewernek a lekérdezése), ezeket megfuttatja az API szervereken és az eredmény elérhetővé válik a renderelt gadget html kódjában:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="javascript"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>opensocial.<span style="color: #006600;">data</span>.<span style="color: #006600;">DataContext</span>.<span style="color: #006600;">putDataSet</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;viewer&quot;</span><span style="color: #339933;">,</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;hasApp&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;thumbnailUrl&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;http://approval.iwiw.hu/rest/person/HkVD909RD.jpg&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;formatted&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Bányai Zsolt&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;givenName&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Zsolt&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;familyName&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Bányai&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;profileUrl&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;http://approval.iwiw.hu/rest/person/HkVD909RD.html&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;isOwner&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;approval.iwiw.hu:HkVD909RD&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;isViewer&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;displayName&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Bányai Zsolt&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>opensocial.<span style="color: #006600;">data</span>.<span style="color: #006600;">DataContext</span>.<span style="color: #006600;">putDataSet</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;vf&quot;</span><span style="color: #339933;">,</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;list&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;hasApp&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;thumbnailUrl&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;http://approval.iwiw.hu/rest/person/m8VhWkg8.jpg&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;formatted&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;iWiW Root User&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;givenName&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;User&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;familyName&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;iWiW Root&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;profileUrl&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;http://approval.iwiw.hu/rest/person/m8VhWkg8.html&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;approval.iwiw.hu:m8VhWkg8&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;displayName&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;iWiW Root User&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;hasApp&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;thumbnailUrl&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;http://approval.iwiw.hu/rest/person/4pVS21R42.jpg&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;formatted&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Elfogadó Dezső&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;givenName&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Dezső&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;familyName&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Elfogadó&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;profileUrl&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;http://approval.iwiw.hu/rest/person/4pVS21R42.html&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;approval.iwiw.hu:4pVS21R42&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;displayName&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Elfogadó Dezső&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;startIndex&quot;</span><span style="color: #339933;">:</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;totalResults&quot;</span><span style="color: #339933;">:</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Elsőre ugye nem szép, azonban felettébb hasznos megoldás, hiszen nincs szükségünk már kliens oldali hívásokra, ezek az információk azonna elérhetőek JavaScript segítségével:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="javascript"><span style="color: #003366; font-weight: bold;">var</span> viewer <span style="color: #339933;">=</span> opensocial.<span style="color: #006600;">data</span>.<span style="color: #006600;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006600;">getDataSet</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'viewer'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> viewerFriends <span style="color: #339933;">=</span> opensocial.<span style="color: #006600;">data</span>.<span style="color: #006600;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006600;">getDataSet</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'vf'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p><br/><br />
<strong>OpenSocial Templating</strong><br />
Az előző példa elég meggyőző, azonban a fejlesztő még mindig nem szabadulhat a JavaScript mágiától. Ebben segítség az OpenSocal Templating, amely szerver és kliens oldalon egyaránt futtatható template lehetőséget biztosít, akár saját magunk által definiált template-ekkel. <br/><br />
Kicsit egészítsük ki az előző példát, és rögtön megvilágosodhatunk:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span> <span style="font-weight: bold; color: black;">?&gt;</span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Module<span style="font-weight: bold; color: black;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;ModulePrefs</span> <span style="color: #000066;">title</span>=<span style="color: #ff0000;">&quot;OpenSocial 0.9 Teszt&quot;</span>
                <span style="color: #000066;">title_url</span>=<span style="color: #ff0000;">&quot;http://myserver&quot;</span>
                <span style="color: #000066;">author</span>=<span style="color: #ff0000;">&quot;Bányai Zsolt [bazso]&quot;</span>
                <span style="color: #000066;">author_email</span>=<span style="color: #ff0000;">&quot;banyai.zsolt@virgo.hu&quot;</span>
                <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;Teszteljük az ópenszósölt!&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
                <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Require</span> <span style="color: #000066;">feature</span>=<span style="color: #ff0000;">&quot;opensocial-0.9&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span>
                <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Require</span> <span style="color: #000066;">feature</span>=<span style="color: #ff0000;">&quot;opensocial-data&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span>
                <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Require</span> <span style="color: #000066;">feature</span>=<span style="color: #ff0000;">&quot;opensocial-templates&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/ModulePrefs<span style="font-weight: bold; color: black;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Content</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;html&quot;</span> <span style="color: #000066;">view</span>=<span style="color: #ff0000;">&quot;canvas&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #339933;">&lt;![CDATA[</span>
<span style="color: #339933;">           &lt;script xmlns:os=&quot;http://ns.opensocial.org/2008/markup&quot; type=&quot;text/os-data&quot;&gt;</span>
<span style="color: #339933;">              &lt;os:PeopleRequest key=&quot;vf&quot; userId=&quot;@viewer&quot; groupId=&quot;@friends&quot;/&gt;</span>
<span style="color: #339933;">              &lt;os:ViewerRequest key=&quot;viewer&quot;/&gt;</span>
<span style="color: #339933;">           &lt;/script&gt;</span>
<span style="color: #339933;">           &lt;script type=&quot;text/os-template&quot;&gt;</span>
<span style="color: #339933;">               &lt;strong&gt;${viewer.name.formatted} ismerősei:&lt;/strong&gt;</span>
<span style="color: #339933;">               &lt;ul&gt;</span>
<span style="color: #339933;">                  &lt;li repeat=&quot;${vf}&quot;&gt;${name.formatted}&lt;/li&gt;</span>
<span style="color: #339933;">               &lt;/ul&gt;</span>
<span style="color: #339933;">           &lt;/script&gt;</span>
<span style="color: #339933;">        ]]&gt;</span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Content<span style="font-weight: bold; color: black;">&gt;</span></span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Module<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre></td></tr></table></div>

<p>A példában nem tettünk mást, mint a gadget szerverrel szerver oldalon futtattatunk egy egyszerű template-et, amely segítségével a már előzőekben elérhető adatokat JavaScript mutyizás nélkül szépen html formában megjeleníthetjük, a következő eredményt kapva a renderelt gadgetünkben:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre>&lt;strong&gt;Bányai Zsolt ismerősei:&lt;/strong&gt;
&lt;ul&gt;
   &lt;li&gt;iWiW Root User&lt;/li&gt;
   &lt;li&gt;Elfogadó Dezső&lt;/li&gt;
&lt;/ul&gt;</pre></td></tr></table></div>

<p><strong>Egy kis nyalánkság</strong><br />
Bár eddig csak ízelítőt kaphattunk az újdonságokból, azért egy dolgot még körbejárunk. Sokszor előfordul, hogy a felhasználónak a kapcsolati hálója alapján szűrve szeretnénk tartalmat visszaadni, de körülményes dolog megjáratni az adatokat a böngésző és a szerverek között. Ehhez a fenti példákat kicsit összemixelve kapunk egy nagyon hasznos megoldást. Csapjunk rögtön a lovak közé:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Content</span> <span style="color: #000066;">view</span>=<span style="color: #ff0000;">&quot;canvas&quot;</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;http://myserver/canvas&quot;</span> <span style="color: #000066;">authz</span>=<span style="color: #ff0000;">&quot;signed&quot;</span>  <span style="color: #000066;">xmlns:os</span>=<span style="color: #ff0000;">&quot;http://ns.opensocial.org/2008/markup&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
   <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;os:PeopleRequest</span> <span style="color: #000066;">key</span>=<span style="color: #ff0000;">&quot;vf&quot;</span> <span style="color: #000066;">userId</span>=<span style="color: #ff0000;">&quot;@viewer&quot;</span> <span style="color: #000066;">groupId</span>=<span style="color: #ff0000;">&quot;@friends&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Content<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre></td></tr></table></div>

<p>No, lássuk mire megyünk ezzel a bűvészkedéssel. Külön-külön már tudjuk értelmezni ezeket a sorokat, azaz látjuk, hogy egyszer a gadget szerver SignedRequest alkalmazásával bekéri saját szerverünktől a gadget html tartalmát, valamint az is tudjuk, hogy az os:PeopleRequest előkészíti nekünk a @viewer ismerőseit. De hogy ér össze a kettő, merül fel a kérdés&#8230; Jelen esetben a sorrend megfordul, a gadget szerver lekérdezi a @viewer ismerőseit, majd az eredményt POST-olja a canvas nézet megjelenítéséért felelős oldalunknak, ráadásul úgy, hogy közben megbizonyosodhatunk a SignedRequest segítségével arról is, hogy valóban az iWiW-től érkezett a kérés. Íme az egyszerű szerveroldali php kód - a SignedRequest feldolgozása nélkül -, amely segítségével már dolgozhatjuk is fel az adatokat:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php"><span style="color: #000033;">$data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;php://input&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #000033;">$my</span> <span style="color: #339933;">=</span> json_decode<span style="color: #009900;">&#40;</span><span style="color: #000033;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000033;">$my</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">list</span> <span style="color: #b1b100;">as</span> <span style="color: #000033;">$d</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #990000;">print</span> <span style="color: #000033;">$d</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">formatted</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;&lt;br /&gt;&quot;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>Konklúzió</strong><br />
Látszódik, hogy az OpenSocial szabvány keresi azokat az utakat, amelyek segítségével a fejlesztők számára kényelmesebbé és JavaScript-függetlenebbé válhat a fejlesztés, ezzel igyekezve felzárkózni a Facebook sokak által kényelmesebbnek ítélt platformja mögé.<br />
Aki a fentiekről bővebben akar tájékozódni, az olvasgassa a <a href="http://opensocial.org">http://opensocial.org</a> oldalain található dokumentációkat, aki pedig arra kíváncsi, hogy az újdonságok mikor és milyen formában lesznek az iWiW-en is elérhetőek, az kövesse <a href="http://twitter.com/iwiwdev">@iwiwdevet</a>,  valamint kísérje figyelemmel az <a href="http://dev.iwiw.hu/blog">iWiW Fejlesztői Blogot</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.virgo.hu/undercode/2009/05/valtozasok-az-opensocial-alapu-fejlesztesben/feed/</wfw:commentRss>
		</item>
		<item>
		<title>HTML és CSS szerkesztés gyorsan és szépen</title>
		<link>http://www.virgo.hu/undercode/2009/02/html-es-css-szerkesztes-gyorsan-es-szepen/</link>
		<comments>http://www.virgo.hu/undercode/2009/02/html-es-css-szerkesztes-gyorsan-es-szepen/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 18:00:03 +0000</pubDate>
		<dc:creator>Bácsi László</dc:creator>
		
		<category><![CDATA[Nincs kategorizálva]]></category>

		<category><![CDATA[Compass]]></category>

		<category><![CDATA[Haml]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Sass]]></category>

		<category><![CDATA[slides]]></category>

		<category><![CDATA[view]]></category>

		<guid isPermaLink="false">http://www.virgo.hu/undercode/?p=37</guid>
		<description><![CDATA[A fejlesztések során igyekszünk olyan eszközökkel dolgozni, amelyek növelik a hatékonyságunkat és a kód karbantarthatóságát is. Ez az egyik oka annak, hogy tavaly felvettük az eszköztárunkba a Rubyt és vele együtt a Rails keretrendszert. Azóta már több projektet átadtunk amelyek ezeket a technológiákat használják. A nagyobb dolgok mellett azonban szükséges néha az alacsonyabb szinteken is [...]]]></description>
			<content:encoded><![CDATA[<p>A fejlesztések során igyekszünk olyan eszközökkel dolgozni, amelyek növelik a hatékonyságunkat és a kód karbantarthatóságát is. Ez az egyik oka annak, hogy tavaly felvettük az eszköztárunkba a Rubyt és vele együtt a Rails keretrendszert. Azóta már több projektet átadtunk amelyek ezeket a technológiákat használják. A nagyobb dolgok mellett azonban szükséges néha az alacsonyabb szinteken is nagytakarítást végezni, és megtalálni minden összetevőből a legmegfelelőbbet.</p>
<p>Idén a kliens oldali fejlesztés megkönnyítéséhez sikerült két ilyen összetevőt találni. Ezekből az egyik a <a href="http://haml.hamptoncatlin.com/docs/rdoc/classes/Haml.html">Haml</a>, amely egy indentáláson alapuló HTML és XML kód generálására használható nyelv. A másik pedig ennek a párja a <a href="http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html">Sass</a>, amely hasonlóan CSS kód generálására használható. Mindkettőnek egyik nagy előnye a sima HTML/CSS illetve a HTML-hez Ruby világban hagyományosan használt ERB-vel szemben, hogy sokkal kevesebb a kódban a sallang és az ismétlődés (<a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a>). Emelett persze sok további előnnyel rendelkeznek. Haml esetében a szép kimenetet és a filterekkel való kiterjeszthetőséget emelném ki, Sass esetében pedig a konstansok és egyszerű műveletek használatát, illetve a css mixineket.</p>
<p>A Sass oldalhoz még a <a href="http://wiki.github.com/chriseppstein/compass/">Compass</a> keretrendszert is bevetettük, ami sok hasznos mixint definiál nekünk előre illetve a népszerűbb CSS frameworkökhöz (YUI, Blueprint, stb.) is ad rugalmasan használható Sass átiratot.</p>
<p><strong>Próbáljátok ki, nekünk bevált!</strong> Ha esetleg mélyebben érdekelnek az előnyök, és hogy mi hogyan működik, akkor ajánlom figyelmedbe a bevezetés előtt tartott belső traininghez készült előadás slidejaimat:</p>
<div style="width:425px;text-align:center;margin:0 auto;" id="__ss_902000"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/LacKac/haml-sass-compass-presentation?type=powerpoint" title="Haml, Sass &amp; Compass">Haml, Sass &amp; Compass</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=haml-sass-compass-1231444200327329-1&#038;stripped_title=haml-sass-compass-presentation" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=haml-sass-compass-1231444200327329-1&#038;stripped_title=haml-sass-compass-presentation" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
]]></content:encoded>
			<wfw:commentRss>http://www.virgo.hu/undercode/2009/02/html-es-css-szerkesztes-gyorsan-es-szepen/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Gadgetfejlesztés Rubyval: gadgeteer</title>
		<link>http://www.virgo.hu/undercode/2009/01/gadgetfejlesztes-rubyval-gadgeteer/</link>
		<comments>http://www.virgo.hu/undercode/2009/01/gadgetfejlesztes-rubyval-gadgeteer/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 09:41:18 +0000</pubDate>
		<dc:creator>Bácsi László</dc:creator>
		
		<category><![CDATA[Nincs kategorizálva]]></category>

		<category><![CDATA[gadgeteer]]></category>

		<category><![CDATA[oauth]]></category>

		<category><![CDATA[OpenSocial]]></category>

		<category><![CDATA[opensource]]></category>

		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.virgo.hu/undercode/?p=20</guid>
		<description><![CDATA[OpenSocial gadget fejlesztésénél előfordulhat, hogy a kisalkalmazásunkból egy háttéralkalmazással kell kommunikálnunk. Erre nagyon jó módszereket nyújt a platform, és így az egész fejlesztési folyamat olyan lesz, mint egy jól megtámogatott AJAX intenzív webalkalmazás-fejlesztés. A backend oldalra a platform rugalmassága és a gyors fejlesztés miatt kiválóan alkalmas valamilyen rubys webframework. Az alábbiakban bemutatok pár eszközt, amit [...]]]></description>
			<content:encoded><![CDATA[<p>OpenSocial gadget fejlesztésénél előfordulhat, hogy a kisalkalmazásunkból egy háttéralkalmazással kell kommunikálnunk. Erre nagyon jó módszereket nyújt a platform, és így az egész fejlesztési folyamat olyan lesz, mint egy jól megtámogatott AJAX intenzív webalkalmazás-fejlesztés. A backend oldalra a platform rugalmassága és a gyors fejlesztés miatt kiválóan alkalmas valamilyen rubys webframework. Az alábbiakban bemutatok pár eszközt, amit felhasználhatunk a backend fejlesztés során. Többek közt egy Virgos fejlesztésű Rails plugint is nyílttá teszünk, ami leegyszerűsít néhány dolgot.</p>
<p><span id="more-20"></span></p>
<h4>Backend elérés</h4>
<p>A backend oldallal való kommunikációra a <tt>gadgets.io.makeRequest</tt> függvény ad lehetőséget. Ez alapvetően egy proxyzott cross-domain ajax requestként működik, ahol kérhetjük azt is, hogy a kérés alá legyen írva. A nem aláírt esetben sok különlegességet ne várjunk szerver oldalon, szinte teljesen ugyanolyan, mint egy átlagos ajax request. Arra viszont érdemes figyelni, hogy a sessionkezelés nem fog működni utánajárás nélkül. Emiatt a Rails beépített <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF</a> védelme sem fog működni, de mint látni fogjuk, ez nem is probléma, hiszen a signed requestek megfelelő védelmet nyújtanak.</p>
<p>Aláírt lekérésre kétféle lehetőségünk van. Az egyik a <strong>signed request</strong> használata. Ebben az esetben a OpenSocial konténer a request paraméterekből egy privát kulcs vagy megosztott titok segítségével képez egy ellenőrző összeget. Ez alapján a távoli szerver tudni fogja, hogy valóban a várt helyről érkezik a kérés. Az aláírt paraméterek között szerepel az alkalmazás azonosító, és a <em>viewer</em> és az <em>owner</em> felhasználó azonosítója is. A lekérés a kulcs ismerete nélkül nem hamisítható, így biztosak lehetünk benne, hogy a kérést valóban az OpenSocial konténer küldte és a megadott adatok valódiak. Ebből már látható, hogy ez megfelelő CSRF védelmet nyújt, ezért <strong>ajánlatos minden nem GET requestnél a signed requestek használata</strong>.</p>
<p>A másik lehetőség az <strong>oauth</strong> használata, ahol az aláírás ugyanígy működik, de a request folyamat bonyolultabb, mert egy autentikációs lépést is tartalmaz. Ezt akkor érdemes használni, ha egy OpenSocial profilt össze akarunk kötni egy backend oldalon autentikációt igénylő saját felhasználónkkal. Erről a témáról bővebben majd egy későbbi bejegyzésben lesz szó.</p>
<h4>Signed requestek ellenőrzése</h4>
<p>A signed requestekről <a href="http://dev.iwiw.hu/blog/index.php/2009/01/06/alairt-kommunikacio-signed-request/">már volt szó</a> az iWiW fejlesztői blogon, ott érdemes esetleg utánaolvasni a kliens oldali részleteknek. A fejlesztői blog bejegyzésének kommentjeiben előkerült egy rubys probléma is, ami a signed requestek ellenőrzésekor jön elő.</p>
<p>A signed requestek ellenőrzéséhez Rubyban az <a href="http://github.com/pelle/oauth/tree/master">oauth gemre</a> lesz szükség. A gem jelenlegi verziójában van egy bug, ami miatt a request paraméterek túl sokszor lesznek escape-elve az ellenőrző kód számításakor, és emiatt az ellenőrző kód hibás lesz. Hivatalos javítás még nincs, de már többen is megoldották a problémát a GitHubos forkokban. A javítás a gem <a href="http://github.com/lackac/oauth/tree/master">általam forkolt verzióban</a> is elérhető, és ez a verzió tartalmaz egy Rails Edge kompatibilitás fixet is. Ajánlom, hogy innen telepítsétek a gemet, amíg az új verzióval ki nem jön a hivatalos javítás. (Pull request ment, és úgy tűnik most kezd feléledni a fejlesztői lista, úgyhogy van remény.)</p>
<h5>A githubról telepítéshez segédlet:</h5>
<pre>$ git clone git://github.com/lackac/oauth.git
$ cd oauth
$ rake gem
$ sudo gem install pkg/oauth-0.2.7.gem</pre>
<h4>Introducing gadgeteer</h4>
<p>Az ellenőrzési folyamat és gadget backend fejlesztés megkönnyítésére házon belül készítettünk egy Rails plugint, ami igyekszik minél több terhet levenni a fejlesztő válláról. A plugin neve <em>gadgeteer</em>, és MIT licensz alatt <a href="http://github.com/virgo/gadgeteer/tree/master">elérhető a GitHub-on</a>.</p>
<h5>Telepítés:</h5>
<pre>$ script/plugin install git://github.com/virgo/gadgeteer.git</pre>
<p>A plugin három dologban nyújt jelenleg segítséget. A kulcsokat teszi könnyen konfigurálhatóvá, a bejövő kérések ellenőrzését teszi egyszerűvé, és a konténertől kapott OpenSocial specifikus paramétereket teszi könnyen elérhetővé.</p>
<h5>Kulcsok</h5>
<p>A kulcsokat kétféleképpen lehet tárolni. A <tt>config</tt> könyvtár alatt, vagy valamelyik kontrollerben (célszerűen az <tt>ApplicationController</tt>-ben) konfigurálva.</p>
<p>Publikus kulcsok esetében a <tt>config/certs</tt> könyvtár alá kell berakni <tt>.cert</tt> kiterjesztésű fájlokat, vagy a kontrollerben a <tt>public_keys</tt> hash-be kell felvenni a megfelelő kulcsot a <tt>OpenSSL::PKey::RSA</tt> osztály egy példányaként. A gadgeteer a megfelelő kulcsot a <tt>xoauth_signature_publickey</tt> request paraméter alapján választja ki (iWiW esetében ennek értéke &#8216;iwiw.hu&#8217;).</p>
<p>Megosztott titok esetében a consumer_key/consumer_secret párosokat a <tt>config/oauth_secrets.yml</tt> fájlban lehet megadni, vagy közvetlenül a kontrollerben az <tt>oauth_secrets</tt> hash-be kell felvenni.</p>
<h5>Ellenőrzés</h5>
<p>A bejövő lekérések ellenőrzését a <tt>verify_signature</tt> metódussal végezhetjük. Ezt akár közvetlenül megadhatjuk egy <tt>before_filter</tt>-ben is. Az implementáció gondoskodik a megfelelő kulcs kiválasztásáról, és a megfelelő metódus segítségével ellenőrzi az aláírást.</p>
<h5>OpenSocial paraméterek elérése</h5>
<p>Signed request esetében kapunk pár hasznos paramétert, amiket a konténer &#8216;opensocial_&#8217; előtaggal lát el. Ezeket persze el tudjuk érni a <tt>params</tt> metódus segítségével is, de a gadgeteer plugin ad erre egy kézenfekvőbb metódust, aminek <tt>open_social</tt> a neve. Így például a <em>viewer</em> azonosítója <tt>open_social[:viewer_id]</tt>, az alkalmazás azonosítója pedig <tt>open_social[:app_id]</tt> lesz. Ezen túl bekerülnek még az &#8216;os_&#8217; kezdetű paraméterek is, hogy lehetőség legyen a kliens oldal által további OpenSocial specifikus paramétereket is ide csoportosítani. (Például kliens oldalon lekérhetünk további adatokat a <em>viewer</em>-ről és továbbadhatjuk a backend-nek &#8216;os_viewer_*&#8217; paraméterekben.)</p>
<p>A projekt README-ben található példakódok még világosabbá teszik a fentieket.</p>
<h5>További tervek</h5>
<p>A plugint szeretnénk tovább bővíteni hasznos dolgokkal, amelyek a kisalkalmazások fejlesztése közben előjönnek. Nyitottak vagyunk további javaslatok felé is, de nem ígérhetjük, hogy minden felmerülő ötletet megvalósítunk. Örömmel fogadjuk viszont, ha GitHubon keresztül küldtök pull requestet azokról a dolgokról, amelyekkel ti bővítitek a plugint.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.virgo.hu/undercode/2009/01/gadgetfejlesztes-rubyval-gadgeteer/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Sharding a&#8217;la Virgo</title>
		<link>http://www.virgo.hu/undercode/2008/12/sharding-ala-virgo/</link>
		<comments>http://www.virgo.hu/undercode/2008/12/sharding-ala-virgo/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 15:31:05 +0000</pubDate>
		<dc:creator>Zachar Krisztián</dc:creator>
		
		<category><![CDATA[Nincs kategorizálva]]></category>

		<category><![CDATA[ConnectionProvider]]></category>

		<category><![CDATA[Hibernate]]></category>

		<category><![CDATA[horizontális particionálás]]></category>

		<category><![CDATA[Java]]></category>

		<category><![CDATA[JPA]]></category>

		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[sharding]]></category>

		<category><![CDATA[shards]]></category>

		<guid isPermaLink="false">http://www.virgo.hu/undercode/?p=13</guid>
		<description><![CDATA[A feladat, nagyon nagy mennyiségű adat tárolása – esetünkben 30G rekord –, viszont az adatok rendelkeznek azzal a kellemes tulajdonsággal, hogy bizonyos szempont szerint szeparálhatók.
Ilyen esetekben jöhet szóba valamiféle sharding megoldás, más néven horizontális particionálás. Az ilyen megoldások lényege, hogy az adatokat fizikailag külön adatbázisban tároljuk. A szükséges adatokat az egyes shardokról külön-külön visszanyerjük, majd [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">A feladat, nagyon nagy mennyiségű adat tárolása – esetünkben 30G rekord –, viszont az adatok rendelkeznek azzal a kellemes tulajdonsággal, hogy bizonyos szempont szerint szeparálhatók.</p>
<p style="text-align: justify;">Ilyen esetekben jöhet szóba valamiféle sharding megoldás, más néven horizontális particionálás. Az ilyen megoldások lényege, hogy az adatokat fizikailag külön adatbázisban tároljuk. A szükséges adatokat az egyes shardokról külön-külön visszanyerjük, majd elvégezzük az esetleges utófeldolgozást (pl.: a különböző shard-okról származó adatok rendezése). Itt rögtön meg is mutatkozik, hogy mikor nem jó a sharding technológia: ha az utófeldolgozás túl költséges.<span id="more-13"></span></p>
<p>A sharding-ot legtöbbször alkalmazás szinten valósítjuk meg, bár vannak alacsonyabb szintű kezdeményezések is, például a MySQL Proxy-n alapuló <a href="http://www.hscale.org/display/HSCALE/Home">HScale</a>. Ezektől most tekintsünk el, és nézzük, milyen lehetőségeink vannak alkalmazás oldalon. A környezet, amiben dolgozunk: Java 1.5, JPA, Hibernate, MySQL. Hibernate-hez van egy „dobozolt” sharding megoldás, a <a href="http://www.hibernate.org/hib_docs/shards/reference/en/html/">Hibernate Shards</a>. Ez még béta állapotban van, de nagyon ígéretes. Azért érdemes elolvasni a „Limitations” fejezetet, és figyelni arra, hogy csak akkor lehet eredményesen használni, ha már a tervezésnél figyelembe vesszük, hogy shard-olt adatbázissal fogunk dolgozni. A Shards ugyan rengeteg dolgot megold utófeldolgozással, de ez legtöbbször performancia okokból nem vállalható. Az egyetlen járható út, ha már a tervezés során úgy építjük fel az alkalmazásunkat, hogy elkerüljük a költséges utófeldolgozások szükségességét!</p>
<p>Amiért nem a Shards-ot választottuk, annak két fő oka volt:</p>
<ul>
<li>Shard-onként külön <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/SessionFactory.html">SessionFactory</a>-t használ, ami elég nagy erőforrást emészt fel, ráadásul kényelmetlenné teszi a konfigurálást. (A Google saját bevallása szerint körülbelül 10 shard-ig eredményes.)</li>
<li>Mi JPA-n keresztül szeretnénk használni a Hibernate-et, míg a Shards leginkább a Criteria API-ra van kihegyezve</li>
</ul>
<p>A mi ötletünk lényege az volt, hogy a SessionFactory-nál mélyebb szinten, a <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/connection/ConnectionProvider.html">ConnectionProvider</a> interfészen keresztül avatkozunk be. A Hibernate ezen az interfészen keresztül kér el a JDBC connection-öket. Ha itt mindig a megfelelő shard-hoz tartozó connection-t adunk vissza, akkor az egyes műveletek a megfelelő adatbázisszerveren hajtódnak végre. Erőforrásban így shard-onként csak a ConnectionPool-ok többszöröződnek, ami nem kis költség, de nehezen megúszható. <img src='http://www.virgo.hu/undercode/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> Másrészt a sharding miatt egy pool-ban kevesebb connection-lesz a szokásosnál, így kevesebb memóriát emészt fel, és a karbantartó szálakon is spórolhatunk.</p>
<p>A konfigolhatóság egyszerű lesz, hisz a Hibernate által használt ConnectionProvider-t egyszerűen megadhatjuk a szabványos <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: navy;">hibernate.connection.provider_class </span>tulajdonságon keresztül (ahogy a ConnectionPool-t is), az egyes shard-okhoz tartozó beállításoknál pedig megtartjuk a Hibernate-es kulcsokat, azzal a megkötéssel, hogy mindegyik elé egy <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: navy;">virgo.shard.&lt;SHARD-NEVE&gt;. </span>prefix kerül, és ezt a saját Provider-ünkben fordítjuk vissza a hibernate-nek megfelelő formába. Ezt meg lehet még spékelni default érték kezeléssel (<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: navy;">virgo.shard.DEFAULT.</span> prefixű paraméterek minden shard-ra igazak, ha ott nincsenek megadva), hisz shard-onként rengeteg közös paraméter lesz – általában csak a connection url más. Így shard-onként egy plusz konfig sorral elintézhető a beállítás.</p>
<p>Két problémát kellett megoldanunk:</p>
<ol>
<li>Az alkalmazás csak olyan műveleteket hajthat végre, amik csak egyetlen shard-ra vonatkoznak. Minden más műveletet felsőbb rétegben szét kell bontani shard-onkénti műveletekre.</li>
<li>A felsőbb szinten valahogy jelezni kell, hogy melyik Shard-on is kell végrehajtani az adott műveletet.</li>
</ol>
<p>Az 1. pont igen nagy megkötésnek tűnik, azonban éles helyzetben nem igen képzelhető el, hogy olyan lekérdezések futnak, amik több – esetleg minden – shard-ot érintenek, ekkor ugyanis nem sokat nyerünk a sharding-gal. Ebben az esetben valószínű érdemesebb más terheléselosztást választani, esetleg más szisztéma szerint shard-olni. Ha néhány ilyen helyzet mégis előfordul, akkor könnyű rá valamiféle JPA kompatibilis, újrafelhasználható megoldást írni, például QueryBuilder-ek / speciális Shard-olt Query implementációk formájában. Általános megoldás egyébként sincs, ugyanis alacsony szinten egy összetettebb lekérdezésnél igen nehéz eldönteni, hogy mit is akart a hívó. (A Hibernate Shards is korlátozott képességekkel rendelkezik ezen a téren.)</p>
<p>A mi esetünkben nem is volt olyan olvasó művelet, amikor több shard-hoz kellett nyúlni. Író műveletünk volt, ott egy bulk insert-et kiadó QueryBuilder-t valósítottunk meg, ami előbb memóriában összegyűjti a beszúrandó adatokat shard-onként, majd egyesével elküldi őket. Itt problémás a hibakezelés: mi van, ha az n-edik shard tranzakciója nem sikerül? Mi amellett döntöttünk, hogy a query objektum visszaadja a sikertelen rekordokat, ezek egy hibasorra kerülnek, és később újra megpróbáljuk a feldolgozást.</p>
<p>A 2. problémára adott megoldások igazából egy dologra épülhetnek,mivel a ConnectionProvider getConnection() metódusa nem kap paramétereket, így a hívóval csak ThreadLocal-on keresztül kommunikálhat. Arra persze már több lehetőség kínálkozik, hogy ezt a ThreadLocal-t hogyan állítjuk be. Mi egy JPA metodikába illő megoldást kerestünk, a következőt választottuk. Az EntityManager interfészt kiterjesztettük <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">ShardedEntityManager</span> néhány shard-kezelő metódussal, például:</p>
<div style="margin-left: 40px">
<p><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">boolean</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> isSharded();</span></p>
<p><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> getShardCount();</span></p>
<p><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String getCurrentShard();</span></p>
<p><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">void</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> setCurrentShard(String shardName);</span></p>
<p><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String[] getShards();</span></p>
<p><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String resolveShard(Object entity);</span></p>
<p><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String resolveShard(Class&lt;?&gt; entityClass, Object&#8230; primaryKey);</span></div>
<p>Látható, hogy az egyes entity-khez tartozó shard kiválasztását (<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">resolveShard</span>) és az aktuális shard beállítását (<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">setCurrentShard</span>) külön metódusba tettük. Így lehetséges, hogy eltároljuk a shard nevét, megspórolva a resolve költségét, illetve van lehetőség iterálni az összes shard-on. Annak a leprogramozása, hogy az egyes Entity-khez milyen shard-ok tartoznak egy külön osztályba került, ezt PersistenceUnit-onként egyszer kell megtenni.</p>
<p>Egy statikus metóduson keresztül ­– <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">ShardManager.extend(EntityManager em) –</span>tetszőleges <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">EntityManager</span> kiterjeszthető <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">ShardedEntityManager-</span>ré, ezért került bevezetésre az<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> isSharded() </span>metódus, ami nem shard-olt esetben false-t ad vissza.</p>
<p>A shard-olt eset az érdekesebb, ilyenkor ugyanis nem elég, hogy a visszaadott manager a <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">setCurrentShard</span> metódusban átállítja a ThreadLocal értékét, hiszen ha egy szál esetleg több EntityManager-t használ felváltva, akkor függetlenül a sorrendtől az egyes manager-eknek a rajtuk beállított shard-hoz kell menniük. Ezért egy olyan EntityManager kerül visszaadásra, ami wrap-eli a kapott EntityManager-t, és az eredeti metódusok hívása előtt mindig beállítja az adott manager aktuális shard-ját a ThreadLocal-ban. Mi ezt a wrap-elést CGLib-en keresztüli proxy-zással valósítottuk meg, de meg lehet írni a wrapper osztályt kézzel is.</p>
<p>Megjegyzések:</p>
<ol>
<li>A shard-ok szerinti connection visszaadás nem okoz gondot a 2nd level cache-ben, hisz a shard-ok diszjunktak, az id-k globálisan egyedik.</li>
<li>Nem szóltunk az id generálás problémáiról, mivel ez nem tartozik szorosan a témához, de garantálni kell, hogy globálisan egyedi id-k kerülnek kiosztásra. Erre több lehetőség kínálkozik:
<ul>
<li>globális szekvenciából / táblából – pool-ozva – osztjuk az id-t</li>
<li>lokálisan osztjuk, de úgy, hogy globálisan egyedi legyen (pl.: &lt;shard-index&gt; + N * &lt;shardok-száma&gt;, ahol N=1, 2, …)</li>
<li>összetett kulcs (shard + lokális id)</li>
</ul>
</li>
<li>A kézi shard állítás automatizálásán is gondolkodtunk, több ötletünk is volt, de egy olyan sem, ami elég általános, és valódi haszonnal járó lett volna. Ami nekünk eszünkbe jutott:
<ul>
<li>ha shard-olt entity-vel hívunk persist(), merge(), stb. metódust, akkor a shard automatikusan állítódjon be.</li>
<li>findEntity(@Shard(class=Entity.class) int primaryKey)</li>
<li>A fenti üzleti metódus esetén az aktuális Shard beállítódik a class, és primaryKey által meghatározott entity-nek megfelelőre.</li>
</ul>
</li>
<li>Természetesen a query-k „shard-osításán” is gondolkodtunk, de ennek általános megoldása túl nagy falat – nem is volt cél –, és performancia szempontból sem tűnik jó útnak. Egy egyszerű példa: már egy query Order By feltételének megfelelő Comparator elkészítése, amivel ugyanaz a rendezés a memóriában elvégezhető sem egyszerű. (Nem is beszélve arról, ha az oszlop, ami szerint rendezünk, nem is szerepel a visszaadott mező listában; a lokalizációs problémákról, stb.)</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.virgo.hu/undercode/2008/12/sharding-ala-virgo/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MySQL előadás az OpenSource BI konferencián</title>
		<link>http://www.virgo.hu/undercode/2008/11/mysql-eloadas-az-opensource-bi-konferencian/</link>
		<comments>http://www.virgo.hu/undercode/2008/11/mysql-eloadas-az-opensource-bi-konferencian/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 14:45:10 +0000</pubDate>
		<dc:creator>Boros Péter</dc:creator>
		
		<category><![CDATA[Nincs kategorizálva]]></category>

		<guid isPermaLink="false">http://www.virgo.hu/undercode/?p=3</guid>
		<description><![CDATA[
Először mi is meglepődtünk, mikor a Sun megkeresett minket, hogy egy BI konferencián kellene MySQL előadást tartani. Már csak azért is, mert BI és DW területen nem kifejezetten elterjedt a MySQL. Gyors telefonos egyeztetés a szervezővel. Szerinte elég aktuális a téma, ha már távközlési cégek is keresnek Magyarországon MySQL adattárház szakértőt. A BI területről jövő [...]]]></description>
			<content:encoded><![CDATA[<div class="entry-content">
<p>Először mi is meglepődtünk, mikor a Sun megkeresett minket, hogy egy BI konferencián kellene MySQL előadást tartani. Már csak azért is, mert BI és DW területen nem kifejezetten elterjedt a MySQL. Gyors telefonos egyeztetés a szervezővel. Szerinte elég aktuális a téma, ha már távközlési cégek is keresnek Magyarországon MySQL adattárház szakértőt. A BI területről jövő résztvevőknek valószínű nem lesz ismerős a MySQL, legyen szó adattárházakról és új dolgokról is, 40 percbe férjen bele. Ez volt tegnap.</p>
<p>A MySQL a cserélhető storage engine architektúra miatt jól testreszabható célfeladatokra egy storage engine cserével. Egy adattárházas storage engine-t onnan lehet megismerni, hogy nem sor, hanem oszlop alapon tárol. Ez elég sok optimalizációra ad lehetőséget, a legtriviálisabb az, hogy tömöríteni jobban lehet (mert egy oszlopban ugyanolyan típusú adatok vannak).</p>
<p>A MySQL és a Falcon engine újdonságait már valószinűleg hallotta előtte is a közönség, ha voltak Oracle 7 vagy 8 újdonságok előadáson. Ez így elsőre viccesnek hat, de ahhoz képest, hogy CRUD adatbáziskezelőnek indult, már támogat tranzakciókat, nézeteket, és triggereket.</p>
<p>Az előadás után többen érdeklődtek a MySQL-ről (főleg az enterpriseról) meg arról, hogy mi milyen esetben milyen adatbáziskezelőt használnánk. Szerintünk sikerült annyira jól, hogy rögtön <a href="/undercode/wp-content/uploads/2008/12/boros_peter_opensource_bi_mysql1.pdf">ide</a> is teszem a prezentációt, hogy le lehessen tölteni.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.virgo.hu/undercode/2008/11/mysql-eloadas-az-opensource-bi-konferencian/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
