poniedziałek, 12 października 2009

Dostęp do Websphere Remote EJB 2.1 z JAVA SE

Potrzebowałem stworzyć małą aplikację J2SE do wołania zdalnych sesyjnych bezstanowych EJB uruchomionych na Websphere 6.1.0.19. W mojej poprzedniej pracy juz robiłem coś takiego, ale wtedy aplikacja działała na SUN JRE. Tym razem podstawowym wymaganiem było użycie IBM JRE. Skoro serwera aplikacyjny oraz JRE są od tego samego dostawcy to sprawa powinna być prosta.... tymbardziej, że aplikacja była trywialnana a dodatkowo nie miałem potrzeby korzystać z żadnych z enterprise features jak bezpieczeństwo czy transakcyjność.
Dodatkowo EAR zawierający EJB, do którego trzeba się było dobierać nie był mojego autorstwa i nie dostarczono dla niego jara klienckiego - ze stubami, ale te można samemu wygenerować za pomocą ejbdeploy.
Za wszelką cene chciałem uniknąć sytuacji, w której to musiałbym uruchamiać moją aplikację za pomocą client container albo wykonywać jakies inne, dziwne kroki w fazie developmentu/deploymentu.
Po przeczytaniu dokumentacji wyglądało to wszystko extra skomplikowanie. Tymbardziej, że Weblogic już od dawna udostępniał swoim użytkownikom lekkiego client.jar (czy jakoś tak) do takich celów.
Czemu prosta rzecz nie może byc prosta?
Po wielu próbach i błędach udało mi się w końcu przygotować aplikację. Oprócz jara ze stubami, classpath zawiera następujące pozycje:

ecore-2.3.0-v200706262000.jar
emf-2.1.0.jar
com.ibm.ws.webservices.thinclient_6.1.0.jar
com.ibm.ws.runtime_6.1.0.jar


ecore-2.3.0-v200706262000.jar jest do ściągnięcia z mvnrepository, pozostałe 3 są skopiowane z WebSphere.
Dodatkowo bardzo ważna jest kolejność na classpath: com.ibm.ws.webservices.thinclient_6.1.0.jar musi byc przed com.ibm.ws.runtime_6.1.0.jar, ze względu na to, że klasa com.ibm.ejs.ras.Tr znajduję się w tych obu jarach.

Odwołanie do EJB jest realizowane w następujacy sposób:

Context initialContext = new InitialContext();
StringBuilder builder = new StringBuilder("corbaname:iiop:");
builder.append(serverIp);
builder.append(":");
builder.append(serverPort);
builder.append("#");
builder.append(ejbJNDIName);
Object lookUpResult = initialContext.lookup(builder.toString());
HomeInterface home = (HomeInterface) javax.rmi.PortableRemoteObject.narrow(
lookUpResult, HomeInterface.class);

serverIp - adres serwera na którym jest zdeployowany EJB
serverPort - port do komunikacji RMI (domyslnie 2809)
ejbJNDIName - nazwa JNDI zdalnego EJB

Dodatkowo dla serwera, którego EJB będziemy wywoływać należy dodać parę:adres ip, nazwa serwera do etc\hosts.

Jedyne co mi się nie podoba w przygotowanym przeze mnie rozwiązaniu to potrzeba umieszczenia na classpath w/w bibliotek z Websphere (sam com.ibm.ws.runtime_6.1.0.jar zajmuję prawie 60 MB).
Podobno w Websphere 7.0 został przygotowany jar kliencki, ale osobiście nie mam jak na razie dostępu do tej wersji.

UPDATE: przeglądając materiały związane z classloadingiem dla WAS 6.1 natknąłem się na info dotyczące "thin client library" dla WAS 6.1. Składają się na to 2 jary: com.ibm.ws.admin.client_6.1.0.jar (34 Kb) oraz com.ibm.ws.webservices.thinclient_6.1.0.jar (15 Kb) siedzące w <INSTALL_ROOT>/runtimes. Po usunięciu z classpath jarów wymienionych na początku posta (ecore-2.3.0-v200706262000.jar, emf-2.1.0.jar, com.ibm.ws.webservices.thinclient_6.1.0.jar, com.ibm.ws.runtime_6.1.0.jar) i podegraniu na ich miejsce tych z <INSTALL_ROOT>/runtimes wszystko działa bez zmian.

Brak komentarzy:

Prześlij komentarz