wtorek, 31 marca 2009

Jazoon Cutting Edge

Jeżeli zawsze chciałeś opowiedzieć coś ciekawego programistom Java, świetnie trafiłeś. Masz pomysł na prezentację, ale boisz się, że nie będziesz w stanie zająć 60, czy 90 minut?

Jazoon Cutting Edge - These 20 minutes talks address the most recent developments in the Java industry.
Call for papers: 15 April 2009
Submission deadline: 15 May 2009

i wszystko wiadomo.

Do zgarnięcia darmowa wejściówka czerwcowy Jazoon i 50% zniżki dla osoby towarzyszącej (również w prezentacji).
Miło byłoby usłyszeć kogoś z Polski.

Może Jacek się zgłosi, ze swoimi zabawkami? Kto nie był dziś na spotkaniu warszawskiego JUGa niech żałuje.

niedziela, 22 marca 2009

Ziarna sesyjne - czar prysł.

Dopiero co zachwycałem się nad lokalnym i zdalnym sposobem wywoływania usług ziaren EJB. Przyszła wiosna, śnieg stopniał i czar prysł. Otóż pomiędzy wywołaniem danej metody poprzez interfejs oznaczony adnotacją @Local a wywołaniem za pomocą interfejsu @Remote mogą być subtelne różnice. Bierze się to stąd, że parametry metod wywoływanych lokalnie (@Local) przekazywane są poprzez referencje, parametry metod zdalnych (@Remote) przez wartość.

Zobaczmy o co chodzi na podstawie prostego przykładu. Stworzę z tej okazji w NetBeans IDE 6.5.1 projekt ziarna EJB oraz projekt klienta EJB.

Zaczynam od aplikacji EJB:
Z menu File wybieram pozycję New Project:


następnie wybieram kategorię Java EE i projekt EJB Module
klikam Next, po czym na zakładce Server and Settings dodaję nową konfigurację serwera, klikając przycisk Add...

Przykład będę uruchamiał na serwerze JBoss 4.2.2.GA


więc wskazuję jego położenie na dysku:


klikam Next> i Finish. Projekt gotowy.

W projekcie stworzę proste ziarno, które będzie udostępniało metodę dodającą podany jako parametr element do podanej jako parametr kolekcji:


public Collection add(Collection collection, Object element) {
collection.add(element);
return collection;
}


Ziarno będzie implementowało interfejs lokalny oraz zdalny. Ziarno oraz interfejsy przedstawiają się następująco:

Kod ziarna StatelessBean:

package pl.matt.session;

import java.util.Collection;
import javax.ejb.Local;
import javax.ejb.Remote;


@javax.ejb.Stateless
@Remote(StatelessRemote.class)
@Local(StatelessLocal.class)
public class StatelessBean implements StatelessRemote, StatelessLocal {

public Collection add(Collection collection, Object element) {
collection.add(element);
return collection;
}

}


interfejs zdalny StatelessRemote:

package pl.matt.session;

import java.util.Collection;
import javax.ejb.Remote;

public interface StatelessRemote {

Collection add(Collection collection, Object element);

}


i identyczny interfejs lokalny StatelessLocal:

package pl.matt.session;

import java.util.Collection;
import javax.ejb.Remote;

public interface StatelessLocal {

Collection add(Collection collection, Object element);

}


Całość uzupełnia ziarno testujące dodawanie elementów do kolekcji, które próbuje zarówno zdalnie jak i lokalnie dodać 3 napisy do listy:

interfejs TestRemote:

package pl.matt.session;

public interface TestRemote {
void test();
}


oraz jego implementacja:


package pl.matt.session;

import java.util.ArrayList;
import java.util.List;
import javax.ejb.Remote;
import javax.naming.Context;
import javax.naming.InitialContext;

@javax.ejb.Stateless
@Remote(TestRemote.class)
public class TestBean implements TestRemote {

public void test() {
try {
Context context = new InitialContext();
StatelessLocal statelessLocal = (StatelessLocal) context.lookup("StatelessBean/local");
StatelessRemote statelessRemote = (StatelessRemote) context.lookup("StatelessBean/remote");
List<String> localList = new ArrayList();
statelessLocal.add(localList, "1");
statelessLocal.add(localList, "2");
statelessLocal.add(localList, "3");
System.out.println("local list: " + localList);

List<String> remoteList = new ArrayList();
statelessRemote.add(remoteList, "1");
statelessRemote.add(remoteList, "2");
statelessRemote.add(remoteList, "3");
System.out.println("remote list: " + remoteList);
} catch (Exception e) {
e.printStackTrace();
}
}
}


Do wywołania metody ziarna TestBean potrzebuję klienta EJB. Tworzę go wybierając ponownie pozycję New Project... z menu File. Następnie z kategorii Java EE wybieram projekt Enterprise Application Client:

Do tak stworzonego projektu dodaję jako zależność stworzony uprzednio projekt EJB


Dzięki temu, będę w nim mógł uzyskać dostęp do interfejsu testującego. Całość kodu klienta zawarta jest w metodzie main():


package pl.matt;

import javax.naming.Context;
import javax.naming.InitialContext;
import pl.matt.session.TestRemote;

public class Main {

public static void main(String[] args) {
try {
System.out.println("start");
Context context = new InitialContext();
TestRemote test = (TestRemote) context.lookup("TestBean/remote");
test.test();
System.out.println("finished");
} catch (Exception e) {
e.printStackTrace();
}

}
}


Pozostało uruchomienie i przekonanie się, jak to wszystko będzie działać. Klikam prawym przyciskiem myszy na projekcie EJB, wybieram opcję Run. Następnie to samo robię na projekcie klienta EJB. JBoss się uruchamia, po chwili widzę w konsoli:


22:27:55,969 INFO [STDOUT] local list: [1, 2, 3]
22:27:55,974 INFO [STDOUT] remote list: []


2 razy wywołałem tę samą metodę, raz przez interfejs @Remote, raz przez @Local i wynik jej działania jest inny. Do kolekcji, przekazanej przez wartość elementy nie zostały dodane (tzn. zostały, ale do kopii tej kolekcji, przekazanej do ziarna EJB).

Trzeba uważać.