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 ![]()
Przedsmak szkoleń tutaj, więcej szczegółów (w tym cena) w najbliższym czasie.
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
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:
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.
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:
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:
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:
"-//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:
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:
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:
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:
<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:
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:
Otrzymacie taki oto wynik:
<elements>
<element>
<id>1</id>
<name>First</name>
</element>
<element>
<id>2</id>
<name>Second</name>
</element>
</elements>
Gdy wejdziecie na ten adres:
Zwrócona zostanie odpowiedź zawierająca tylko jeden “element”, którego id jest równe 1:
<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.
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:
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:
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.:
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:
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:
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:
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
Groovy - przydatne informacje
Dzisiaj kilka przydatnych linków dla wszystkich zainteresowanych Groovy:
- Strona domowa projektu
- Grails
- Groovy on Grails
- Gradle
- GroovyMag
- Grails Podcast
- Hosting aplikacji napisanych w Grails
- Groovy Zone
- Grails Jobs
- Groovy Blogs
- Grails Tutorials
- IntelliJ IDEA
- About Groovy
- Grails Crowd
- Grails success stories
- Groovy Awards
- Groovy Live
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.
Strona domowa najpopularniejszego frameworku webowego napisanego w Groovy
Agregator blogów o Groovy i Grails.
Narzędzie do budowania aplikacji stworzonych przy pomocy języka Groovy (i nie tylko).
Magazyn developerów Groovy, bardzo ciekawy lecz płatny
Podcast poświęcony Groovy i Grails.
Najlepszy hosting aplikacji Grails.
Wydzielona część DZone w całości poświęcona Groovy.
Szukasz pracy jako deweloper Grails? W takim razie ta strona jest warta Twojej uwagi.
Kolejny agregator blogów o Groovy.
BARDZO przydatna strona z linkami HOWTO w Groovy i Grails.
Bezsprzecznie najlepsze środowisko do Groovy i Grails.
Newsy, Podcasty, Książki o Groovy i Grails - wszystko w jednym miejscu.
Szukasz projektów napisanych w Groovy lub Grails? Musisz odwiedzić powyższą stronę.
Lista tzw. “success stories” na oficjalnej stronie Grails.
Kto jest najlepszym developerem Groovy? Sprawdź na Groovy Awards.
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
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.
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:
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.
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ć:
static mappings = {
“/$controller/$action?/$id?”
{
constraints {
// apply constraints here
}
}
}
Załóżmy jednak, że chcielibyśmy aby pod następującą ścieżką:
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:
{
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:
[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.:
{
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:
{
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.
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 ![]()



