JBoss Web Services

Po długiej batalii z EJB przyszedł czas na wyjazd do Wenecji. Chwila relaksu i oderwania od klawiatury – smażenie się na plaży w Lido, zwiedzanie wcale nie śmierdzących kanałów miasta, przejażdżka gondolą i niemal bójka w Padwie. Po tych jakże odprężających ćwiczeniach usiadłem na moment w domowym zaciszu przed komputerem i wpadła mi do głowy jedna myśl – jak skorzystać z Web Services w Jboss? Z technologią tą miałem sporo do czynienia w implementacji Oracle’owej na serwerze aplikacyjnym Weblogic. Tam jednak umysł programisty wyręcza myszka i JDeveloper. Generowany przez IDE kod jest nadmiarowy lecz o dziwo zazwyczaj działa :P.

Przystąpmy więc do części bardziej merytorycznej. Zacznę od krótkiego przypomnienia technologii Web Services, standardu SOAP oraz takich terminów jak np. WSDL. Web Service wykorzystuje jako warstwę transportu protokół HTTP (zazwyczaj, inne możliwości: SMTP, FTP, JMS) oraz język XML (w celu strukturyzacji przesyłanych danych). Komunikat SOAP ma formę XML’a składającego się z <Envelope>, oraz zagnieżdżonych w nim nagłówku <Header> i ciele <Body>.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:edu="edu.lantoniak.ws">
  <soapenv:Header/>
  <soapenv:Body>
    <edu:sayHello>Lukasz</edu:sayHello>
  </soapenv:Body>
</soapenv:Envelope>

Za opis udostępnianego przez Nas serwisu odpowiada WSDL. Jest on zwyczajowo umieszczony na serwerze aplikacyjnym i dostępny z poziomu przeglądarki internetowej. Klienci WS, na podstawie informacji zawartych w tym pliku, określić mogą typy wymaganych parametrów poszczególnych metod oraz wartości przez nich zwracanych. Jako deweloper Java rzadko piszę WSDL ręcznie. Deskryptor ów generowany jest automatycznie na podstawie klasy Java (implementacji Web Service’u) opatrzonej odpowiednimi adnotacjami. Poniżej zamieściłem przykładowy WSDL.

<definitions name="HelloService" targetNamespace="edu.lantoniak.ws">
  <types>
    <xs:schema targetNamespace="edu.lantoniak.ws" version="1.0">
      <xs:element name="sayHello" nillable="true" type="xs:string"/>
      <xs:element name="sayHelloResponse" nillable="true" type="xs:string"/>
    </xs:schema>
  </types>
  <message name="HelloWSRemote_sayHelloResponse">
    <part element="tns:sayHelloResponse" name="sayHelloResponse"/>
  </message>
  <message name="HelloWSRemote_sayHello">
    <part element="tns:sayHello" name="sayHello"/>
  </message>
  <portType name="HelloWSRemote">
    <operation name="sayHello" parameterOrder="sayHello">
      <input message="tns:HelloWSRemote_sayHello"/>
      <output message="tns:HelloWSRemote_sayHelloResponse"/>
    </operation>
  </portType>
  <binding name="HelloWSRemoteBinding" type="tns:HelloWSRemote">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="sayHello">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>
  <service name="HelloService">
    <port binding="tns:HelloWSRemoteBinding" name="HelloWSPort">
      <soap:address location="http://localhost:8080/Tutorial7/HelloWSImpl"/>
    </port>
  </service>
</definitions>

Wewnątrz tagu <types> określa się wszystkie typy danych stosowanych w serwisie (typy parametrów oraz wartości zwracanych wykorzystywanych w metodach). W Naszym przypadku, zdefiniowane są dwa proste typy klasy xs:string: sayHello oraz sayHelloResponse. Tag <message> specyfikuje wszystkie rodzaje wiadomości jakie obsługiwane są przez Web Service. Linijki 14 – 19 wiążą rodzaje wykorzystywanych wiadomości z poszczególnymi operacjami (metodami). Sekcja <binding> wyróżnia poszczególne operacje serwisu oraz definiuje szczegóły dotyczące stosowanego protokołu (w tym przypadku stylu document – por. RPC). Wreszcie, tag <service> specyfikuje nazwę serwisu oraz jego adres.

Implementacja prostego Web Service’u

W Eclipse, podobnie jak w JDeveloper, implementację Web Service’u oraz projektu proxy stosowanego przez klienta, można ponoć (mi się nie udało) w stosunkowo łatwy sposób wyklikać (rodzaje projektu: “Create a Sample Web Service” oraz “Web Service Client”). Zaprezentuję jednak drogą równie przyjemną metodę, nie opierającą się na kreatorach graficznych i klikologii, lecz na nieco bardziej przemyślanym użyciu klawiatury. Web Service tworzyć można na dwa sposoby: bottom up (najpierw klasy Java, a potem WSDL), lub top down (inaczej zwane contract first – najpierw WSDL, a następnie implementacja).

Stwórzmy nowy projekt EJB, a w nim bezstanowe (@Statefull nie jest wspierane, polecam zapoznać się z terminem conversational Web Service) ziarno EJB.

@Remote
@WebService(targetNamespace = "edu.lantoniak.ws")
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT,
             parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface HelloWSRemote {
   public String sayHello(String name);
}

@Stateless
@WebService(serviceName = "HelloService", targetNamespace = "edu.lantoniak.ws",
            name = "HelloWS", endpointInterface = "edu.lantoniak.ws.HelloWSRemote")
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT,
             parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class HelloWSImpl implements HelloWSRemote {
   public String sayHello(String name) {
      return "Hello " + name + "!";
   }
}

Następnie deploy’ujemy aplikację. Uwaga: nazwa pod którą deploy’owana jest aplikacja nie może zawierać spacji! Aby upewnić się, że aplikacja wgrana została pomyślnie, przejdź do http://localhost:8080/jbossws/services i sprawdź, czy na liście serwisów widnieje Twoja nowo dodana usługa. Działanie samego Web Service’u weryfikujemy za pomocą narzędzia SoapUI.

W celu dalszej zabawy, polecam zapoznanie się z podstawowymi adnotacjami @WebMethod, @WebParam, @WebResult, oraz bardziej zaawansowanymi @OneWay i @HandlerChain.

Implementacja klienta standalone

Poniżej znajduje się kod prostego klienta, wywołującego wcześniej stworzony Web Service z poziomu Javy.

public class Main {
   public static void main(String[] args) {
      String endpointURI = "http://localhost:8080/Tutorial7/HelloWSImpl?wsdl";
      try {
         String hello = getPort(endpointURI).sayHello("Lukasz");
         System.out.println(hello);
      } catch (MalformedURLException e) {
         e.printStackTrace();
      }
   }

   private static HelloWSRemote getPort(String endpointURI) throws MalformedURLException {
      QName serviceName = new QName("edu.lantoniak.ws", "HelloService");
      URL wsdlURL = new URL(endpointURI);
      Service service = Service.create(wsdlURL, serviceName);
      return service.getPort(HelloWSRemote.class);
   }
}

Wstrzykiwanie proxy serwisu do ziaren EJB

W celu wywołania serwisu w ziarnie EJB, skorzystać należy z narzędzia wsconsume wchodzącego w skład serwera aplikacyjnego JBoss. Narzędzie to generuje klasy proxy Web Service’u, które następnie wepniemy za pomocą adnotacji @WebServiceRef. Stwórzmy nowy, pusty katalog w dowolnym miejscu na dysku twardym i wywołajmy polecenie: $JBOSS_HOME\bin\wsconsume.bat -p edu.lantoniak.ws.proxy http://localhost:8080/Tutorial7/HelloWSImpl?wsdl. Wygenerowane klasy (wraz z katalogami pakietu – w tym przypadku edu.lantoniak.ws.proxy) kopiujemy np. do katalogu generated w projekcie modułu EJB. Następnie w Eclipse klikamy prawym przyciskiem na projekt -> Properties -> Java Build Path -> Libraries -> Add Class Folder i wskazujemy na katalog generated. Pozostało Nam jedynie stworzenie nowego ziarna EJB korzystającego z Web Service’u:

@Stateless
public class StatelessSampleEJB implements StatelessSampleEJBRemote {
   @WebServiceRef(wsdlLocation = "http://localhost:8080/Tutorial7/HelloWSImpl?wsdl")
   private HelloService helloService;

   public String sayHello(String name) {
      return helloService.getHelloWSPort().sayHello(name);
   }
}

Źródła projektów: Tutorial 7 All.zip.

Advertisements

27/07/2010 SCBCD … [done]

No cóż, przygoda z EJB i JPA zaczęła mnie już trochę nużyć. Czas najwyższy podejść do egzaminu i zdać! Jak postanowiłem, tak też uczyniłem. Nikogo nie interesuje pewnie mój wynik, a ja nie lubię się chwalić, więc powiem tylko z czego się przygotowywałem:

  1. “EJB 3 in Action”, Manning 2007. Wg mnie bardzo dobra pozycja. Większość rzeczy jasno i żetelnie wyjaśnionych. Moje podstawowe źródło wiedzy.
  2. “Pro EJB 3 Java Persistence API”, Apress 2006. Obowiązkowo przeczytać należy rozdział 5 pt. “Entity Manager”. Bardzo dobrze przedstawione wszelkie zagadnienia związane z Persistence Context, User Transactions, CMT & BMT.
  3. “Enterprise JavaBeans 30.” O’Reilly 2006. Dość przeciętnie napisane (nie zaciekawiło mnie). Zwraca jednak uwagę czytelnika na zaznajomienie się nie tylko z adnotacjami, lecz także ich odpowiednikami w deploy deksryptorze ejb-jar.xml.
  4. Sławny JSR-220. Raczej lektura do poduszki, chociaż warto na egzamin wkuć poszczególne role serwera EJB (ich funkcje w odniesieniu np. do security). W JSR sprawdzałem wszelkie informacje dotyczące działania poszczególnych metod, np. co się stanie, gdy do EntityManager.remove() podamy jako argument detached entity.
  5. uCertify.
  6. Forum Code Ranch: http://www.coderanch.com/forums/f-70/java-EJB-SCBCD.
  7. http://www.blackbeltfactory.com/gen/documents/6830028/SCBCD_study_guide.pdf – porządnie przedstawiony pełen plik ejb-jar.xml.

Na koniec życzę wszystkim powodzenia na egzaminie!

EJB Security

Tym razem poruszę zagadnienia związane z zabezpieczeniem bean’ów działających w ramach kontenera JBoss AS EJB. W tym celu stworzymy arcyciekawą aplikację – komercyjny kalkulator. Osoby niezarejestrowane będą miały możliwość wykonywania jedynie operacji dodawania, podczas gdy każdy użytkownik należący do grupy ENTERPRISE także operację mnożenia. Serwer aplikacyjny JBoss posiada wbudowaną obsługę standardu LDAP, relacyjnych baz danych oraz plików płaskich, gdzie składować możemy nazwy użytkowników, ich hasła oraz informacje na temat przynależności do poszczególnych ról. Dla zachowania prostoty owego przykładu zdecydowałem się na przechowywanie owych informacji w plikach płaskich.

Pierwszy krok, jaki należy wykonać, to konfiguracja serwera aplikacyjnego, czyli stworzenie tzw. securoty domain, przykładowego zarejestrowanego użytkownika, przypisanie mu hasła oraz roli ENTERPRISE. Na początku (czyt. wewnątrz taga <policy>) pliku $JBOSS_HOME/server/default/conf/login-config.xml dopisujemy:

<application-policy name="CommercialCalculator">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
                  flag = "required">
      <module-option name="unauthenticatedIdentity">anonymous</module-option>
      <module-option name="usersProperties">props/cc-users.properties</module-option>
      <module-option name="rolesProperties">props/cc-roles.properties</module-option>
    </login-module>
  </authentication>
</application-policy>

Następnie tworzymy dwa pliki cc-users.properties oraz cc-roles.properties (w podkatalogu props/). Struktura plików powinna mieć formę properties, tzn. każdy wiersz posiada parę klucz-wartość rozdzieloną znakiem równości. Linia rozpoczęta symbolem # traktowana jest jako komentarz. Plik cc-users.properties zawiera nazwy użytkowników oraz przypisane im hasła (niezaszyfrowane niestety, aczkolwiek istnieje taka możliwość: http://community.jboss.org/wiki/UsersRolesLoginModule). Drugi plik zaś, definiuje role posiadane przez danego użytkownika. W przypadku większej niż jedna ilości ról, należy rozdzielić je przecinkiem. Zwróćmy uwagę na użytkownika anonimowego, gdyż musi on posiadać odpowiedni wpis w pliku login-config.xml, jak i cc-users.properties. Przykładowe pliki konfiguracyjne:

cc-users.properties:

foo=bar
anonymous=

cc-roles.properties:

foo=ENTERPRISE

Zastanawia mnie teraz, czy istnieje możliwość definiowania hierarchii ról… Wracając do przykładu – stwórzmy ziarno EJB (Stateless, Remote) kalkulatora wykorzystując adnotacje @RolesAllowed oraz @PermitAll. W tutorialu tym nie opisuję szczegółowo kolejnych kroków tworzenia projektu EJB w Eclipse IDE. Jeśli ktoś przypadkiem trafił na ten mini-artykuł z wyszukiwarki Google, odsyłam do mojego poprzedniego wpisu na temat EJB i JPA, gdzie wymagane kroki zostały szczegółowo przedstawione.

import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;

import org.jboss.ejb3.annotation.SecurityDomain;

@Stateless
@SecurityDomain("CommercialCalculator")
@RolesAllowed("ENTERPRISE")
public class CommercialCalculator implements CommercialCalculatorRemote {
    @PermitAll
    public int add(int a, int b) {
        return a + b;
    }

    public int multiply(int a, int b) {
        return a * b;
    }
}

Klasa CommercialCalculator opatrzona została adnotacją @SecurityDomain, która specyfikuje, z której domeny bezpieczeństwa korzysta ziarno EJB. Domena ta zdefiniowana została przez Nas uprzednio w pliku login-config.xml. Adnotację @RolesAllowed stosować można w odniesieniu do całej klasy (definiuje wtedy role wymagane domyślnie do użycia jakiejkolwiek z metod) lub dla pojedynczej metody. @PermitAll przesłania adnotację @RolesAllowed udostępniając wszystkim wywołanie owej metody.

Przedstawię teraz kod klienta. Niestety JBoss nie trzyma się tutaj standardów. Serwer aplikacyjny nie korzysta z atrybutów Context.SECURITY_PRINCIPAL oraz Context.SECURITY_CREDENTIALS. Mało tego – udostępnia on całkowicie odrębny mechanizm logowania! Szczegóły widać gołym okiem na poniższym listingu (por.: http://nurkiewicz.blogspot.com/2009/08/invoking-secured-remote-ejb-in-jboss-5.html i http://community.jboss.org/wiki/SecurityFAQ).

import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.jboss.security.client.SecurityClient;
import org.jboss.security.client.SecurityClientFactory;
import edu.lantoniak.ejb.security.CommercialCalculatorRemote;

public class Main {
    public static void main(String[] args) throws Exception {
        SecurityClient securityClient = null;
        try {
            securityClient = SecurityClientFactory.getSecurityClient();
//          securityClient.setSimple("anonymous", "");
            securityClient.setSimple("foo", "bar");
            securityClient.login();

            Properties props = new Properties();
            props.put(Context.INITIAL_CONTEXT_FACTORY,
                      "org.jnp.interfaces.NamingContextFactory");
            /* Not supported by JBoss AS. */
//          props.put(Context.INITIAL_CONTEXT_FACTORY,
//                    "org.jboss.security.jndi.JndiLoginInitialContextFactory");
//          props.put(Context.SECURITY_PRINCIPAL, "foo");
//          props.put(Context.SECURITY_CREDENTIALS, "bar");
            props.put(Context.PROVIDER_URL, "localhost:1099");
            props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");

            Context ctx = new InitialContext(props);

            CommercialCalculatorRemote calc =
                (CommercialCalculatorRemote) ctx.lookup("CommercialCalculator/remote");
            System.out.println(calc.multiply(2, 2));
            System.out.println(calc.add(1, 2));
        } finally {
            if (securityClient != null) {
                securityClient.logout();
            }
        }
    }
}

Zachęcam czytelników do zabawy w komentowanie i odkomentowywanie na przemian linii 13, 14 oraz 32, 33.

Źródła projektów: Tutorial 6 All.zip.

EJB i JPA

Witam!

Na wstępie zaznaczę, iż jest to mój pierwszy wpis typu “tutorial” na internetowym blogu. Proszę o wszelką wyrozumiałość oraz krytyczne komentarze w celu podniesieniu poziomu kolejnych:). Po tej krótkiej, ciekawej i jakże interesującej przedmowie przejdźmy do meritum sprawy, a mianowicie EJB i JPA. Mateusz Mrozowski na swoim blogu (http://tech.mrozewski.pl) opublikował szereg ćwiczeń związanych z EJB dla początkujących. Początkowo korzystał on z Elcipse i JBoss AS. Część poświęconą JPA przeniósł jednak (dla urozmaicenia:P) na NetBeans i Glassfish. Moja wewnętrzna niechęć do owych środowisk okazała się wystarczającym impulsem do powstania tego mini-artykułu. A więc do dzieła!

Naszym celem jest stworzenie trzech projektów:

  1. projektu JPA zawierającego mapowanie tabel relacyjnej bazy danych na encje.
  2. projektu EJB udostępniającego podstawowe operacje na danych. Coś na wzór Data Access Objects.
  3. projektu aplikacji klienckiej.

Jako docelową bazą danych posłużę się Oracle 10g XE (10.2). Dlaczego?! Ci co mnie znają pewnie wiedzą, i niech tak pozostanie. Oficjalnie zachęcam wszystkich do korzystania z baz Oracle, gdyż nie są trudne w instalacji, jeszcze darmowe (!) oraz szeroko stosowane w projektach komercyjnych. W projekcie JPA zmapuję tylko fragment jednej tabelki przykładowego schematu HR dalszą zabawę z JPA pozostawiając czytelnikowi.

Projekt JPA

Z Eclipse’owego menu wybieramy File -> New -> JPA Project, wpisujemy nazwę Tutorial 3 i klikamy Finish. Następnie tworzymy klasę encji edu.lantoniak.ejb3.jpa.Job oraz wklejamy kod znajdujący się na listingu zamieszczonym poniżej.

@Entity
@Table(name="JOBS")
public class Job implements Serializable {
    @Id
    @Column(name="JOB_ID")
    private String jobId;

    @Column(name="JOB_TITLE")
    private String jobTitle;

    /* Getters & setters */
    ...
}

Pamiętać należy o przeciążeniu metod equals() oraz hashCode() (zgodnie z kontraktem znanym z przygotowań do SCJP). Prezentowany przykład mapowania jest dziecinnie prosty i nikomu znającemu język angielski nie trzeba go zapewne objaśniać.

Ostatni krok niezbędny do ukończenia projektu JPA, polega na edycji pliku persistence.xml i wyspecyfikowania źródła danych, z którego korzysta aplikacja. Plik ten powinien mieć postać podobną do tej z drugiego listingu.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="Tutorial 3">
        <jta-data-source>java:/OracleDS</jta-data-source>
    </persistence-unit>
</persistence>

Dzięki tagowi <jta-data-source> deskryptor połączenia do bazy danych pobrany zostanie z zasobów serwera aplikacyjnego. Domyślna konfiguracja JBoss nie posiada zainstalowanego sterownika JDBC Oracle (link). Plik ojdbc14.jar umieścić należy w katalogu $JBOSS_HOME/server/default/lib/. Następnie w katalogu $JBOSS_HOME/server/default/deploy/ tworzymy plik oracle-ds.xml, którego przykładową zawartość prezentuje kolejny listing. Plik ten definiuje między innymi connection string, adres bazy danych, użytkownika, hasło oraz wielkość dostępnej puli połączeń.

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
    <local-tx-datasource>
        <jndi-name>OracleDS</jndi-name>
        <connection-url>jdbc:oracle:thin:@localhost:1521:XE</connection-url>
        <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
        <user-name>hr</user-name>
        <password>hr</password>
        <min-pool-size>1</min-pool-size>
        <max-pool-size>5</max-pool-size>
        <exception-sorter-class-name>
            org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter
        </exception-sorter-class-name>
        <metadata>
            <type-mapping>Oracle9i</type-mapping>
        </metadata>
    </local-tx-datasource>
</datasources>

Otwieramy w przeglądarce internetowej konsolę administracyjną JBoss – http://localhost:8080/admin-console/ (domyślnie admin/admin). Uwaga: ważne, aby najpierw uruchomić serwer aplikacyjny, a dopiero potem bazę danych Oracle. Występuje konflikt domyślnych portów i konsola administracyjna nie zbinduje się na port 8080. Tak to działa przynajmniej u mnie.. Nie wierzysz – sprawdź, a jeśli się mylę umieść komentarz. Tak czy owak, po zalogowaniu się, powinniśmy widzieć w sekcji Datasources źródło danych OracleDS ze statusem up.

Projekt EJB

Przypomnę, iż projekt ten pełni funkcję warstwy DAO – udostępnia operacje wyszukiwania oraz DML wyższym warstwom aplikacji. Tworzymy nowy projekt EJB o nazwie Tutorial 3 EJB. We właściwościach projektu dodajemy mozolnie skonfigurowany uprzednio moduł JPA (Tutorial 3) do Java Build Path. Następnie tworzymy nowe bezstanowe ziarno EJB (patrz listing 4).

@Stateless
public class JobDAO implements JobDAORemote, JobDAOLocal {
    @PersistenceContext
    private EntityManager em;

    public JobDAO() {
    }

    @Interceptors(DAOInterceptor.class)
    public void add(Job job) {
        em.persist(job);
    }
}

Do bean’a JobDAO, za pomocą adnotacji @PersistenceContext, wstrzykujemy EntityManager. Obiekt ten umożliwia podstawowe operacje na encjach. Jeśli chodzi o szerszy opis klasy PersistenceContext, to odsyłam do fachowej literatury, z której dowiesz się znacznie więcej niż z tego prostego tutorialu. W prezentowanym powyżej kodzie, niespodziankę stanowi interceptor DAOInterceptor. Interceptor jest to klasa umożliwiająca wykonanie pewnych operacji przed oraz po wykonaniu danej metody (w tym przypadku add()), lub wszystkich metod danej klasy. Kod interceptora przedstawia się następująco:

public class DAOInterceptor {
    @AroundInvoke
    public Object profile(InvocationContext invocation) throws Exception {
        if ("add".equals(invocation.getMethod().getName())) {
            if (invocation.getParameters()[0] instanceof Job) {
                Job job = (Job) invocation.getParameters()[0];
                job.setJobTitle(job.getJobTitle() + " ADDED");
            }
        }
        return invocation.proceed();
    }
}

Obiekt InvocationContext enkapsuluje wszelkie dobrodziejstwa i niebezpieczeństwa jakie niesie za sobą mechanizm refleksji. W tym przypadku do każdego nowo tworzonego tytułu stanowiska, doklejany sufiks ” ADDED”. Oczywiście, zaprezentowany interceptor nie ma żadnego sensu biznesowego. Bardziej użyteczny przykład wykorzystania interceptora dotyczy wypełniania kolumn audytowych i opisany został w artykule “Using a Hibernate Interceptor To Set Audit Trail Properties”.

Projekt aplikacji klienckiej
Prosty projekt umożliwiający dostęp do wcześniej powstałego obiektu DAO tworzymy przez opcje File -> New -> Project -> Application Client Project. Mateusz Mrozowski opisuje na swoim blogu procedurę dostępu do ziaren EJB spoza kontenera. Dla porządku umieszczam jednak kod aplikacji klienckiej:

public class Main {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
        props.put(Context.PROVIDER_URL, "localhost:1099");
        props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
        try {
            Context ctx = new InitialContext(props);
            JobDAORemote jobDAO = (JobDAORemote) ctx.lookup("JobDAO/remote");
            Job job = new Job();
            job.setJobId("LUK_DYR");
            job.setJobTitle("Dyrektor");
            jobDAO.add(job);
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
}

Źródła projektów: Tutorial 3 All.zip.

SCBCD czas start!

Blog powstał w celu samomobilizacji do zdania egzaminu Sun SCBCD. Jest już dość późno, a ja zamiast iść na piwo, postanowiłem zaklepać sobie domenę blog’a i umieścić pierwszy powitalny post… A więc, jak na razie to by było na tyle. “Za tych co na lądzie!”

System.out.println("Hello World!");