<?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>j2ee.pl - związani z javą &#187; GWT</title>
	<atom:link href="http://j2ee.pl/category/gwt/feed/" rel="self" type="application/rss+xml" />
	<link>http://j2ee.pl</link>
	<description>związani z Javą</description>
	<lastBuildDate>Mon, 24 Aug 2009 11:45:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>GWT, czyli AJAX bez bólu</title>
		<link>http://j2ee.pl/2007/09/30/gwt-czyli-ajax-bez-bolu/</link>
		<comments>http://j2ee.pl/2007/09/30/gwt-czyli-ajax-bez-bolu/#comments</comments>
		<pubDate>Sun, 30 Sep 2007 00:59:49 +0000</pubDate>
		<dc:creator>Andrzej Maliszewski</dc:creator>
				<category><![CDATA[GWT]]></category>
		<category><![CDATA[ajax]]></category>

		<guid isPermaLink="false">http://j2ee.pl/2007/09/30/gwt-czyli-ajax-bez-bolu/</guid>
		<description><![CDATA[Google Web Toolkit jest to framework umożliwiający łatwe i bezbolesne tworzenie aplikacji AJAX. Aby użyć GWT wystarcza znajomość Javy i podstaw HTMLa, nie jest natomiast potrzebna znajomość JavaScriptu. Poniższy artykuł ma na celu przybliżyć podstawy GWT oraz krok po kroku pokazać jak szybko stworzyć prostą aplikację opartą na tym frameworku.

Budowa GWT
Na początek przyjrzymy się, co [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://code.google.com/images/code_sm.png" alt="Google Code" />Google Web Toolkit jest to framework umożliwiający łatwe i bezbolesne tworzenie aplikacji AJAX. Aby użyć GWT wystarcza znajomość Javy i podstaw HTMLa, nie jest natomiast potrzebna znajomość JavaScriptu. Poniższy artykuł ma na celu przybliżyć podstawy GWT oraz krok po kroku pokazać jak szybko stworzyć prostą aplikację opartą na tym frameworku.<br />
<span id="more-90"></span></p>
<h3>Budowa GWT</h3>
<p>Na początek przyjrzymy się, co tak naprawdę kryje się nazwą GWT. GWT składa się z czterech podstawowych komponentów.</p>
<p>Pierwszy z nich, kompilator Java-to-JavaScript, tłumaczy kod źródłowy na JavaScript i HTML. Oczywiście, aby kod mógł zostać poprawnie przetłumaczony, musi spełniać szereg ograniczeń. Przede wszystkim należy pamiętać, że GWT w obecnej wersji (1.4) jest zgodny z Javą 1.4.2,  więc użycie jakichkolwiek rozszerzeń Javy 1.5 skończy się błędem kompilacji. Poza tym należy zapomnieć o takich przyjemnościach jak wielowątkowość czy refleksja.</p>
<p>Drugi komponent to dedykowana przeglądarka WWW. Umożliwia ona uruchomienie aplikacji bez translacji do JavaScriptu, w tzw. Hosted Mode. Szczegóły – za chwilę.</p>
<p>Trzeci komponent to biblioteka emulująca podstawowe klasy biblioteki standardowej Javy w JavaScripcie. Zawiera ona implementację większości klas z <code>java.lang</code>, oraz część <code>java.util</code>.</p>
<p>Czwarty komponent, czyli biblioteka Web UI, służy do tworzenia interfejsu użytkownika który zostanie następnie przetłumaczony na stronę WWW.</p>
<h3>Hosted Mode vs. Web Mode</h3>
<p>GWT oferuje nam dwa tryby uruchomienia stworzonej aplikacji. Pierwszy z nich, tzw. Hosted Mode, wykorzystując wspomnianą już dedykowaną przeglądarkę WWW uruchamia aplikację bezpośrednio w wirtualnej maszynie Javy, bez tłumaczenia kodu do JavaScriptu. To pozwala programiście korzystać z takich dobrodziejstw Javy, jak chociażby wygodne debugowanie kodu. Z tego względu Hosted Mode jest używany w trakcie procesu tworzenia aplikacji.</p>
<p>Z kolei Web Mode polega na skompilowaniu kodu do HTMLa i JavaScriptu i uruchomieniu tak przygotowanej aplikacji w dowolnej przeglądarce WWW. Ten tryb używany jest przy wdrażaniu gotowej aplikacji.</p>
<h3>GWT w praktyce</h3>
<p>Po krótkim wprowadzeniu czas przejść do konkretów, czyli przykładowej aplikacji.  Będzie to prosty kalendarz zamieszczony na stronie WWW.<br />
Aby użyć GWT wystarczy pobrać wersję odpowiednią dla używanego systemu ze strony <a href="http://code.google.com/webtoolkit">http://code.google.com/webtoolkit</a> i rozpakować ją do dowolnego katalogu. Dla wygody warto dopisać go do zmiennej środowiskowej <code>PATH</code>.</p>
<p>Do stworzenia projektu skorzystamy z dwóch skryptów dostarczonych wraz z GWT: <code>projectCreator</code> oraz <code>applicationCreator</code>. Pierwszy z nich posłuży do stworzenia plików projektu Eclipse’a, drugi do wygenerowania podstawowych plików aplikacji.</p>
<pre class="prettyprint">C:\\projects\\gwtcalendar&gt;projectCreator.cmd -eclipse gwtcalendar
Created directory C:\\projects\\gwtcalendar\\src
Created directory C:\\projects\\gwtcalendar\\test
Created file C:\\projects\\gwtcalendar\\.project
Created file C:\\projects\\gwtcalendar\\.classpath

C:\\projects\\gwtcalendar&gt;applicationCreator.cmd -eclipse gwtcalendar pl.jcommerce.example.gwtcalendar.client.Calendar
Created directory C:\\projects\\gwtcalendar\\src\\pl\\jcommerce\\example\\gwtcalendar
Created directory C:\\projects\\gwtcalendar\\src\\pl\\jcommerce\\example\\gwtcalendar\\client
Created directory C:\\projects\\gwtcalendar\\src\\pl\\jcommerce\\example\\gwtcalendar\\public
Created file C:\\projects\\gwtcalendar\\src\\pl\\jcommerce\\example\\gwtcalendar\\Calendar.gwt.xml
Created file C:\\projects\\gwtcalendar\\src\\pl\\jcommerce\\example\\gwtcalendar\\public\\Calendar.html
Created file C:\\projects\\gwtcalendar\\src\\pl\\jcommerce\\example\\gwtcalendar\\client\\Calendar.java
Created file C:\\projects\\gwtcalendar\\Calendar.launch
Created file C:\\projects\\gwtcalendar\\Calendar-shell.cmd
Created file C:\\projects\\gwtcalendar\\Calendar-compile.cmd</pre>
<p>Skrypt applicationCreator tworzy strukturę pakietów zgodną z zaleceniami GWT:<br />
<code>.../gwtcalendar</code> – główny pakiet zawierający wszystkie pliki projektu. Bezpośrednio w tym pakiecie tworzony jest plik konfiguracyjny XML.<br />
<code>.../gwtcalendar/client</code> – pakiet zawierający pliki źródłowe warstwy klienta. To właśnie te pliki będą później tłumaczone na JavaScript.<br />
<code>.../gwtcalendar/public</code> – w tym pakiecie zawarte są statyczne zasoby takie jak gotowe pliki html, css czy grafika.<br />
W typowych aplikacjach występuje dodatkowo pakiet <code>.../gwtcalendar/server</code>, zawierający źródła warstwy serwerowej. Ta część kodu nie podlega kompilacji do JavaScriptu, więc nie obowiązują tu żadne ograniczenia nałożone przez GWT. W naszej przykładowej aplikacji zajmiemy się tylko warstwą klienta, więc ten pakiet jest zbędny.</p>
<p>Dodatkowo stworzone zostały trzy pliki w katalogu głównym projektu:<br />
<code>Calendar.launch</code> – plik projektu Eclipse’a pozwalający uruchomić projekt w trybie debug<br />
<code>Calendar-shell.cmd</code> – skrypt uruchamiający aplikację w Hosted Mode<br />
<code>Calendar-compile.cmd</code> – skrypt kompilujący aplikację do postaci HTMLa i JavaScriptu w celu uruchomienia jej w trybie Web Mode</p>
<p>Po wykonaniu powyższych skryptów importujemy projekt do Eclipse’a i przystępujemy do dokładniejszych oględzin plików w pakiecie <code>.../gwtcalendar</code>.<br />
Najpierw przyjrzyjmy się plikowi konfiguracyjnemu modułu <code>Calendar.gwt.xml</code>:</p>
<pre class="prettyprint">&lt;module&gt;

   &lt;!-- Inherit the core Web Toolkit stuff.                  --&gt;
   &lt;inherits name='com.google.gwt.user.User'/&gt;

   &lt;!-- Specify the app entry point class.                   --&gt;
   &lt;entry-point class='pl.jcommerce.example.gwtcalendar.client.Calendar'/&gt;

&lt;/module&gt;</pre>
<p>Jak widać nie jest on zbyt skomplikowany. Pierwszy element, <code>inherits</code>, wskazuje na dziedziczenie ze standardowego modułu interfejsu użytkownika GWT. Drugi element, <code>entry-point</code>, wskazuje na główną klasę modułu. W momencie wczytania strony WWW, wykonana zostanie metoda <code>onModuleLoad()</code> wskazanej klasy. Główna klasa modułu musi implementować interfejs <code>com.google.gwt.core.client.EntryPoint</code>.</p>
<p>Teraz przejdźmy do naszej statycznej strony WWW, czyli pliku <code>Calendar.html</code>.  Wygenerowana, przykładowa zawartość pokazuje, jak można użyć modułu GWT jako część istniejącej strony WWW. W naszym przypadku w zupełności wystarczy mocno okrojona wersja:</p>
<pre class="prettyprint">&lt;html&gt;
   &lt;head&gt;

      &lt;title&gt;Calendar&lt;/title&gt;

   &lt;/head&gt;
   &lt;body&gt;

      &lt;script language='javascript' src='pl.jcommerce.example.gwtcalendar.Calendar.nocache.js'&gt;&lt;/script&gt;

      &lt;!-- OPTIONAL: include this if you want history support --&gt;
      &lt;iframe src="javascript:''" id="__gwt_historyFrame" style="width:0;height:0;border:0"&gt;&lt;/iframe&gt;

   &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Nie ma tu za wiele do wyjaśniania. W elemencie <code>script</code> podajemy nazwę modułu z końcówką <code>.nocache.js</code>. Z kolei umieszczenie elementu <code>iframe</code> pozwala na wykorzystanie wsparcia historii przeglądarki oferowanego przez GWT. W naszej przykładowej aplikacji nie ma to żadnego zastosowania, ale warto pamiętać o tym udogodnieniu.</p>
<p>Na koniec trzeci, najbardziej interesujący plik, czyli <code>Calendar.java</code>. Podobnie jak w przypadku <code>Calendar.html</code>, wygenerowana treść metody <code>onModuleLoad()</code> jest tylko przykładowa i od razu możemy się jej pozbyć.</p>
<p>Przyjrzyjmy się teraz budowie interfejsu użytkownika za pomocą GWT. Podstawową klasą interfejsu jest <code>com.google.gwt.user.client.ui.Widget</code>. Z Widget dziedziczą wszystkie elementy UI takie jak przyciski, pola tekstowe, tabele i wiele innych. Szczególnym elementem jest <code>com.google.gwt.user.client.ui.Panel</code>, abstrakcyjna klasa bazowa dla wszystkich kontenerów. GWT, w odróżnieniu od np. Swinga, nie używa odrębnych klas typu <code>LayoutManager</code>. Układem komponentów zarządzają  bezpośrednio klasy dziedziczące z Panel, takie jak <code>HorizontalPanel</code>, <code>VerticalPanel</code>, <code>FlowPanel</code> czy <code>DockPanel</code>. Aby umieścić jakiekolwiek komponenty na stronie musimy uzyskać dostęp do głównego panelu. Służy do tego metoda statyczna <code>RootPanel.get()</code>.</p>
<p>Interfejs naszego kalendarza  będzie się składał z nagłówka zawierającego przyciski do zmiany wyświetlanego miesiąca, paska z etykietami oznaczającymi kolejne dni tygodnia oraz panelu przedstawiającego dni miesiąca. Na początek kilka zmiennych i stałych wykorzystywanych w naszej klasie, oraz metoda <code>onModuleLoad()</code>:</p>
<pre class="prettyprint">private int currYear;private int currMonth;
private VerticalPanel mainPanel;
private Label monthLabel;
private Widget monthPanel;private static final int DAY = 1000 * 3600 * 24;
private static final int WEEK = DAY * 7;
private static final String[] dayNames = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

/**
 * This is the entry point method.
 */
public void onModuleLoad() {
   Date date = new Date();
   currYear = date.getYear();
   currMonth = date.getMonth();
   initUI();
}</pre>
<p>Zmienne <code>mainPanel</code>, <code>monthLabel</code> oraz <code>monthPanel</code> będą przechowywać komponenty, do których potrzebny będzie dostęp w metodach odpowiedzialnych za „dynamikę” naszej aplikacji. Reszta kodu nie wymaga chyba komentarza. Przyjrzyjmy się wobec tego kolejnej metodzie tworzącej interfejs:</p>
<pre class="prettyprint">private void initUI() {
   mainPanel = new VerticalPanel();
   mainPanel.setWidth("250px");
   mainPanel.setSpacing(3);
   mainPanel.add(createHeaderPanel());
   mainPanel.add(createDayNamesPanel());
   mainPanel.add(monthPanel = createMonthPanel());
   RootPanel.get().add(mainPanel);
}</pre>
<p>W tej metodzie tworzymy główny panel, ustawiamy jego parametry i dodajemy podstawowe elementy. Na koniec ustawiamy go jako jedyny element RootPanela. Warto zwrócić uwagę na wywołanie metody <code>setWidth()</code>, która przyjmuje parametr typu <code>String</code>, a nie <code>int</code>. Metoda ta przyjmuje wszystkie poprawne wartości CSS, a więc poprawne będzie zarówno „250px”, jak i „5cm” czy „15%”.</p>
<p>Następne dwie metody tworzą nagłówek naszego kalendarza:</p>
<pre class="prettyprint">private Widget createHeaderPanel() {
   HorizontalPanel headerPanel = new HorizontalPanel();
   headerPanel.setWidth("100%");
   headerPanel.setSpacing(3);
   Button prevButton = new Button("&amp;lt;&amp;lt;");
   prevButton.setWidth("100%");
   headerPanel.add(prevButton);
   headerPanel.setCellWidth(prevButton, "20%");
   monthLabel = new Label((currYear + 1900) + "-" + (currMonth + 1));
   headerPanel.add(monthLabel);
   headerPanel.setCellHorizontalAlignment(monthLabel,
         HasHorizontalAlignment.ALIGN_CENTER);
   Button nextButton = new Button("&amp;gt;&amp;gt;");
   nextButton.setWidth("100%");
   headerPanel.add(nextButton);
   headerPanel.setCellWidth(nextButton, "20%");
   return headerPanel;
}

private Widget createDayNamesPanel() {
   HorizontalPanel dayNamesPanel = new HorizontalPanel();
   dayNamesPanel.setWidth("100%");
   dayNamesPanel.setSpacing(3);
   Label lab;
   for (int i = 0; i &lt; dayNames.length; i++) {
      lab = new Label(dayNames[i]);
      lab.setWidth("100%");
      dayNamesPanel.add(lab);
      dayNamesPanel.setCellWidth(lab, "14%");
      dayNamesPanel.setCellHorizontalAlignment(lab, HasHorizontalAlignment.ALIGN_CENTER);
   }
   return dayNamesPanel;
}</pre>
<p>Jak widać uzyskanie żądanego układu komponentów nie powinno sprawić problemów programiście posiadającemu chociaż podstawowe doświadczenia z takimi bibliotekami GUI jak Swing czy SWT. Bardzo pomocne są metody <code>setCellWidth()</code> czy <code>setCellHorizontalAlignment()</code>, pozwalające ustawić rozmiar i ułożenie osobno dla każdego elementu.<br />
Kolejne dwie metody tworzą panel przedstawiający dni miesiąca:</p>
<pre class="prettyprint">private Widget createMonthPanel() {
   VerticalPanel monthPanel = new VerticalPanel();
   monthPanel.setWidth("100%");
   monthPanel.setSpacing(3);
   Date firstDay = new Date(currYear, currMonth, 1);
   Date currDay = new Date(firstDay.getTime() - firstDay.getDay() * DAY);
   monthPanel.add(getWeekPanel(currDay));
   while ((currDay = new Date(currDay.getTime() + WEEK)).getMonth() == firstDay.getMonth()) {
      monthPanel.add(getWeekPanel(currDay));
   }
   return monthPanel;
}

private Widget getWeekPanel(Date date) {
   HorizontalPanel weekPanel = new HorizontalPanel();
   weekPanel.setWidth("100%");
   weekPanel.setSpacing(3);
   Date firstDay = new Date(date.getTime() - date.getDay() * DAY);
   for (int i = 0; i &lt; 7; i++) {
      Date btnDate = new Date(firstDay.getTime() + i * DAY);
      Button btn = new Button(String.valueOf(btnDate.getDate()));
      if (btnDate.getMonth() != currMonth) {
         btn.setEnabled(false);
      }
      btn.setWidth("100%");
      weekPanel.add(btn);
      weekPanel.setCellWidth(btn, "14%");
   }
   return weekPanel;
}</pre>
<p>W powyższych metodach nie ma w zasadzie niczego nowego, poza nieco karkołomnym żonglowaniem datami. Jeśli zastanawiasz się, dlaczego konsekwentnie używamy oznaczonych jako deprecated metod klasy <code>Date</code>, zamiast użyć znacznie wygodniejszej klasy <code>Calendar</code>, odpowiedź brzmi: klasa <code>Calendar</code> nie istnieje. A właściwie: klasa <code>Calendar</code> należy do tej znaczącej części pakietu <code>java.util</code>, której GWT nie implementuje. Pozostaje więc zacisnąć zęby i radzić sobie z tym, co mamy.</p>
<p>Ale wróćmy do naszej aplikacji. Mamy już wszystko co potrzeba do stworzenia interfejsu. Efekt możemy obejrzeć uruchamiając nasz projekt (bezpośrednio za pomocą Eclipse’a lub za pomocą skryptu <code>Calendar-shell.cmd</code>).</p>
<p>Teraz, gdy mamy stworzony interfejs, czas tchnąć życie w naszą stronę WWW. Do obsługi zdarzeń GWT wykorzystuje wzorzec Listener, dobrze znany np. ze Swinga. Na początek dodajmy interfejs <code>com.google.gwt.user.client.ui.ClickListener</code> do deklaracji naszej klasy <code>Calendar</code>:</p>
<pre class="prettyprint">public class Calendar implements EntryPoint, ClickListener {
   ...
}</pre>
<p>Następnie dopiszmy parę metod odpowiedzialnych za obsługę zdarzeń:</p>
<pre class="prettyprint">public void onClick(Widget sender) {
   String text = ((Button) sender).getText();
   if ("&lt;&lt;".equals(text)) {
      prevMonth();
   } else if ("&gt;&gt;".equals(text)) {
      nextMonth();
   } else {
      Window.alert(text + "-" + (currMonth + 1) + "-" + (currYear + 1900));
   }
}

private void prevMonth() {
   if (currMonth &gt; 0) {
      currMonth--;
   } else {
      currYear--;
      currMonth = 11;
   }
   refreshMonthPanel();
}

private void nextMonth() {
   if (currMonth &lt; 11) {
      currMonth++;
   } else {
      currYear++;
      currMonth = 0;
   }
   refreshMonthPanel();
}

private void refreshMonthPanel() {
   monthLabel.setText((currYear + 1900) + "-" + (currMonth + 1));
   mainPanel.remove(monthPanel);
   mainPanel.add(monthPanel = createMonthPanel());
}</pre>
<p>Na koniec musimy podpiąć obsługę kliknięć do stworzonych przycisków:</p>
<pre class="prettyprint">private Widget createHeaderPanel() {
   ...
   Button prevButton = new Button("&amp;lt;&amp;lt;");
   prevButton.setWidth("100%");
   <strong>prevButton.addClickListener(this);</strong>
   ...
   Button nextButton = new Button("&amp;gt;&amp;gt;");
   nextButton.setWidth("100%");
   <strong>nextButton.addClickListener(this);</strong>
   ...
}

private Widget getWeekPanel(Date date) {
   ...
   for (int i = 0; i &lt; 7; i++) {
      ...
      Button btn = new Button(String.valueOf(btnDate.getDate()));
      <strong>btn.addClickListener(this);</strong>
   ...
}</pre>
<p>W ten sposób dotarliśmy do końca, nasza przykładowa aplikacja jest gotowa. Wystarczy uruchomić skrypt <code>Calendar-compile.cmd</code>, a w katalogu WWW pojawi się nasza aplikacja przetłumaczona na HTML i JavaScript, gotowa do uruchomienia w dowolnej przeglądarce WWW lub umieszczenia na serwerze.</p>
<h3>Podsumowanie</h3>
<p>Oczywiście zaprezentowana aplikacja pokazuje tylko skromny wycinek możliwości GWT. Nie wspomnieliśmy o prostej komunikacji z serwerem za pomocą RPC, ułatwionej internacjonalizacji czy bezpośrednich wstawkach JavaScript za pomocą JavaScript Native Interface (JSNI). Jednak już tak prosty przykład pokazuje jak łatwo można tworzyć dynamiczne strony WWW używając jedynie Javy. Jeśli dodatkowo wierzyć zapewnieniom autorów o kompatybilności stworzonego kodu ze wszystkimi wiodącymi przeglądarkami WWW oraz o wydajności porównywalnej z ręcznie tworzonymi stronami AJAX, wówczas warto bliżej zainteresować się frameworkiem Google Web Toolkit.</p>
]]></content:encoded>
			<wfw:commentRss>http://j2ee.pl/2007/09/30/gwt-czyli-ajax-bez-bolu/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Nowy framework AJAX / Java od Google</title>
		<link>http://j2ee.pl/2006/05/17/nowy-framework-ajax-java-od-google/</link>
		<comments>http://j2ee.pl/2006/05/17/nowy-framework-ajax-java-od-google/#comments</comments>
		<pubDate>Wed, 17 May 2006 17:44:00 +0000</pubDate>
		<dc:creator>Michał Porzożyński</dc:creator>
				<category><![CDATA[GWT]]></category>

		<guid isPermaLink="false">http://wporzo.reakcja.net/2006/05/17/nowy-framework-ajax-java-od-google/</guid>
		<description><![CDATA[Google Web Toolkit jest nowym (jeszcze w wersji beta) javowym frameworkiem, który według deweloperów z firmy Google znacząco ułatwia tworzenie aplikacji w oparciu o AJAX. Framework ten jest przeznaczony dla programistół Javy,  którzy średnio pragną nauczyć się kolejnych języków (no chyba szczególnie JavaScript). Według opisu, który możemy znaleść na stronach code.google.com, tworzenie takich aplikacji [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://code.google.com/images/code_sm.png" alt="Google" title="Google" align="left" />Google Web Toolkit jest nowym (jeszcze w wersji beta) javowym frameworkiem, który według deweloperów z firmy Google znacząco ułatwia tworzenie aplikacji w oparciu o AJAX. Framework ten jest przeznaczony dla programistół Javy,  którzy średnio pragną nauczyć się kolejnych języków (no chyba szczególnie JavaScript). Według opisu, który możemy znaleść na stronach code.google.com, tworzenie takich aplikacji to istny koszmar (głównie dzięki braku kompatybilności między przeglądarkami).. i dzięki GWT.. ten koszmar zniknie z naszych powiek ;D Coś w tym koszmarze musi być.. skoro, jak wczoraj napisał na <a href="http://jdn.pl" target="_blank">jdn.pl</a> użytkownik xoft (za stroną <a href="http://ajaxian.com/archives/134-ajax-frameworks-and-counting">ajaxian.com</a>), mamy już 134 (a teraz pewnie już 135) różne frameworki dla AJAXa właśnie. Z wielką ciekawością zasiąde przed tym najnowszym :)</p>
]]></content:encoded>
			<wfw:commentRss>http://j2ee.pl/2006/05/17/nowy-framework-ajax-java-od-google/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
