GeeCON za 250zł ?!!!

Tak, właśnie pojawiła się informacja o promocji 5+1, wiele firm pytało o zniżki za grupowe wejściówki więc pojawiła się standardowa “procedura” w tej kwestii. Wystarczy, że zarejestrujesz pięć osób a dostaniesz bilet dla szóstej osoby całkowicie za free! Ta promocja sprawi, że GeeCON będzie dostępny już od 250zł (w przypadku biletów dla studentów/aktywnych członków JUGów) za osobę za calutkie DWA dni!!! Jeśli już się zarejestrowałeś to znajdź dodatkowe osoby a będziesz płacił mniej!!!

A to jeszcze nie wszystko, szykujemy dla was specjalne szkolenia prowadzone przez Sun Learning Services w powalającej cenie (stanowiącej ułamek ich realnej ceny!!!), niestety ilość miejsc na szkolenia będzie ograniczona więc kto pierwszy ten lepszy :P
Przedsmak szkoleń tutaj, więcej szczegółów (w tym cena) w najbliższym czasie.

March 20, 2009 | Leave a Comment  |

GeeCON - czy Twój szef wystarczająco dba o Ciebie?

Tytuł może zbyt kontrowersyjny ale w innym przypadku pewnie nie zwrócilibyście na niego uwagi :)

Jak zapewne większość z Was wie, wczoraj wystartowaliśmy z rejestracją na GeeCON - pierwszą w pełni międzynarodową konferencją poświęconą Javie w Polsce. Jest to dobry moment aby przybliżyć pokrótce powody dla których ją organizujemy oraz dlaczego poważnie powinieneś zastanowić się nad udziałem w GeeCON.

Po pierwsze, głównym powodem dla którego zabraliśmy się za organizację GeeCON była chęć umożliwienia Wam i sobie udziału w konferencji podczas której prelegentami będą ludzie z naprawdę topową wiedzą. Część z nich to znane osoby pracujące nad rozwojem technologii których używacie codziennie w pracy, część to ludzie pracujący nad ciekawymi projektami, którzy są chętni podzielić się swoim doświadczeniem. Staramy się ich zebrać w jednym miejscu i czasie, tak aby stworzyć możliwie najbardziej interesujące wydarzenie “javowe” w tym roku w Polsce.

Oczywiście, nie wszystkie tematy muszą wszystkim odpowiadać, możliwe też, że część z prezentacji, które znajdują się w agendzie byłaby Waszym zdaniem gorsza od tych, które musieliśmy odrzucić z braku wolnych slotów (aktualne wolne sloty w agendzie są przeznaczone dla prelegentów, którzy nie śpieszą się z podsyłaniem tematów i abstraktów).

Organizując GeeCON staramy się unikać tego czego sami nie lubimy, dlatego też ograniczyliśmy do absolutnego minimum wszystkie marketingowe aspekty prezentacji, a prelegenci sponsorów będą opowiadać o rozwiązaniach open source i technologiach ogólnie dostępnych, to jest jeden z naszych głównych celów.

Pomimo faktu, że wszyscy organizujemy konferencję za free (ot taki rodzaj wolontariatu), nie uda nam się doprowadzić do tego aby wejściówki były za darmo. Niestety są pewne koszty stałe, których pokrycie konieczne jest do realizacji pełni naszej wizji. Gdybyśmy z nich zrezygnowali to GeeCON nie byłby już GeeCONem w tej postaci jaką możecie obserwować (byłby krótszy i z udziałem mniejszej ilości zagranicznych prelegentów oraz z dużym udziałem prezentacji marketingowych).

Na całe szczęście udało nam się zminimalizować stawkę do poziomu, który część osób naprawdę zadowala (pozostałe zawsze będą narzekać, że jest zbyt drogo :P). 389 PLN to chyba stawka do przełknięcia dla wszystkich firm informatycznych w kraju i dla większości developerów (już nie narzekajcie jak to mało zarabiacie), w ten sposób prawdopodobnie odrzucamy główny argument Waszego PM’a, który pewnie zawsze mówi Wam, że wyjazd na zagraniczne konferencje to zbyt duży koszt :)

Faktycznie porównując z takimi konferencjami jak QCon, Jazoon czy też ApacheCon to GeeCON jest śmiesznie tani. Oczywiście wiadomo, że te konferencje są sporo większe od GeeCON ale z drugiej strony i tak możecie uczestniczyć w jednej ścieżce w jednej chwili co sprawia, że w przeliczeniu na godzinę prezentacji GeeCON to zdecydowanie mniejszy koszt. I o to właśnie wszystkim organizatorom chodziło, nie organizować imprezy dla zysku a tylko dlatego aby dostarczyć Wam godne uwagi wydarzenie “javowe”.

Jeśli już dotarliście do tego miejsca to mam nadzieję, że podzielicie się swoimi uwagami i spostrzeżeniami, zarówno jeśli chodzi o GeeCON, jak i inne rzeczy które mogą się Wam wydać istotne w kontekście tego wpisu. Na koniec jeszcze chciałem wszystkich zaprosić do udziału w GeeCON i nie tylko, bo już wielkimi krokami zbliża się kolejna Javarsovia i Java4People :)

February 27, 2009 | 3 Comments  |

Java Servlet 3.0 Specification czyli nadchodzą zmiany…

Ostatnio przeglądałem listę specyfikacji nad którymi trwają prace w ramach Java Community Process, w ten sposób natrafiłem na specyfikację oznaczoną JSR 315. Zapewne to oznaczenie kodowe większości z Was nic nie mówi, więc przytoczę tu pełną nazwę którą jest “Java Servlet 3.0 Specification”. Tak, dokładnie specyfikacja oznaczona jako JSR 315 dotyczy niczego innego jak właśnie nowej wersji servletów, oznaczonej numerem 3.0.
Nowa wersja nową wersją i różnie to wygląda w przypadku różnych technologii, jednak wydaje mi się, że zmiany które będą wprowadzone w ramach kolejnej wersji servletów są na tyle istotne, iż warto je tutaj przybliżyć.

Servlety 3.0 wniosą powiew świeżości, oto część zmian jakie nadchodzą:

  • użycie adnotacji do konfiguracji servletów i filtrów
  • “web fragments”, czyli dotychczasowa konfiguracja web.xml z wykorzystaniem wielu plików
  • metody do dodawania servletów i filtrów
  • asynchroniczne przetwarzanie

Opiszę teraz pokrótce poszczególne z nich:

Użycie adnotacji do konfiguracji servletów i filtrów

Tak naprawdę oprócz konfiguracji servletów i filtrów możemy również skonfigurować listenery.
Pakiet zawierający potrzebne adnotacje nosi nazwę javax.servlet.annotation.
Znajdują się w nim m.in. następujące adnotacje:

  • @WebServlet
  • @ServletFilter
  • @WebServletContextListener

Oczywiście servlety, filtry jak i listenery muszą implementować/rozszerzać odpowiednie interfejsy/klasy (tak jak to było do tej pory), zespół pracujący nad tą specyfikacją planował wcześniej zrezygnować z konieczności rozszerzania klasy javax.servlet.http.HttpServlet na rzecz samego oznaczenia klasy servletu adnotacją @Servlet (obecnie jest @WebServlet)oraz dostarczenia metod przyjmujących jako parametr HttpServletRequest oraz HttpServletResponse. Oczywiście w takim przypadku konieczne byłyby dodatkowe adnotacje jak np. @GET czy też @POST w celu oznaczenia czy dana metoda zdefiniowana w ramach servletu obsługuje odpowiednią metodę HTTP. Wcześniejsze podejście umożliwiało w ten sposób zastosowanie zwykłych klas POJO jako klas servletów. Nie jestem do końca przekonany do takiego podejścia, nie to żebym był tradycjonalistą, jednak taka elastyczność wydaje mi się zbędna w tym przypadku w dodatku wprowadza pewien ład. Wracając jednak do adnotacji to będą one obok standardowego pliku web.xml drugim sposobem na definicję parametrów servletu, servlet w ten sposób oznaczony będzie automatycznie wykrywany (oczywiście o ile będzie się znajdował w classpath) przez kontener servletów zgodny ze specyfikacją Java Servlet 3.0. Warto tu nadmienić, iż wzorcową implementacją (RI - reference implementation) kontenera zgodnego z tą specyfikacją ma być Glassfish w wersji 3 (to chyba nikogo nie dziwi).

Aby obrazowo przedstawić zastosowanie adnotacji @WebServlet proponuję spojrzeć na poniższy przykład:

@WebServlet(
        name=“sampleservlet”,
        urlPatterns={“/sampleservlet”},
        initParams={
                @InitParam(name=“paramname”, value=“paramvalue”)
        }
)
public class TestServlet extends javax.servlet.http.HttpServlet {
        //tu kod servletu
}

Jak widzicie w powyższym przykładzie zdefiniowałem nazwę servletu “sampleservlet” oraz mapowanie “/sampleservlet“, podałem też przykładowy parametr który może zostać użyty przy inicjalizacji servletu. Tak zdefiniowany servlet musimy umieścić w zasięgu naszego classpath, kontener zgodny ze specyfikacją 3.0 servletów powinien sam wykryć taki servlet i go odpowiednio zainicjować. Oczywiście można wyłączyć obsługę automatycznego wykrywania servletów, filtrów czy też listenerów, jest to jednak całkiem wygodna opcja, którą z uwagi na bezpieczeństwo powinno się używać z rozwagą.

Web fragments

Pewnie nie raz spotykaliście się z przydługawymi plikami web.xml (tzw. deskryptory aplikacji), w których skonfigurowana była cała masa servletów, filtrów, listenerów.
Obsługa takiego pliku może niejednokrotnie przysporzyć problemów, dodatkowe problemy pojawiają się
gdy chcemy skonfigurować jakiś framework, którego jeszcze nie znamy.
Tutaj z pomocą przyjdzie nam JSR 315 i tzw. “web fragments”. Pewnie już domyślacie się do czego to służy? Otóż web fragments mają w zamiarze umożliwić dzielenie konfiguracji która znajduje się w jednym pliku konfiguracyjnym na wiele “fragmentów”, z których zostanie wczytana kompletna konfiguracja.
W praktyce oznacza to, iż we frameworkach takich jak np. Struts 2 a właściwie w ich archiwum JAR będzie można umieścić taki fragment deskryptora. Tak umieszczony fragment będzie mógł zostać wykryty przez kontener servletów i odpowiednio wykorzystany np. do domyślnej konfiguracji frameworku. Oczywiście będzie tu przyjęta odpowiednia konwencja, plik taki musi się nazywać web-fragment.xml, musi być też umieszczony w katalogu META-INF biblioteki.
Prawda, że przyjemne? A jak to jeszcze ułatwi życie :) Oczywiście może się tutaj pojawić problem z bezpieczeństwem jak automatyczna inicjalizacja rzeczy o których moglibyśmy sobie nie zdawać sprawy.

Kolejna rzecz to:

Metody do dodawania servletów i filtrów

Tak, będziemy mogli użyć specjalnych metod, których przeznaczeniem będzie inicjalizacja np. servletu.
Będą to metody addServlet oraz addFilter.

Czas na ostatnią z wymienionych powyżej nowości (oczywiście znajdziecie tego więcej na stronie specyfikacji), a mianowicie:

Asynchroniczne przetwarzanie

To jedna z najważniejszych zmian w porównaniu do wersji 2.5. Znacie dobrze te sytuacje w których Wasz servlet musi wywołać wywołanie usługi sieciowej albo przeprowadzić jakąś inną operację zajmującą więcej czasu, w takie sytuacji klient wywołujący servlet musi czekać aż operacja zostanie wykonana. Właśnie w takim przypadku przydaje się wywołanie asynchroniczne, i tutaj okazuje się, że twórcy specyfikacji 3.0 servletów wprowadzają do niej asynchroniczne przetwarzanie. Ale jak to ma wyglądać w praktyce? Obecna wersja specyfikacji wprowadza pojęcie kontekstu wywołania asynchronicznego, reprezentowanego przez klasę AsyncContext zawiera on informacje o otrzymanym żądaniu i odpowiedzi. Oczywiście w celu użycia wywołania asynchronicznego na servlecie należy go odpowiednio skonfigurować, czyli ustawić jeden atrybut o nazwie supportAsync, tak skonfigurowany servlet (lub filtr) będzie mógł już służyć do obsługi wywołań asynchronicznych. Ponieważ po wykonaniu operacji przez servlet może się okazać konieczne wykonanie dodatkowych czynności, autorzy specyfikacji JSR 315 wprowadzają nowy rodzaj interfejsu listenera AsyncListener którego implementację należy dodać do requestu. Implementacja taka będzie posiadała co najmniej dwie metody o nazwach onComplete oraz onTimeout (zdefiniowane w ramach interfejsu), pierwsza zostanie wywołana w przypadku zakończenia przetwarzania requestu na czas, druga w przypadku gdy wystąpi timeout (wartość timeoutu w milisekundach podamy w parametrze servletu o nazwie asyncTimeout).

To wszystko w tym wpisie, więcej informacji na temat Java Servlet 3.0 Specification znajdziecie na stronie Java Community Process.

February 8, 2009 | 3 Comments  |

Tworzenie RESTful Web Services przy użyciu Apache CXF

Na grupie dyskusyjnej Lódź JUG Paweł Włodarski zapoczątkował temat “Usługi typu REST “. W jednej z odpowiedzi napisałem, iż do tworzenia usług za pomocą JAX-RS można wykorzystać framework Apache CXF, w dzisiejszym wpisie przedstawię w jaki sposób zaimplementować taką usługę używając właśnie Apache CXF oraz Spring Framework.

Utwórzmy nasz projekt przy użyciu Maven 2:

mvn archetype:create -DgroupId=org.holewa.restapp -DartifactId=restapp -DarchetypeArtifactId=maven-archetype-webapp

Po chwili powinniśmy zobaczyć utworzoną strukturę aplikacji, która znajduje się w katalogu restapp.
Ponieważ w naszym projekcie użyjemy frameworków Spring i Apache CXF stąd też musimy je dodać do naszego pom.xml, po modyfikacji nasz pom powinien wyglądać następująco:

<project xmlns=“http://maven.apache.org/POM/4.0.0″
         xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
         xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0
                                        http://maven.apache.org/maven-v4_0_0.xsd”
>

    <modelVersion>4.0.0</modelVersion>
    <groupId>org.holewa.restapp</groupId>
    <artifactId>restapp</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <build>
        <finalName>restapp</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
            <version>2.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-bundle-jaxrs</artifactId>
            <version>2.1.3</version>
        </dependency>
    </dependencies>
    <repositories>
        <repository>
            <id>Atlassian</id>
            <layout>default</layout>
            <url>https://m2proxy.atlassian.com/repository/public</url>
        </repository>
    </repositories>
</project>

Powyższy fragment zawiera zależności od Spring Framework i Apache CXF JAX-RS bundle, czyli specjalnej paczki Apache CXF przeznaczonej do implementacji RESTful Web Services w oparciu o specyfikację JAX-RS.
Dodałem również jedno repozytorium Maven 2, jest ono potrzebne aby Maven mógł pobrać zależność od Apache Abdera (jednej z zależności Apache CXF) i wtyczkę maven-compiler-plugin zdefiniowaną dla wersji 1.6 Javy gdyż kod, który zobaczycie w tym przykładzie był kompilowany właśnie z tą wersją.

Teraz czas na konfiguracje deskryptora naszej aplikacji webowej, modyfikujemy plik web.xml sprowadzając go do następującej postaci:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>REST Application</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/applicationContext.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>
            org.apache.cxf.transport.servlet.CXFServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>
</web-app>

Zdefiniowaliśmy tutaj listener który odpowiada za uruchomienie kontakstu Spring’a oraz servlet Apache CXF, będzie on odpowiedzialny za obsługę wywołań naszych usług.

Utworzymy teraz dwie klasy o nazwach Element i Elements, które zawierać będą adnotacje JAXB.

Klasa Element:

package org.holewa.restapp;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = “element”)
class Element {

    private Integer id;

    private String name;

    public Element() {
    }

    public Element(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

Klasa Elements:

package org.holewa.restapp;

import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlRootElement(name = “elements”)
public class Elements {

    @XmlElements({
        @XmlElement(name = “element”, type = Element.class)
    })
    List<Element> elements;

    @XmlTransient
    public List<Element> getElements() {
        return elements;
    }

    public void setElements(List<Element> elements) {
        this.elements = elements;
    }
}

Klasy te zostaną wykorzystane do przedstawienia prostych możliwości interfejsu REST’owego, posłużą one jako przykładowe obiekty zwracane przez usługę RESTful web services.

Javowa implementacja tej usługi znajduje się poniżej:

Klasa ElementEndpointImpl:

package org.holewa.restapp;

import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;

public class ElementEndpointImpl {

    @Context
    UriInfo uriInfo;
    private List<Element> elements;

    public ElementEndpointImpl() {
        elements = new ArrayList<Element>();
        elements.add(new Element(1, “First”));
        elements.add(new Element(2, “Second”));
    }

    @ProduceMime(value = “application/xml”)
    @GET
    @Path(value = “/elements”)
    public Elements getElements() {
        Elements result = new Elements();
        result.setElements(elements);
        return result;
    }

    @ProduceMime(value = “application/xml”)
    @GET
    @Path(value = “/elements/{id}”)
    public Element getElement(@PathParam(value = “id”) Integer id) {
        Element result = null;
        for (Element e : elements) {
            if (e.getId().equals(id)) {
                result = e;
                break;
            }
        }
        return result;
    }
   
}

Na koniec konfiguracja Apache CXF w pliku applicationContext.xml:

<?xml version=“1.0″ encoding=“UTF-8″?>
<beans xmlns=“http://www.springframework.org/schema/beans”
       xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
       xmlns:jaxrs=“http://cxf.apache.org/jaxrs”
       xmlns:cxf=“http://cxf.apache.org/core”
       xsi:schemaLocation=“http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://cxf.apache.org/core
        http://cxf.apache.org/schemas/core.xsd
        http://cxf.apache.org/jaxrs
        http://cxf.apache.org/schemas/jaxrs.xsd”
>

    <import resource=“classpath:META-INF/cxf/cxf.xml”/>
    <import resource=“classpath:META-INF/cxf/cxf-servlet.xml”/>
    <import resource=“classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml”/>

    <bean id=“elementEndpoint” class=“org.holewa.restapp.ElementEndpointImpl”/>

    <jaxrs:server id=“restWSServer” address=“/”>
        <jaxrs:serviceBeans>
            <ref bean=“elementEndpoint”/>
        </jaxrs:serviceBeans>
    </jaxrs:server>

    <cxf:bus>
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus>

</beans>

To już wszystko, budujemy naszą aplikację za pomocą Maven’a:

mvn clean package

W wyniku otrzymujemy plik restapp.war, skopiujmy do go katalogu webapps w Tomcacie lub innym kontenerze servletów.

Po uruchomieniu Tomcata na standardowym porcie i podaniu w przeglądarce następującego adresu:

http://localhost:8080/restapp/services/elements/

Otrzymacie taki oto wynik:

<?xml version=“1.0″ encoding=“UTF-8″ standalone=“yes”?>
<elements>
    <element>
        <id>1</id>
        <name>First</name>
    </element>
    <element>
        <id>2</id>
        <name>Second</name>
    </element>
</elements>

Gdy wejdziecie na ten adres:

http://localhost:8080/restapp/services/elements/1

Zwrócona zostanie odpowiedź zawierająca tylko jeden “element”, którego id jest równe 1:

<?xml version=“1.0″ encoding=“UTF-8″ standalone=“yes”?>
<element>
    <id>1</id>
    <name>First</name>
</element>

To chyba wszystko na dzisiaj, jako ćwiczenie polecić mogę zmianę tej usługi tak aby wywołanie listy zwracało jedynie podstawowe informacje o wszystkich elementach, a wśrod nich linki do interfejsu REST’owego zwracającego szczegóły poszczególnych elementów.

January 9, 2009 | 4 Comments  | Tags: , , ,

Inicjalizacja danych w zależności od trybu uruchomienia aplikacji Grails

Pisząc aplikacje w Grails niejednokrotnie stajecie przed koniecznością wykonania pewnej logiki podczas startu aplikacji, logika taka to np. dodanie użytkownika do bazy danych, zapisanie podstawowych i zarazem koniecznych do działania aplikacji danych w bazie.
Logika taka powinna zostać zawarta w klasie BootStrap znajdującej się w katalogu conf Waszej aplikacji. Początkowa postać tej klasy to:

class BootStrap {

     def init = { servletContext ->
     }
     def destroy = {
     }
}

W bloku init możecie umieścić kod, który zostanie wywołany podczas uruchomienia aplikacji, blok destroy powinien zawierać operacje, które mają zostać wykonane podczas zakończenia aplikacji - zakończenie takie musi odbyć się w sposób standardowy, zakończenie wykonania aplikacji spowodowane sytuacją nadzwyczajną nie spowoduje wykonania instrukcji zawartych w bloku destroy.

Dodajmy do powyższej klasy kod, który zostanie wykonany podczas startu naszej aplikacji:

class BootStrap {

     def init = { servletContext ->
          new User(username: ‘admin’, password: ‘admin’).save()
     }
     def destroy = {
     }
}

W ten sposób zapisujemy użytkownika o loginie admin i haśle admin, oczywiście musimy mieć utworzoną klasę domenową User z odpowiednimi polami ;)

Teraz podczas startu naszej aplikacji nasz przykładowy użytkownik będzie zawsze dodawany do bazy,
pytanie co zrobić gdy chcemy wykonać logikę w zależności od środowiska w którym uruchamiamy aplikację, jak wiadomo standardowo mamy trzy środowiska: development, test, production. Uruchomienie aplikacji w konfiguracji odpowiadającej określonemu środowisku odbywa się poprzez wykonanie komendy grails run-app z odpowiednim parametrem, np.:

grails prod run-app

Powyższa komenda uruchomi aplikację w trybie produkcyjnym.
Dobra, pojawia się teraz pytanie jak w klasie BootStrap sprawdzić w jakim trybie została uruchomiona nasza aplikacja?
Odpowiedź jest bardzo prosta, użyjemy do tego celu takiego oto fragmentu kodu:

def env = GrailsUtil.environment

Jest to wywołanie statycznej metody getEnvironment, znajdującej się w klasie GrailsUtil (dla niewtajemniczonych wywołania getterów w Groovy wyglądają jak odwołania do pól klasy). Teraz zmienna env będzie zawierała wartość dzięki której będziemy w stanie zidentyfikować rodzaj trybu w jakim uruchomiona została aplikacja, będą to odpowiednio: test, development, production dla trybów: testowego, developerskiego, produkcyjnego.

Teraz nie pozostaje nam nic innego jak uzależnić od zwróconej wartości wykonanie odpowiedniego kodu, można tu standardowo zastosować instrukcję if-else, można też to zrobić sprytniej i wykorzystać dobrodziejstwa jakie daje nam Groovy:

class BootStrap {

     def init = { servletContext ->
        def env = GrailsUtil.environment
        InitializeData.“$env”()
     }
     def destroy = {
     }
}

Co oznacza powyższy blok kodu, a w szczególności tajemnicza konstrukcja InitializeData.”$env”()?
A więc dzięki niej w bardzo ciekawy sposób rozdzieliliśmy wykonanie kodu zależnego od trybu w którym została uruchomiona aplikacja, umieszczając go w klasie InitializeData w jej statycznych metodach:

class InitializeData {

       static void development() {
           //kod wykonywany dla środowiska developerskiego
       }

       static void test() {
           //kod wykonywany dla środowiska testowego
       }

       static void production() {
           //kod wykonywany dla środowiska produkcyjnego
       }
       
}

Zastosowana konstrukcja InitializeData.”$env”() służy do wywołania statycznej bezparametrowej metody o nazwie odpowiadającej wartości zmiennej env, która została zdefiniowana w klasie InitializeData

December 14, 2008 | 2 Comments  |

Groovy - przydatne informacje

Dzisiaj kilka przydatnych linków dla wszystkich zainteresowanych Groovy:

  • Strona domowa projektu
  • Strona projektu Groovy, znajdziecie tam specyfikację języka, tutoriale i masę linków do różnego typu blogów i portali poświęconych językowi Groovy.

  • Grails
  • Strona domowa najpopularniejszego frameworku webowego napisanego w Groovy

  • Groovy on Grails
  • Agregator blogów o Groovy i Grails.

  • Gradle
  • Narzędzie do budowania aplikacji stworzonych przy pomocy języka Groovy (i nie tylko).

  • GroovyMag
  • Magazyn developerów Groovy, bardzo ciekawy lecz płatny :)

  • Grails Podcast
  • Podcast poświęcony Groovy i Grails.

  • Hosting aplikacji napisanych w Grails
  • Najlepszy hosting aplikacji Grails.

  • Groovy Zone
  • Wydzielona część DZone w całości poświęcona Groovy.

  • Grails Jobs
  • Szukasz pracy jako deweloper Grails? W takim razie ta strona jest warta Twojej uwagi.

  • Groovy Blogs
  • Kolejny agregator blogów o Groovy.

  • Grails Tutorials
  • BARDZO przydatna strona z linkami HOWTO w Groovy i Grails.

  • IntelliJ IDEA
  • Bezsprzecznie najlepsze środowisko do Groovy i Grails.

  • About Groovy
  • Newsy, Podcasty, Książki o Groovy i Grails - wszystko w jednym miejscu.

  • Grails Crowd
  • Szukasz projektów napisanych w Groovy lub Grails? Musisz odwiedzić powyższą stronę.

  • Grails success stories
  • Lista tzw. “success stories” na oficjalnej stronie Grails.

  • Groovy Awards
  • Kto jest najlepszym developerem Groovy? Sprawdź na Groovy Awards.

  • Groovy Live
  • Znacie Try Ruby!? Jeśli tak to czas na Groovy Live, co prawda w chwili obecnej po chińsku ale w niczym to nie przeszkadza :)

December 12, 2008 | 2 Comments  |

GeeCON - pierwsza międzynarodowa konferencja o Javie oficjalnie ogłoszona!

Miło mi oznajmić, że z dniem dzisiejszym oficjalnie zostały ogłoszone prace nad pierwszą międzynarodową konferencją poświęconą Javie i RIA w Polsce. Konferencja ta nazywa się GeeCON i odbędzie się w maju przyszłego roku w Krakowie. Jest ona organizowana przesz Polską Grupę Użytkowników Języka Java, Czeską Grupę Użytkowników Języka Java oraz Poznańską Grupę Użytkowników Języka Java.

Konferencja potrwa dwa dni, podczas których uczestnicy będą mieli możliwość spotkania światowej sławy specjalistów, wśród nich Guillaume Laforge, Charles Nutter oraz Scott Davis i wielu innych. Mam nadzieję, że wydarzenie to przejdzie do pamięci wszystkich sympatyków języka Java w naszym kraju.

Aby się zbytnio nie rozpisywać zapraszam Was na oficjalną stronę konferencji.

December 8, 2008 | 6 Comments  |

ROOT application context w aplikacji Grails

Pisząc ostatnio aplikacje w Grails, stanąłem przed problemem zmiany kontekstu aplikacji z domyślnego na ROOT, czyli chciałem aby moja aplikacja uruchamiała się po wpisaniu adresu serwera i portu, bez konieczności podawania specjalnej nazwy kontekstu. Zadanie wydawałoby się proste, mógłbym się bawić w konfigurowanie aplikacji w kontenerze w którym uruchamiałem aplikację, jednak chciałem to zrobić w sposób zalecany przez twórców Grails (wtedy nie wiedziałem, że tak ciężko będzie znaleźć informację na ten temat).
Po dość uciążliwym googlowaniu natrafiłem na rozwiązanie. Okazało się, że ustawienie kontekstu aplikacji sprowadza się do zdefiniowania odpowiedniego wpisu w pliku Config.groovy:

grails.app.context = “/”

W ten oto sposób możecie ustawić kontekst aplikacji na tzw. ROOT.

Dziwi mnie fakt, że dokumentacja Grails nie informuje o tym, moim zdaniem użytecznym parametrze, ja odnalazłem informację o nim w jednym z wpisów w dedykowanym Grails’om systemie obsługi zgłoszeń.
Dodam jeszcze, że w chwili pisania tego wpisu Google pokazuje tylko 123 wyniki dla zapytania “grails.app.context”, widać więc, że rozwiązanie to jest mało znane.

December 7, 2008 | Leave a Comment  |

URL mapping w Grails

Dzisiaj będzie szybko aczkolwiek treściwie :) Podczas pisania aplikacji w Grails niejednokrotnie pojawia się potrzeba zmienienia mapowania URLi. Mapowanie takie definiujemy w pliku UrlMappings w katalogu conf naszej aplikacji. Plik taki ma początkowo następującą postać:

class UrlMappings {
    static mappings = {
        “/$controller/$action?/$id?”
        {
            constraints {
                // apply constraints here
            }
        }
}

Załóżmy jednak, że chcielibyśmy aby pod następującą ścieżką:

/site/id

Była dostępna strona która będzie rozpoznawana za pomocą parametru id.
Mapowanie takie możemy zdefiniować za pomocą następującego wpisu w pliku UrlMapping:

“/site/$id”
{
        controller = “main”
        action = “showPage”
        constraints {
              // apply constraints here
        }
}

Mapowanie to sprawi, że po wywołaniu adresu kończącego się na /site/home zostaniemy przekierowani do kontrolera o nazwie main (nazwa klasy to MainController) i zdefiniowanej w nim akcji showPage. Z poziomu akcji możemy pobrać identyfikator strony, uczynimy to w następujący sposób:

def showPage = {
        [pageInstance: Page.findByPageId(params.id)]
}

Jak widać w powyższym kodzie, parametr id zdefiniowany w mapowaniu URL’a będzie dostępny w params pod tą samą nazwą. W ten sposób pobierzemy stronę której parametr pageId jest równy home gdyż taka właśnie wartość odpowiada naszemu parametrowi id.
Dodatkowo w sekcji constraints możemy zdefiniować warunki dla których nasz URL będzie mapowany, np.:

“/site/$id”
{
        controller = “main”
        action = “showPage”
        constraints {
              id(matches:/[A-Z]{5}/)
        }
}

Dodanie id(matches:/[A-Z]{5}/) do bloku constraints spowoduje, iż jako parametr id podane będą mogły być wartości spełniające wyrażenie regularne, w tym wypadku identyfikator id musi się składać z pięciu liter z których dopuszczalne to A-Z.

Ostatnia ważna rzecz przy mapowaniu URLi to zdefiniowanie parametru będącego częścią URL’a jako parametru opcjonalnego:

“/site/$id?”
{
        controller = “main”
        action = “showPage”
        constraints {
             
        }
}

Zmieniliśmy tutaj ciąg znaków “/site/$id” na “/site/$id?, dodanie pytajnika oznacza, że parametr ten jest opcjonalny. Niezależnie od tego czy go podamy, czy też nie to zostaniemy przekierowani do akcji showPage w kontrolerze MainController.

December 5, 2008 | Leave a Comment  |

Cube°n - odpowiednik Mylyn dla NetBeans?

Tym razem przedstawię jeden z projektów w którym biorę udział (choć to może nad wyrost powiedziane :)), chodzi mi oczywiście o Cube°n (Task-Focused Interface for Netbeans).
Cube°n to inspirowana na Eclipse’owym Mylyn wtyczka do NetBeans. Wtyczka ta została stworzona przez członka NetBeans Dream Team - Anuradha Gunasekara, do commiterów projektu należą również inni członkowie NB Dream Team jak również pracownicy Sun’a co powinno oznaczać, że nie jest to tylko chwilowy projekt.

W chwili obecnej pozwala ona na zarządzanie zadaniami zarówno lokalnie jak i za pomocą systemów Jira i Trac, dodatkowo do jej podstawowych funkcjonalności należą:

  • tworzenie zapytań, które pozwalają na wyświetlenie listy zadań wg. określonych kryteriów
  • powiązanie wybranych fragmentów kodu z określonym zadaniem
  • synchronizacji lokalnych zadań ze zdalnymi (zdefiniowanymi z zdalnych systemach) zadaniami
  • możliwość dodawania komentarzy do zadań
  • inne funkcjonalności opisane na tej stronie

W planach jest również support dla Bugzilli, niestety implementacja tej funkcjonalności przypadła mojej skromnej osobie, a ponieważ jak zwykle brakuje mi czasu stąd jej rozwój zatrzymał się chwilowo w miejscu (taka przypadłość projektów open-source :( ).

Jeśli jednak jesteście zainteresowani tą wtyczką to szczególnie Was zachęcam do jej pobrania i zainstalowania, sam fakt, iż znalazła się ona w finale NetBeans Innovators Grant Contest świadczy o tym, że również ludzie z NetBeans widzą w niej potencjał (wtyczka dostała również nagrodę za jakość wykonania).

Więcej informacji na temat najnowszej wersji Cube°n’a znajdziecie w tym wpisie Anuradhy oraz na oficjalnej stronie projektu. W szczególności zapraszam na stronę z planem rozwoju oraz grupę użytkowników na której możecie zgłaszać pomysły/uwagi.

Na koniec życzę sobie i Wam szybkiego ukończenia modułu obsługującego repozytoria Bugzilla :)

November 29, 2008 | 2 Comments  |

Page 1 of 812345»...8