O roli języka Java i technologii J2EE w Oraclu

część 2

Sebastian Wyrwał

W poprzednim artykule zaprezentowano pewne podstawowe
informacje na temat omawianej technologii. Podjęcie decyzji o ewentualnym jej
zastosowaniu, a następnie efektywne wykorzystanie wymaga jednak głębszego
przyjrzenia się zarówno J2EE, narzędziom, ich możliwościom oraz praktyce
ich stosowania. Jest to konieczne tym bardziej, iż produkty i narzędzia można
łączyć w różny sposób. Można np. używać serwera aplikacji jednego
producenta, motoru bazy danych innego, a środowiska deweloperskiego jeszcze
innego producenta. Można również od początku do końca stosować narzędzia
i produkty firmy Oracle. Poza tym, stosując jedno narzędzie warto wiedzieć na
jakiej zasadzie funkcjonują inne. Należy również rozgraniczyć wymagania i
oczekiwania stawiane danej technologii i narzędziom, które są z nią związane,
od wymagań użytkowników, które są stawiane systemowi. Pierwsza grupa
dotyczy wygody i łatwości zastosowania technologii i narzędzi. Druga grupa
dotyczy jakości wytworzonego systemu, a konkretnie np. jego niezawodności,
pewności itp. Wybierając technologię lub narzędzie warto zwrócić uwagę na
te cechy, które są kluczowe w porównywaniu
z innymi rozwiązaniami służącymi do tego samego lub podobnego celu. Na
stronach oracle.com jest dużo materiałów i przykładów dotyczących
wykorzystania narzędzi takich jak Jdeveloper, więc nie warto ich tu powielać.
Bardziej celowe wydaje się przedstawienie prostego przykładu i rozwiązanie
problemu narzędziem Oracla i narzędziem innej firmy. Aby ułatwić analizę
zamieszczonych przykładów, w telegraficznym skrócie przypomnimy pewne
podstawowe informacje:

Dla atrybutu x w EJB encji definiujemy metody getX
i setX. Dostęp do komponentów EJB może być lokalny
(z tej samej JVM) lub zdalny (inna JVM, inny system). Obiekty uzyskuje się
(tzn. tworzy i wyszukuje) przy pomocy interfejsów Home i LocalHome.
Pierwszy zapewnia dostęp zdalny, drugi lokalny. Dla każdej metody, jak i całego
komponentu możemy określić rodzaj dostępu. Manipulacja egzemplarzami
(obiektami) komponentów odbywa się z użyciem odpowiednich interfejsów. Używając
interfejsu Home lub LocalHome uzyskujemy odpowiedni interfejs.

Kilka słów o narzędziu JDeveloper

Patrząc chociażby na JDevelopera 10g łatwo można dojść
do wniosku, iż tworzenie aplikacji opartych o J2EE jest
w Oraclowym świecie bardzo ważne. Enterprise Jave Beans tworzy się przy
pomocy dość wygodnych kreatorów
i stosowane tu podejście jest inne od stosowanego w bardzo popularnym środowisku
MyElicpse.1 W tym ostatnim prym wiedzie użycie narzędzia XDoclet. EJB
„opisuje” się tam bezpośrednio w kodzie aplikacji a wiele właściwości
ustawia się w konfiguracji narzędzia, które jest z MyEclipse zintegrowane. Użycie
Oraclowych kreatorów jest niewątpliwie łatwiejsze przy definiowaniu relacji
pomiędzy komponentami EJB. XDoclet oferuje generowanie pomocniczych obiektów służących
do uzyskiwania referencji do odpowiedniego interfejsu oraz ObjectValues.
JDeveloper potrafi generować klasy *DTO (ang. Data Transfer Object), które służą
mniej więcej do tego samego co Object Values, czyli do „zdalnego transportowania” wartości obiektów, które
mają lokalną widoczność. W narzędziu JDeveloper znaczny nacisk położono
na możliwość generowania komponentów EJB na podstawie istniejących
w bazie danych tabel. Możliwości tej brak niestety w narzędziu MyEclipse. Jeśli
chodzi o edycję kodu źródłowego oraz szablony kodu, lepiej zdaniem autora
sprawuje się Eclipse i MyEclipse.

Co jest istotne dla twórców oprogramowania w technologii J2EE

Aby odpowiedzieć na postawione powyżej pytanie, należy
wcielić się w postać kierownika projektu, projektanta, lub programistę, który
ma do napisania aplikację, a technologią implementacji jest J2EE.

Osoba tworząca projekt musi go utworzyć w wybranym narzędziu
a następnie stworzyć pewną ilość komponentów EJB. Dla komponentów-encji
należy zdefiniować atrybuty (lub mówiąc ściślej abstrakcyjne metody get i
set dla każdego z atrybutów). Należy również zdefiniować relacje pomiędzy
komponentami i określić pewne szczegóły związane z kluczem głównym. Ważne
jest również zdefiniowanie metod wyszukujących (ang. Finder).

Dla komponentów sesyjnych należy zdefiniować i
zaimplementować metody realizujące logikę biznesową. Dla wszystkich
komponentów należy określić pewne informacje potrzebne serwerowi aplikacji.
Znajdują się one m.in. w pliku rozmieszczenia. Należy ponadto określić
mapowanie atrybutów komponentów-encji na kolumny w BD. Teoretycznie to
wszystko można zrobić ręcznie…

W praktyce jednak stosuje się różne rozwiązania wspierające
projektanta i programistę w jego pracy. Najważniejsze jest generowanie
deskryptora rozmieszczenia i pliku określającego mapowania.

Choć każda osoba używająca J2EE powinna znać strukturę
tych plików, to ręczne pisanie deskryptorów rozmieszczenia rodzi duże możliwości
popełnienia błędów. Można więc powiedzieć, iż dla osoby lub zespołu, która
ma realizować projekt z użyciem J2EE, a nie ma doświadczenia z użyciem tej
technologii najistotniejsze są:

  • Sposób tworzenia deskryptorów rozmieszczenia i
    rozmieszczania aplikacji;
  • Sposób tworzenia Entity Beans;
  • Sposób definiowania relacji pomiędzy encjami;
  • Sposób tworzenia zapytań;
  • Możliwość zautomatyzowania pewnych czynności w
    procesie produkcji aplikacji (generowanie klas pomocniczych, obiektów wartości
    (ang. value object) lub DTO;
  • Tworzenie GUI, warstwy prezentacji itp.

Prosty przykład

Jako przykład zostanie zaprezentowany fragment systemu
informatycznego służący do parametryzacji przy pomocy słowników. Na
poziomie bazy danych obejmuje on dwie tabele – typ słownika (ttypslow)
i słownik (tslow). Tabela ttypslow ma dwie kolumny fid i fvalue2. Pierwsza jest kluczem głównym, druga przechowuje nazwę słownika. Druga z
tabel (tslow) ma trzy kolumny: fid, fvalue, typ_id.
Pierwsza to klucz główny, druga – wartość elementu słownika, trzecia
– klucz obcy określający nazwę słownika. W obrębie przykładu
pokazano to samo rozwiązanie stworzone przy pomocy płatnego pluginu do Eclipse
– MyEclipse oraz narzędzia JDeveloper. Z tym, że w drugim przypadku
definicje EJB Ttypslow1Bean i Tslow1Bean zostały stworzone
automatycznie na podstawie już istniejących w bazie danych tabel. Ręcznie
zostały napisane ciała metod ejbCreate. W ich obrębie generowana jest
liczba losowa, która po konwersji do łańcucha znaków jest używana jako
klucz główny. W części dotyczącej użycia MyEclipse klucze główne są
generowane przez klasę pomocniczą3 wygenerowaną narzędziem Xdoclet.

Podejście MyEclipse i Xdoclet

Narzędzie XDoclet potrafi wygenerować m.in. deskryptor
rozmieszczenia oraz plik konfiguracyjny charakterystyczny dla danego typu
serwera aplikacji. W poniższym przykładzie zostały wykorzystane tagi na
poziomie klasy i metod. Przy pomocy tych pierwszych zdefiniowano nazwę
komponentu, opis, typ trwałości, nazwę JNDI4, tabelę, która zapewni
trwałość. Przy pomocy tagów charakterystycznych dla serwera aplikacji JBoss
określono, iż tabela ma być tworzona i usuwana odpowiednio przy
rozmieszczaniu i usuwaniu aplikacji z serwera. Zdefiniowano również dwie
metody wyszukiwania w języku EJB QL5.
W sygnaturach tych metod należy podawać pełne nazwy typów łącznie z nazwą
pakietu, czyli nie np. String, a java.lang.String. Dla metod określa
się ich widoczność (local, remote, both), odpowiadającą
kolumnę w tabeli6, nazwy parametrów wywołania, informację czy metoda
zwraca wartość (@return) i informacje na temat tego, czy metoda może
rzucić wyjątek (@exeption). Klucz główny definiuje się na poziomie
atrybutu poprzez obecność tagu @ejb.pk-field przy metodzie get* dla
tego atrybutu. Kilku słów wymaga definiowanie relacji. Definicji relacji typu
1:n dokonuje się w obydwu klasach biorących w niej udział. Jest to czynność,
która przy niezbyt starannym wykonywaniu może powodować błędy. W praktyce
najlepiej zdefiniować jedną stronę relacji i skopiować, a następnie dokonać
odpowiednich przeróbek po drugiej stronie. Warto przypomnieć, iż dla atrybutu
x istnieją odpowiednio metody getX i setX.

Między typem słownika a słownikiem istnieje relacja 1:n.
Po stronie słownika jest ona zdefiniowana następująco:

/**

    * @ejb.interface-method view-type="local"

    * @ejb.relation name="elementSlownika-Slownik"

    * role-name="nalezy do slownika"

    * target-ejb="TypSlownika"

    * target-role-name="jest typem tego slownika"

    * target-multiple="true"

    * @jboss.relation related-pk-field="id" fk-column="typ_id"

    * fk-constraint="true"

    * @return

    */

    public abstract TypSlownikaLocal getTypSlownikaLocal();

     

    /**

    * @ejb.interface-method view-type="local"

    * @param typSlownikaLocal

    */

    public abstract void setTypSlownikaLocal(TypSlownikaLocal typSlownikaLocal);

Po stronie typu słownika natomiast:

/**

    * @ejb.interface-method view-type="local"

    * @ejb.relation name="elementSlownika-Slownik"

              
role-name="typ ma wartosci"

    *

    *

    * @return a Collection of Slownik

    */

    public abstract Collection getWartosci();

     

    /**

    * @ejb.interface-method view-type="local"

    * @param Collection of wartosc

    */

    public abstract void setWartosci(Collection wartosc);

Obie strony relacji są identyfikowane poprzez nazwę: elementSlownika-Slownik.
Po obu stronach relacji zdefiniowano (oczywiście różne) nazwy ról. Po
stronie typu słownika jest jeszcze informacja o tym, iż metoda zwraca wartość
i to kończy definicję. Po stronie przeciwnej definicja relacji jest bardziej
rozbudowana. Określono tam m.in. docelowy komponent, nazwę kolumny dla klucza
obcego, obecność ograniczenia typu klucz obcy.

TypSlownika EJB

/**

*

* @ejb.bean name="TypSlownika"

* display-name="TypSlownika"

* description="TypSlownika EJB"

* jndi-name="ejb/TypSlownikaHome"

* type="CMP"

* cmp-version="2.x"

* view-type="local"

* local-jndi-name="ejb/TypSlownikaLocalHome"

* primkey-field="id"

* @ejb.persistence table-name="ttypslow"

* @ejb.value-object match="*" name="TypSlownika"

*

* @jboss.create-table "true"

* @jboss.remove-table "true"

* *

*

*@jboss.persistence create-table="true" pk-constraint="true"

*@ejb.util generate="physical"

*

*

*

* @ejb.finder signature="java.util.Collection findAll()"

* query="Select object(c) from TypSlownika as c"

*

* @ejb.finder signature="java.util.Collection
findByNazwa(java.lang.String nazwa)"

* query="Select object(c) from TypSlownika as c Where c.value= ?1"

*

*/

public abstract class TypSlownikaBean extends BaseEntityBean implements
EntityBean {

        /**

    *

    */

    public TypSlownikaBean() {

        super();

        // TODO Auto-generated constructor stub

    }

     

    /**

    * @ejb.create-method

    * @return

    * @throws CreateException

    */

    public String ejbCreate() throws CreateException {

       
setId(TypSlownikaUtil.generateGUID(this));

        return getId();

    }

    public void ejbPostCreate(){}

     

    /**

    * @ejb.interface-method view-type="local"

    * @ejb.persistence column-name="fid"

    *

    * @ejb.pk-field

    * @return

    */

    public abstract String getId();

     

    /**

    * @ejb.interface-method view-type="local"

    * @param id

    */

    public abstract void setId(String id);

     

    /**

    * @ejb.interface-method view-type="both"

    * @ejb.persistence column-name="fvalue"

    *

    * @param val

    */

    public abstract void setValue(String val);

     

    /**

    * @ejb.interface-method view-type="both"

    * @ejb.persistence column-name="fvalue"

    *

    * @return

    */

    public abstract String getValue();

     

    /**

    * @ejb.interface-method view-type="local"

    * @ejb.relation name="elementSlownika-Slownik" role-name="typ
ma wartosci"

    *

    *

    * @return a Collection of Slownik

    */

    public abstract Collection getWartosci();

     

    /**

    * @ejb.interface-method view-type="local"

    * @param Collection of wartosci

    */

    public abstract void setWartosci(Collection wartosci);

     

    /**

    * @ejb.interface-method view-type="both"

    *

    * @return

    */

    public abstract TypSlownikaValue getTypSlownikaValue();

     

    /**

    * @ejb.interface-method view-type="both"

    *

    * @param typSlownikaValue

    */

    public abstract void setTypSlownikaValue(TypSlownikaValue
typSlownikaValue);

}

Słownik EJB

/**

*

* @ejb.bean name="Slownik"

* display-name="Slownik"

* description="Slownik EJB"

* jndi-name="ejb/SlownikHome"

* type="CMP"

* cmp-version="2.x"

* view-type="both"

* local-jndi-name="ejb/SlownikLocalHome"

*

* primkey-field="id"

* @ejb.persistence table-name="tslow"

* @ejb.value-object match="*" name="Slownik"

* @jboss.persistence create-table="true" pk-constraint="true"

*

* @ejb.util

* generate="physical"

*

* @ejb.finder signature="java.util.Collection findAll()"

* query="Select object(c) from Slownik as c"

*

*

* @ejb.finder signature="java.util.Collection findBySlownikiTypu(

* java.lang.String pid_typu) "

* query="Select object(s) from Slownik as s where s.typSlownikaLocal.id
= ?1"

*

*

*/

public abstract class SlownikBean extends BaseEntityBean implements
EntityBean {

    public SlownikBean() {

        super();

    }

     

    /**

    * @ejb.create-method

    * @return

    * @throws CreateException

    */

    public String ejbCreate() throws CreateException {

            setId(SlownikUtil.generateGUID(this));

            return getId();

    }

    public void ejbPostCreate(){}

     

/**

    * @ejb.interface-method view-type="local"

    * @ejb.persistence column-name="fid"

    *

    * @ejb.pk-field

    * @return

    */

    public abstract String getId();

    public abstract void setId(String id);

     

    /**

    * @ejb.interface-method view-type="local"

    * @ejb.persistence column-name="fvalue"

    *

    * @return

    */

    public abstract String getValue();

     

    /**

    * @ejb.interface-method view-type="local"

    *

    * @param value

    *

    */

    public abstract void setValue(String value);

     

    /**

    * @ejb.interface-method view-type="local"

    * @ejb.relation name="elementSlownika-Slownik"

    * role-name="nalezy do slownika"

    * target-ejb="TypSlownika"

    * target-role-name="jest typem tego slownika"

    * target-multiple="true"

    * @jboss.relation related-pk-field="id" fk-column="typ_id"

    * fk-constraint="true"

    * @return

    */

    public abstract TypSlownikaLocal getTypSlownikaLocal();

     

    /**

    * @ejb.interface-method view-type="local"

    * @param typSlownikaLocal

    */

    public abstract void setTypSlownikaLocal(TypSlownikaLocal typSlownikaLocal);

     

    /**

    * @ejb.interface-method view-type="both";

    *

    * @return

    */

    public abstract SlownikValue getSlownikValue();

     

    /**

    * @ejb.interface-method view-type="both";

    *

    * @param slownikValue

    */

    public abstract void setSlownikValue(SlownikValue slownikValue);

     

    /**

    * @ejb.interface-method view-type="local"

    * @ejb.relation name="Osoba-Slownik"

    * target-role-name="osooba jest typu"

    * target-ejb="Osoba"

    * role-name="typ osoby"

    * *

    * @return

    */

}

Poniżej zdefiniowano przykładową metodę biznesową, która
pochodzi z sesyjnego EJB. Dodaje ona element (wartość) do danego słownika.
Jej XDoclet’owa definicja to określenie parametrów, informacje o tym, że
zawraca ona wartość i może rzucić wyjątek. Określono też jej typ widoczności.
Wartość both oznacza, iż jest ona widoczna zarówno lokalnie i
zdalnie, local – lokalnie, a remote – zdalnie. Od typu
widoczności zależy, w jakich interfejsach pojawi się deklaracja danej metody.
Jeżeli widoczność jest lokalna, to metoda pojawi się w interfejsie lokalnym,
jeżeli zdalna, to w zdalnym, jeżeli są obie (both), definicja pojawia
się w obu wygenerowanych automatycznie typach interfejsów – lokalnym i
zdalnym.

W obrębie tej metody:

  1. Wyszukiwany jest obiekt lokalny7 komponentu TypSlownika,
    identyfikowany przez przekazany jako argument klucz główny.
  2. Tworzony jest obiekt lokalny Slownik
  3. W obiekcie komponentu Slownik ustawia się
    przekazaną jako parametr nazwę i atrybut określający typ słownika

/**

    *

    * @param nazwaTypuSlownika

    * @param wartosc

    * @return

    * @throws Exception

    * @ejb.interface-method view-type = "both"

    */

public String dodajWartoscSlownika(String idTypuSlownika, String wartosc)

            throws Exception {

try{

 

TypSlownikaLocal typSlownika =
typSlownikaLocalHome.findByPrimaryKey(idTypuSlownika);

    SlownikLocal slownik = slownikLocalHome.create();

    slownik.setTypSlownikaLocal(typSlownika);

    slownik.setValue(wartosc);

    return slownik.getId();

 

    }catch(Exception e){

        e.printStackTrace();

    }

}

JDeveloper

Poniżej przedstawiono przykładowe klasy wygenerowane narzędziem
JDeveloper firmy Oracle. Obie klasy odpowiadające komponentom – encjom
zostały wygenerowane automatycznie przez narzędzie na podstawie istniejących
w bazie danych tabel. Ręcznie dopisano tylko ciało metody ejbCreate
tak, aby został tworzony klucz główny8. Oczywiście „pusta”
metoda została również wygenerowana automatycznie.

public abstract class Ttypslow1Bean implements EntityBean

{

    private EntityContext context;

     

    public String ejbCreate()

    {

        Random rand = new Random();

        int i = rand.nextInt(10000);

        String s = ""+i;

        setId(s);

        return s;

    }

 

    public void ejbPostCreate()

    {

    }

 

    public String ejbCreate(String id)

    {

        setId(id);

        return id;

    }

 

    public void ejbPostCreate(String id)

    {

    }

 

    public void ejbActivate()

    {

    }

 

    public void ejbLoad()

    {

    }

 

    public void ejbPassivate()

    {

    }

 

    public void ejbRemove()

    {

    }

 

    public void ejbStore()

    {

    }

 

    public void setEntityContext(EntityContext ctx)

    {

        this.context = ctx;

    }

 

    public void unsetEntityContext()

    {

        this.context = null;

    }

    public abstract String getId();

     

    public abstract void setId(String id);

     

    public abstract String getValue();

 

    public abstract void setValue(String value);

 

    public abstract Collection getTslow1_idTyp();

 

    public abstract void setTslow1_idTyp(Collection tslow1_idTyp);

}

 

package model;

import java.util.Random;

import javax.ejb.EntityBean;

import javax.ejb.EntityContext;

 

public abstract class Tslow1Bean implements EntityBean

    {

    private EntityContext context;

 

    public String ejbCreate()

    {

        Random rand = new Random();

        long i = rand.nextLong();

        String s = ""+i;

        setId(s);

         

        return s;

    }

 

    public void ejbPostCreate()

    {

    }

 

    public String ejbCreate(String id)

    {

        setId(id);

        return id;

    }

 

    public void ejbPostCreate(String id)

    {

    }

 

    public void ejbActivate()

    {

    }

 

    public void ejbLoad()

    {

    }

 

    public void ejbPassivate()

    {

    }

    public void ejbRemove()

    {

    }

 

    public void ejbStore()

    {

    }

 

    public void setEntityContext(EntityContext ctx)

    {

        this.context = ctx;

    }

     

    public void unsetEntityContext()

    {

        this.context = null;

    }

 

    public abstract String getId();

 

    public abstract void setId(String id);

     

    public abstract String getValue();

     

    public abstract void setValue(String value);

     

    public abstract Ttypslow1Local getTtypslow1_idTyp();

     

    public abstract void setTtypslow1_idTyp(Ttypslow1Local ttypslow1_idTyp);

}

Poniżej zaprezentowano prosty sesyjny EJB, którego szkielet
został wygenerowany automatycznie na postawie definicji dokonanej w
„trybie graficznym”. Narzędzie potrafi wygenerować metody tworzące
i zwracające interfejsy typu LocalHome dla określonych beanów. Określenie, z
jakimi EJB „współpracuje” dany komponent sesyjny, odbywa się w
„trybie graficznym” poprzez poprzez połączenie odpowiednich
komponentów. Pisząc sesyjne EJB należy pamiętać, iż nie można zdalnie
przekazywać „lokalnych” wartości beanów – encji. Można
zatem definiować metody beanów – encji z widocznością typu both,
albo gdy używa się widoczności lokalnej dla beanów – encji,
przekopiowywać wartości tych beanów do specjalnych pomocniczych obiektów
– wartości. Dotyczy to zarówno JDevelopera jak i MyEclipse.

Tslow1Local slow = (Tslow1Local)iter.next(); // interfejs lokalny

    Tslow1LocalDTO slowDTO = new Tslow1LocalDTO(slow);//przekopiowanie do

        //obiektu wartości

    c1.add(slowDTO);//dodanie objektu-wartości do kolekcji, która będzie

        //zwrócona zdalnie przez metodę biznesową sesyjnego EJB

 

public class SlowAppEJBBean implements SessionBean

{

    public void ejbCreate()

    {

    }

 

    public void ejbActivate()

    {

    }

 

    public void ejbPassivate()

    {

    }

 

    public void ejbRemove()

    {

    }

 

    public void setSessionContext(SessionContext ctx)

    {

    }

 

    private Ttypslow1LocalHome getTtypslow1LocalHome() throws NamingException

    {

        final InitialContext context = new InitialContext();

        return (Ttypslow1LocalHome)context.lookup("java:comp/env/ejb/local/Ttypslow1");

    }

 

    private Tslow1LocalHome getTslow1LocalHome() throws NamingException

    {

        final InitialContext context = new InitialContext();

        return (Tslow1LocalHome)context.lookup("java:comp/env/ejb/local/Tslow1");

    }

 

    public Collection pobierzZawSlow(String p1)

    {

        try

    {

    Collection typySlow = getTtypslow1LocalHome().findByNazwa(p1);

     if (typySlow==null || typySlow.size()!=1)

{

        return null;

    }

 

    Ttypslow1Local typSlow = (Ttypslow1Local)typySlow.iterator().next();

 

    Collection c = typSlow.getTslow1_idTyp();

    Collection c1 = new ArrayList();

    Iterator iter = c.iterator();

    for (;iter.hasNext();)

    {

        Tslow1Local slow = (Tslow1Local)iter.next();

        Tslow1LocalDTO slowDTO = new Tslow1LocalDTO(slow);

        c1.add(slowDTO);

    }

    return c1;

    }catch(Exception e)

    {

        e.printStackTrace();

    }

    return null;

    }

 

    public void stworzSlownik(String nazwaTypu)

    {

    try

    {

        Ttypslow1Local typSlow = getTtypslow1LocalHome().create();

        typSlow.setValue(nazwaTypu);

         

    }catch(Exception e)

    {

        e.printStackTrace();

    }

 

}

 

public void dodajElementDoSlow(String typName, String nazwaEl)

    {

    try

    {

        Collection typySlow = getTtypslow1LocalHome().findAll();

 

        if (typySlow==null)

        {

            System.out.println("typySlow is null");

           
return;

        }

 

        if (typySlow.size()!=1)

        {

            System.out.println("more then 1 ttypslow="+typName);

 

        }

 

        Ttypslow1Local typSlow = (Ttypslow1Local)typySlow.iterator().next();

 

        Collection c = typSlow.getTslow1_idTyp();

        Tslow1Local slow = getTslow1LocalHome().create();

        slow.setValue(nazwaEl);

        c.add(slow);

         

        }catch(Exception e)

        {

           
e.printStackTrace();

    }

    }

}

Literatura

[1] Materiały na www.oracle.com
[2] Dokumentacja narzędzia XDoclet na xdoclet.sf.net

c.d.n.