środa, 29 października 2008

Why EJB 3.x rox by Adam Bien

Adam Bien opublikował wczoraj artykuł w serwisie javaworld.com na temat EJB 3. Zawarł w nim swój punkt widzenia dlaczego lubi EJB, wyjaśnia jakie były jego bolączki i jak zostały one sprawnie rozwiązane w najnowszym wydaniu (największa radość jest chyba z braku konieczności pisania setek linii w XMLu aby skonfigurować aplikację). Wspomina także o Java Persistence, wstrzykiwaniu zależności oraz zasobów. Najwięcej miejsca jednak poświęcił interceptorom (metody przechwytujące), opisał sposób ich definiowania oraz możliwe wykorzystanie. Cały artykuł przy tym jest bogato zdobiony przykładami.
Polecam się z nim zapoznać ;-)

EJB3 : From Legacy technology to secret weapon
Adam Bien's Weblog

wtorek, 28 października 2008

Uzyskanie dostępu do EntityManager z poziomu Java SE

Z JPA możemy korzystać nie tylko na serwerze aplikacyjnym ale także w aplikacjach desktopoych w poczciwym Java SE. Jednak aby tego dokonać nie możemy użyć wstrzykiwania tylko musimy skorzystać z klasy javax.persistence.Persistence aby za pomocą metody createEntityManagerFactory utworzyć obiekt typu EntityManagerFactory. Metoda przyjmuje jeden lub dwa parametry. Pierwszy to String - nazwa jednostki utrwalania z której będziemy korzystać, zdefiniowana musi być ona w pliku persistence.xml. Dodatkowo jeśli chcemy zmodyfikować właściwości jakie w nim zostały ustalone możemy podać obiekt typu Map jako drugi parametr i w zawrzeć ustawienia jakie nam odpowiadają.
EntityManagerFactory umożliwia nam utworzenie potrzebnego nam kontekstu utrwalania EntityManager za pomocą metody createEntityManager().

Po zakończeniu korzystania z EntityManagerFactory dobrze jest zamknąć i zwolnić zasoby poprzez wywołanie metody close().

Ok, no to teraz przykład:
JPATest.java
package com.blogspot.wookasz.jpainj2se;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JPATest {

public static void main(String[] args) {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("JPAJ2SETestPU");
EntityManager entityManager = factory.createEntityManager();
factory.close();

Person person = new Person(1L, "Zbyszko", "Ul. Nieznana 18");
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(person);
transaction.commit();
}
}
Person.java
package com.blogspot.wookasz.jpainj2se;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Person implements Serializable {

@Id
private Long id;

private String name;
private String address;

public Person() {
}

public Person(Long id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}

public Long getId() {
return id;
}

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

public String getName() {
return name;
}

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

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

}
persistence.xml



org.hibernate.ejb.HibernatePersistence
com.blogspot.wookasz.jpainj2se.Person








Koniecznie trzeba jeszcze dołączyć Hibernate (lub TopLink ale wtedy trzeba zmodyfikować plik xml) do projektu oraz sterownik odpowiadający używanej bazie danych.

Należy też pamiętać, że jeśli podczas tworzenia EntityManagera aktywna była transakcja to musimy wykonać na nim metoda joinTransaction() aby się do niej przyłączyć, w przeciwnym wypadku dane nie będą synchronizowane z bazą danych.

niedziela, 26 października 2008

Po NetBeans day Poznań

Wczoraj odbył się zapowiadany przeze mnie (i nie tylko) NetBeans Day na Uniwersytecie Adama Mickiewicza w Poznaniu.
Dotarłem na miejsce bezpiecznie ok 9:30. Rejestracją zajmował się Adam Dudczak - bardzo aktywny członek JUG Poznań, z którym się przy okazji zapoznałem (bardzo pozytywna osoba;).
Po pół godzinie czekania (+10min na drobne problemy techniczne) i pierwsze wystąpienie rozpoczął Geertjan Wielenga, technical writer w firmie Sun. Temat: “Creating an application on the NetBeans Platform”. Geertjan przedstawił problemy techniczne jakie napotykają podczas tworzenia NetBeans a następnie przeszedł do omówienia NetBeans Platform jako platformy to budowania aplikacji desktopowych. Pokazał główną zaletę - modularność, zarysował API platformy oraz pokazał którkie demo jak w prosty sposób przenieść już istniejącą aplikację na platformę NetBeans. Jak później się okazało Geertjan Wielenga jest takim Guru NetBeans:) Praktycznie wie o wszystkim co jest w tym środowisku ^^

Następne wystąpienie pt: “Programowanie w oparciu o platformę Netbeans w praktyce, czyli problemy, konstrukcje warte uwagi oraz skąd i jak czerpać na ten temat wiedzę” poprowadził Adam Kędziora - prezes koła naukowego na UAMie. Wystąpienie poświęcone problemom z jakimi spotkał się Adam podczas tworzenia wizualnego edytora JavaFX na jeden z konkursów. Na końcu podał też przydatne źródła wiedzy dla osób tworzących aplikacje w NetBeans Platform.
Godzina 12 wybiła - 20 minutowa przerwa:) Organizatorzy po wyjściu z sali przygotowali dla nas drobny poczęstunek w postaci góry ciastek i kartonów z sokiem.

Przerwa minęła - Adam Dudczak - “VisualVM i VisualVM API”, czyli temat który przegapiłem na PJUGu. Polecam to narzędzie! Bardzo bogata funkcjonalność, która przyda się praktycznie zawsze gdy w naszej aplikacji coś się sypie i nie wiadomo gdzie. Narzędzie dostępne razem z JDK:) Na końcu Adam pokazał jak tworzyć własne wtyczki do VisualVM - bardzo prosta sprawa:) Nawet prosta strzelankę można zrobić :P

O 13 wykład na który czekałem. Autor wizualnego edytora NetBeans Mobility Karol Harezlak mówił o "Teraźniejszości i przyszłości Javowych technologi mobilnych - NetBeans Mobility". Pokazał demo (i to nie jedno;), zapowiedział, że w przyszłym roku pojawi się wersja JavaFX na urządzenia mobilne oraz nowa wersja MIDP (3.0). Po prezentacji udało mi się kilka słów z Karolem wymienić nt. mojej inżynierki, trochę pomógł :) Miło było poznać osobę której narzędzia używa się na co dzień :)

Kolejna przerwa - tym razem obiadowa. Po niej Toni Epple z tematem “Porting an application to the NetBeans Platform”. Toni w swojej pracy przenosił aplikację napisaną we własnym frameworku na platformę NetBeans, przyjechał na spotkanie aby opowiedzieć o tym i podzielić się doświadczeniem jakie podczas tego zadania nabył. Także pokazał (podobnie jak Geertjan) demo jak w prosty sposób można wykonać taki "transfer aplikacji" - zrobiło wrażenie. Dobrze napisana aplikacja jest niezwykle łatwa w przeniesieniu.

No i na samym końcu prezentacja która mi się najbardziej podobała (może dlatego, że było o JEE ?:P). Adam Bien przedstawił “NetBeans and Glassfish - the Synergy for Pragmatic Java EE 6 development” - wszystko na NetBeans 6.5 RC1 którego używał zaledwie przed 3 dni ("No risk, no fun"). Musze przyznać, że poziom obsługi tego środowiska przez Adama jest imponujący. W bardzo szybki sposób zbudował aplikację uzywająć EJB, JPA, JSF, JMS i serwletów - wszystko w NetBeans 6.5 RC1 i GlassFish:) Bardzo podobała mi się ta prezentacja:) Na blogu Adama Biena można przeczytać już wpis o niej z jego perspektywy.

Na koniec organizatorzy rozlosowali nagrody dla zwycięzców konkursu w którym można było wziąć udział w miedzy czasie. Należało odpowiedzieć na kilka pytań - ja poległem, nie znam się na apletach, swingu i historii NetBeans:P

Na imprezie zabrakło niestety Jacka Laskowskiego którego bardzo chciałem poznać :( Tak się złożyło, że nie przyjechał ze swoją prezentacją o zaawansowanym EJB w NetBeans. Ale za to obiecał udostępnić ją w internecie. Przedstawił ją dzisiaj na Gdańskim NetBeans Day.

Wnioski końcowe:
- zainstalować wersję 6.5 RC1
- potestować NetBeans Platform
- zapoznać się bliżej z VisualVM
- jeśli kiedyś bym chciał też wystąpić na takim evencie prawdopodobnie musiałbym zmienić imię na Adam ;P

czwartek, 23 października 2008

NetBeans 6.5 Release Candidate 1 dostępny do ściągnięcia


Od dwóch dni można pobierać wersje RC1 środowiska NetBeans 6.5.
Nowa wersja środowiska wprowadza wiele poprawek, udogodnień, funkcji. Między innymi:
- wsparcie dla języka PHP, JavaScript, Ajax
- debugger JavaScript dla Firefox i IE
- wsparcie dla Groovy i Grails
- ulepszony edytor C++
- nowy kreator dodawania nowych komponentów dla aplikacji mobilnych
- poprawki w debuggerze
i wiele innych o których można poczytać na stronie www.NetBeans.org.

Chciałem jeszcze przypomnieć o sobotnim i niedzielnym NetBeans Day w Poznaniu i Gdańsku -> NetBeansDay.pl. Znany jest już harmonogram wykładów z którym można zapoznać się tutaj.
Kto się jeszcze nie zarejestrował niech to szybko uczyni ;-)
Zapraszam!

poniedziałek, 20 października 2008

Rozsyłanie sygnałów w JMX

Kontynuujemy zabawę z JMX :) W poprzednim wpisie stworzyliśmy aplikację która umożliwiała zmianę parametrów mziaren 'na odległość'. W tym poście wzbogacimy ją o funkcję rozsyłania sygnałów przy spełnieniu pewnych warunków - u nas będzie to sygnał o przekroczenie limitu użytkowników.
Kody źródłowe z poprzedniego wpisu można pobrać: tutaj (projekty w NetBeans IDE).

Zacznijmy od tego jak reprezentowany jest sygnał. Kiedy go wysyłamy przesyłany jest obiekt typu javax.management.Notification, któremu w konstruktorze możemy podać takie parametry jak typ(String), źródło(Object), numer sygnału(long), czas (long) oraz wiadomość (String).

MBean który chce wysyłać sygnały musi implementować interfejs NotificationEmitter jednak w praktyce klasa ziarna dziedziczy po klasie NotificationBroadcasterSupport, która udostępnia kilka użytecznych metod - właśnie tej klasy użyjemy w przykładzie.
No to przejdźmy do implementacji...

Serwer
Lista modyfikacji które należy wprowadzić w klasie serwera:
- klasa powinna dziedziczyć po javax.management.NotificationBroadcasterSupport
- dodajemy pole:
private static final String TYPE_LIMIT_USERS = "USERS_SERVER_LIMIT";
będzie to nasz typ komunikatu. Można to zrealizować trochę inaczej tworząc podklasę klasy Notification i w niej opakować takie informację (przykładem takiej klasy jest np. AttributeChangeNotification).
- dodajemy pole
private int notifyCounter = 0;
które będzie licznikiem wysyłanych sygnałów.

W konstruktorze klasy dodamy klasę anonimową (wątek) która będzie sprawdzać co określony okres czasu czy przekroczono maksymalną liczbę użytkowników. Jeśli taka sytuacja nastąpi wysłany zostanie sygnał do wszystkich "słuchaczy" - czyli klientów obserwujących to mziarno.

Wysłanie sygnału odbywa się poprzez wywołanie metody sendNotification którą odziedziczyliśmy.

W kodzie pojawia się dodatkowy wątek który dla testów zmienia wartość users na większy niż limit aby przetestować działanie całości.

Oto kompletny kod Server.java:
package com.blogspot.wookasz.jmxtutorial;

import java.util.Random;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;

public class Server extends NotificationBroadcasterSupport
implements ServerMBean {

private static final String TYPE_LIMIT_USERS = "USERS_SERVER_LIMIT";
private int notifyCounter = 0;
private int users = 0;
private int limit = 5;
private Thread notificationThread;

public Server() {
Random rnd = new Random();
users = rnd.nextInt(100);

final Server serverObj = this;

notificationThread = new Thread() {

@Override
public void run() {
try {
while (!Thread.interrupted()) {
Thread.sleep(1000 * 10);
System.out.println("Sprawdzanie");
if (limit < users) {
Notification notify =
new Notification(TYPE_LIMIT_USERS,
serverObj,
++notifyCounter,
System.currentTimeMillis(),
"Przekroczono dopuszczalny limit użytkowników na serwerze");
System.out.println("Wysyłanie");
sendNotification(notify);
}
}
} catch (InterruptedException ex) {
}
}
};
notificationThread.start();

/****************************************/
// wątek potrzebny do przykładu
Thread test = new Thread() {

@Override
public void run() {
try {
Thread.sleep(100);
System.out.println("Zmiana");
users = limit + 1;
} catch (InterruptedException ex) {
}
}
};
test.start();
}

public void setUsersLimit(int limit) {
this.limit = limit;
System.out.println("Limit uzytkowników zmieniono na: " + limit);
}

public int getUsers() {
return users;
}
}

Reszta plików pozostaje bez zmian.

Klient
Klasa klienta aby mogła odebrać sygnał musi implementować interfejs NotificationListener który wymusza implementację metody handleNotification.
Parametrami tej metody są:
- Notification notification - sygnał przychodzący
- Object handback - obiekt przekazywany w trakcie wywoływania metody addListener - rejestrowania słuchacza. Jest to obiekt pomocniczy.
Po zaimplementowaniu obiektu nasłuchującego należy go zarejestrować wywołując metodę addNotificationListener klasy typu MBeanServerConnection.
Metoda ta przyjmuje następujące parametry:
- ObjectName name - nazwa mziarna które emituje sygnały
- NotifiactionListener listener - obiekt nasłuchujący który rejestrujemy
- NotificationFilter - filtr sygnałów
- Object handback - obiekt pomocniczy przekazywany do obiektu nasłuchującego

No i to by było na tyle :)
Kod klasy nasłuchującej ClientListener.java:
package com.blogspot.wookasz.jmxtutorial;

import java.util.Date;
import javax.management.*;

public class ClientListener implements NotificationListener {

public void handleNotification(Notification notification,
Object handback) {

System.out.println("*** Odebrano sygnał! ****");
System.out.println("Wiadomość: " + notification.getMessage());
System.out.println("Nadany o godzinie: " + new Date(notification.getTimeStamp()));
}
}

Do klasy klienta dodano tylko następujące linie rejestrujące obiekt nasłuchujący:
ClientListener listener = new ClientListener();
server.addNotificationListener(name, listener, null, null);

Pełne kody źródłowe można pobrać: tutaj.

Zapraszam do komentowania ;-)

środa, 8 października 2008

Pierwsze kroki z JMX

JMX - czyli Java Management Extensions, to kolejna technologia javowa z którą przyszło mi się spotkać i zainteresować. Dziś mały wstęp do tej technologii i może "krótki" przykład ;-)

JMX jak Wikipedia nam tłumaczy jest technologią Javy, która zawiera narzędzia potrzebne do zarządzania oraz monitorowania aplikacji, urządzeń, usług zorientowanych sieciowo.
A teraz kilka pojęć i informacji wstępnych:
Ziarno zarządzane - m-ziarno - mbean - jest to obiekt Javy którym można zarządzać. Taki obiekt posiada atrybuty, operacje oraz sygnały. O ile atrybuty i operacje są dość oczywiste to sygnały są obiektami pewnych klas, które przy spełnieniu pewnych warunków mziarno może rozsyłać do słuchaczy.
M-ziarno musi implementować interfejs zarządzania - m-interfejs, który określa jakie właściwości posiada m-ziarno i jakie operacje na nim można wykonywać w aplikacji. Sygnałów nie uwzględniamy w interfejsie, a atrybuty są deklarowane przez metody set/get.
Interfejs oraz klasa mziarna muszą być publiczne.
Teraz ważna kwestia nazewnictwa. Nazwa klasy m-ziarna, natomiast m-interfejs musi przyjmować nazwę [nazwa klasy]MBean. Czyli, jeśli nasza klasa ma nazwę Ship, to interfejs który implementuje musi się nazywać ShipMBean. Co do nazewnictwa metod get/set to są one takie same jak w przypadku JavaBeans.

To chyba tyle z teoretycznych podstaw, reszta wyjdzie w praniu ;-)

Rejestrowanie m-ziarna
Żeby skorzystać z m-ziarna należy je wcześniej zarejestrować w serwerze m-ziaren. Domyślnie każda JVM przechowuje systemowy serwer m-ziaren i do niego będziemy dorzucać nasze ziarenka.
Obiekt serwera zwraca nam metoda (statyczna)
MBeanServer ManagementFactory.getPlatformMBeanServer()


Zanim jednak dodamy do niego nasz obiekt należy go wcześniej opakować tak, żeby był łatwiejszy do wyszukania na serwerze. Dokonujemy tego poprzez utworzenie dla niego nazwy, a dokładniej obiektu: ObjectName. Konstruktor przyjmuje 3 parametry:
- String domena - my będziemy używać domeny domyślnej dla serwera m-ziaren
- String klucz
- String wartosc
Ostatnie dwa parametry służą określenia nazwy m-ziarna, które może nam sugerować jego przeznaczenie.

Teraz możemy zarejestrować mbean (zakładamy że Test to klasa naszego ziarna:
Test mbean = new Test();

MBeanServer server = ManagementFactory.getPlatformMBeanServer();

ObjectName name = new ObjectName(server.getDefaultDomain(),
"JMXLearning",
"TestBean");

ObjectInstance mbeanObj = server.registerMBean(mbean, name);

mbeanObj przechowuje informacje o zarejestrowanym ziarnie.
Ok, mamy zarejestrowany obiekt. Możemy teraz odpalić naszą aplikacje. Uruchamianie wymaga podania maszynie wirtualnej javy następujących parametrów:
-Dcom.sun.management.jmxremote.port=[numer portu] - numer portu na którym nasłuchiwać będziemy na sygnały
-Dcom.sun.management.jmxremote.authenticate=[true/false] - czy ma być przeprowadzona autoryzacja
-Dcom.sun.management.jmxremote.ssl=[true/false] - czy używać bezpiecznego protokołu ssl
To by było na tyle z części "serwerowej". Teraz czas na klienta.

Dostęp do m-ziaren
Żeby wykonać jakieś operacje na m-ziarnach trzeba najpierw znać adres serwera na którym są one udostępnione. Adres taki ma postać:
service:jmx:rmi:///jndi/rmi://[nazwa hosta]:[numer portu]/jmxrmi

i reprezentowany jest przez obiekt typu JMXServiceURL. Jego konstruktor przyjmuje jako parametr String z adresem postaci takiej jak powyżej.
Połączenie z m-serwerem uzyskuje się następująco:
JMXConnector con = JMXConnectorFactory.connect(url);
MBeanServerConnection server = con.getMBeanServerConnection();

Poprzez obiekt łącznika JMXConnector otrzymujemy połączenie z m-serwerem który reprezentowany jest przez obiekt typu MBeanServerConnection.
W tym momencie jeśli nie znamy m-interfejsu ziarna na serwerze to możemy pobierać odpowiednie wartości poprzez metodę getAttribute lub przypisywać je poprzez odpowiednio setAttribute.
Jeśli znamy m-intefejs to możemy pobrać zdalną referencje na m-ziarno i wykonywać na nim operacje tak jakby był do niego dostęp bezpośredni w aplikacji. Aby tego dokonać należy wywołać statyczną metodę klasy MBeanServerInvocationHandler o nazwie getProxyInstance.
Przyjmuje ona 4 parametry, odpowiednio:
MBeanServerConnection connection - połączenie z serwerem
ObjectName objectName - reprezentacja nazwy obiektu m-ziarna
Class interfaceClass - interfejs implementowany przez m-ziarno
boolean notificationBroadcaster - czy pośrednik (czyli obiekt który otrzymamy) ma informować o sygnałach emitowanych przez m-ziarno
Przykład:
ShipMBean mbean = (ShipMBean)MBeanServerInvocationHandler.
newProxyInstance(server,
name,
ShipMBean.class,
false);
Teraz wykonując operacje na obiekcie mbean wykonujemy zdalnie operacje na m-ziarnie na serwerze.
To wszystko z teorii :) Poniżej zamieszczam kompletny kod źródłowy przykładowej aplikacji dzięki której będzie można pobierać informacje o liczbie użytkowników podłączonych do serwera oraz ustalać ich limit.

M-Interfejs - ServerMBean.java
package com.blogspot.wookasz.jmxtutorial;

public interface ServerMBean {
public void setUsersLimit(int limit);
public int getUsers();
}
M-Ziarno - Server.java
package com.blogspot.wookasz.jmxtutorial;

import java.util.Random;

public class Server implements ServerMBean {
private int limit = 100;
private int users = 0;

public Server() {
Random rnd = new Random();
users = rnd.nextInt(100);
}

public void setUsersLimit(int limit) {
this.limit = limit;
System.out.println("Limit uzytkowników zmieniono na: " + limit);
}

public int getUsers() {
return users;
}
}
Rejestracja m-ziarna - ServerRegistration.java
package com.blogspot.wookasz.jmxtutorial;

import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;

public class ServerRegistration {

public static void main(String[] args) {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName(server.getDefaultDomain(), "tutorial", "server");
Server mbean = new Server();
server.registerMBean(mbean, name);

Thread.sleep(Long.MAX_VALUE);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Uruchamiamy ten plik z parametrami:
-Dcom.sun.management.jmxremote.port=2005
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

I program klienta - Client.java
package com.blogspot.wookasz.jmxtutorial;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class Client {

public static final String servelUrl = "service:jmx:rmi:///jndi/rmi://localhost:2005/jmxrmi";

public static void main(String[] args) {
new Client().doTest();
}

public void doTest() {
try {
JMXServiceURL url = new JMXServiceURL(servelUrl);

JMXConnector con = JMXConnectorFactory.connect(url);
MBeanServerConnection server = con.getMBeanServerConnection();
ObjectName name = new ObjectName(server.getDefaultDomain(),
"tutorial", "server");

ServerMBean mbean = (ServerMBean)MBeanServerInvocationHandler.
newProxyInstance(server,
name,
ServerMBean.class,
false);

System.out.println("Liczba użytkowników na serwerze: " + mbean.getUsers());
mbean.setUsersLimit(120);
} catch(Exception e) {
e.printStackTrace();
}
}
}

Kompletne kody źródłowe można pobrać tutaj (projekty w NetBeans).

Zapraszam do komentowania ;-)

ps. zna ktoś plugina do bloggera, żeby dzielić posty ? Tzn. całość postu żeby pojawiała się po wybraniu czytaj dalej jak np w wordpress.

wtorek, 7 października 2008

Pokaz możliwości Java Real-Time System

Robi wrażenie. Nie sądziłem, że Java takiemu zadaniu podoła, a tu widzę, że bez problemu :)