Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

pozivanje metode remote EJB-a, pitanje

[es] :: Java :: pozivanje metode remote EJB-a, pitanje

[ Pregleda: 1154 | Odgovora: 6 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Hatori_henzo
Yves Al Gadafi
Studentarija
Beograd

Član broj: 185220
Poruke: 17
*.dynamic.sbb.rs.



Profil

icon pozivanje metode remote EJB-a, pitanje08.06.2011. u 16:09 - pre 156 meseci
Počeo sam da pravim neku JSF aplikaciju, sa ciljem da se bolje upoznam sa JSF-om i J2EE konceptima uopšte, pa imam jedno pitanje...Znam da sve zavisi od velikog broja stvari, al cu pokušati da budem što precizniji.

Situacija je sledeća:
- Web aplikacija koja je deploy-ovana na Glassfish(3.1 čini mi se)

-EAR aplikacija koja je isto deploy-ovana na tom serveru
EAR fajl u suštini u sebi sadrži samo jedan EJB modul, sa EJB-om, njegovim Local interfejsom i jednom klasom Users, koja se preslikava u MySQL entitet.

EJB remote interfejs razvijam u zasebnom projektu, kako bi mogao samo da uključim njega u biblioteku web aplikacije, a onda preko JNDI-a da pronađem EJB i pozovem metodu koja mi treba...

Obe aplikacije deploy-ujem i pokrećem direktno iz NetBeans-a 6.9.1. MySQL 5.5.12 (Community Edition) pokrećem zasebno.

E sad, sve radi kako treba, web aplikacija na odredjenoj stranici nadje EJB, on preko EntityManagera pristupi bazi, izvrši upit i vrati HashMap<String,String>, što i treba da vrati. Samo ne znam zašto se pretraga EJB-a i poziv njegove metode dešavaju DVA PUTA? Sad ću da postavim relevantne delove koda, pa ako neko može da mi objasni, ima virtuelno pivce od mene

BeanOneRemote : (EAR)
Code:

@Remote
public interface BeanOneRemote {

    public HashMap<String,String> returnDomainObjects();
}


BeanOne : (EAR)
Code:

@Stateless
public class BeanOne implements BeanOneRemote, BeanOneLocal {

   @PersistenceContext(unitName = "jsf-demoEJBPU")
    private EntityManager em;
...
@Override
    public HashMap<String,String> returnDomainObjects() {
    HashMap<String,String> hashMap = new HashMap<String,String>();
        try{

            Query q = em.createNamedQuery("Users.findByUserId");
            q.setParameter("userId", 1);
            Users u  = (Users) q.getSingleResult();
            hashMap = u.returnAttributeValues();
        }
        catch(Exception e){
            System.out.println(e.getMessage());
        }
        
        return hashMap;
    }


FindUserBean : (WEB)
Code:

@ViewScoped
@Named
public class FindUserBean{
private BeanOneRemote bean;

...
public void setBean() {
        this.bean = lookupBeanOneRemote();//Postavlja bean nakon konstrukcije
    }
@PostConstruct
    private void init(){
    setBean();
    }

public String getObjekti(){
      String odg =null;
      try{
         HashMap<String,String> niz =bean.returnDomainObjects();
         if(niz!=null){
              System.out.println(niz.get("userId")+" - "+niz.get("userUsername")+" - "+niz.get("userPassword")+" - "+niz.get("userMail"));
              odg = "truc";
           }
         }
       catch(Exception e) {
              System.out.println(e.getMessage());
              odg= "bla";
          }
        
   return odg;
    }
...
private BeanOneRemote lookupBeanOneRemote() {
        if(bean==null){ //Ovo mozda ni ne treba, al sam stavio aj za svaki slucaj...
            try {
            Context c = new InitialContext();
            Properties p = new Properties();
            p.put("java.naming.factory.initial", "com.sun.enterprise.naming.impl.SerialInitContextFactory");
            p.put("java.naming.factory.url.pkgs", "com.sun.enterprise.naming.impl");
            System.out.println("properties se puni vrednostima...");
            p.put("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
            c = new InitialContext(p);
            System.out.println("Pre trazenja ejb-a");
            BeanOneRemote b = (BeanOneRemote) c.lookup("java:global/E-Learning/jsf-demoEJB/BeanOne!prvi.BeanOneRemote");
            
            System.out.println("Nadjen EJB - "+b.toString());
            return b;

        } catch (NamingException ne) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
            throw new RuntimeException(ne);
        }
            }
        else return bean;
    }

i na kraju
stuff.xhtml :
Code:

<ui:composition
    template="template.xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

    <ui:define name="skripte">
    </ui:define>
<ui:define name="mainbar">
    <div class="article">
        <h:outputText value="#{findUserBean.objekti}"/><!-- ovo je neki string koji dobijam preko metode getObjekti, a u kojoj radim System.out.println()-ove, da bi znao šta je vraćeno od beana -->
    </div>
</ui:define>
</ui:composition>

A ovo izbacuju System.out.println()-ovi:

INFO: properties se puni vrednostima...
INFO: Pre trazenja ejb-a
INFO: Nadjen EJB - prvi._BeanOneRemote_Wrapper@1305ee63
INFO: 2 - Axl - Rose - [email protected]
INFO: properties se puni vrednostima...
INFO: Pre trazenja ejb-a
INFO: Nadjen EJB - prvi._BeanOneRemote_Wrapper@1305ee63
INFO: 2 - Axl - Rose - [email protected]


Znaci u suštini radi sve kako treba što se tiče povezivanja web aplikacije sa EJB modulom, i njega sa bazom, samo ako neko može da mi kaže zašto se lookupBeanRemote() i
getObjekti() pozivaju dva puta?


 
Odgovor na temu

branecns
Branislav Černić
Novi Sad

Član broj: 28805
Poruke: 40
*.static.kdsinter.net.



Profil

icon Re: pozivanje metode remote EJB-a, pitanje08.06.2011. u 22:42 - pre 156 meseci
Citat:
Hatori_henzo: Znaci u suštini radi sve kako treba što se tiče povezivanja web aplikacije sa EJB modulom, i njega sa bazom, samo ako neko može da mi kaže zašto se lookupBeanRemote() i getObjekti() pozivaju dva puta?


Mislim da to nije do ejb-a vec do jsf-a. Radi testa, mozes da napises da ti getObjekti() vrati bilo kakav string i da preskocis povezivanje na ejb, i trebalo bi da se opet 2 puta ode na metod. Ukoliko je to slucaj, mozes da napises phase listener za jsf i stavis break point na getObjekti() pa da vidimo u kojim se sve fazama jsf life cycle-a ulazi u taj metod. Ovde imas dobro uputstvo za to [url=http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html][/url]. Ako na taj nacin uhvatis nesto, onda je najbolje da getObjekti() metod obrnes na lazy loading, znaci, samo ako je niz == null, uradis povezivanje na bazu.
 
Odgovor na temu

Hatori_henzo
Yves Al Gadafi
Studentarija
Beograd

Član broj: 185220
Poruke: 17
*.dynamic.sbb.rs.



Profil

icon Re: pozivanje metode remote EJB-a, pitanje09.06.2011. u 10:40 - pre 156 meseci
Hvala na sugestijama branecns...

Napravio sam phase listener koji radi sa PhaseId.ANY_PHASE, izostavio sam @PostConstruct metodu gde se inicijalizuje bean, tako da je on sada null, i ne vrši se njegova pretraga. Bio si u pravu da će se getObjekti() pozivati dva puta, evo šta dobijem:

INFO: START PHASE RESTORE_VIEW 1
INFO: END PHASE RESTORE_VIEW 1
INFO: START PHASE RENDER_RESPONSE 6
INFO: Napravljen FindUserBean...
INFO: Pozvana metoda getObjekti...
INFO: Napravljen FindUserBean...
INFO: Pozvana metoda getObjekti...
INFO: END PHASE RENDER_RESPONSE 6


E sad, malo sam eksperimentisao, znači ako u nekoj drugoj stranici stavim <h:outputText value=...>, gde je value String nekog SessionScoped beana, dobijam:

INFO: START PHASE RESTORE_VIEW 1
INFO: END PHASE RESTORE_VIEW 1
INFO: START PHASE RENDER_RESPONSE 6
INFO: Napravljen user bean..
INFO: Get password user bean-a...
INFO: Get password user bean-a...
INFO: END PHASE RENDER_RESPONSE 6

Znači da se on pravi samo jednom, što i ima logike, ali se opet getPassword() u ovom slučaju poziva dva puta. Ako nekim slučajem na stranici dva puta referenciram neki atribut ovog session beana, recimo username, getUsername će se pozvati 4 puta.

Ne znam da li je ovo do implementacije JSF-a (Sun-ova Mojarra 2.0.1) ili sam ja nešto u startu loše podesio.

Probaću kasnije ovo sa proverom za null, pa da vidim šta će da se desi...
 
Odgovor na temu

branecns
Branislav Černić
Novi Sad

Član broj: 28805
Poruke: 40
*.static.kdsinter.net.



Profil

icon Re: pozivanje metode remote EJB-a, pitanje09.06.2011. u 11:47 - pre 156 meseci
Citat:
Hatori_henzo
Znači da se on pravi samo jednom, što i ima logike, ali se opet getPassword() u ovom slučaju poziva dva puta. Ako nekim slučajem na stranici dva puta referenciram neki atribut ovog session beana, recimo username, getUsername će se pozvati 4 puta.

Ne znam da li je ovo do implementacije JSF-a (Sun-ova Mojarra 2.0.1) ili sam ja nešto u startu loše podesio.

Probaću kasnije ovo sa proverom za null, pa da vidim šta će da se desi...


Znaci oba puta je u render response fazi. Posto koristis jsf 2.0 na glassfishu 3.1, da li ti je ukljucen cdi? To ces videti ako u web-inf-u projekta imas i beans.xml fajl. Ako je tako, onda ce se za jsf bean napraviti client proxy, tada se poziva konstruktor bez argumenata, a drugi put se poziva @Inject konstruktor, ako ga imas, ili ponovo ovaj prazan, u svakom slucaju, poziva se 2 puta. Tako radi cdi. Zato, ako npr imas u konstruktoru odlazak na bazu, onda taj deo koda premestis u @PostConstruct metod. A u get metodama radis onaj lazy loading.
E sad, ako cdi nije prisutan, onda je najbolje da skines neku demo aplikaciju sa vec napisanim web.xml i faces-config fajlovima, a da takodje nije cdi, pa da vidis koliko puta se tu poziva konstruktor i uporedis projekat sa tvojim.
 
Odgovor na temu

Hatori_henzo
Yves Al Gadafi
Studentarija
Beograd

Član broj: 185220
Poruke: 17
*.dynamic.sbb.rs.



Profil

icon Re: pozivanje metode remote EJB-a, pitanje09.06.2011. u 12:58 - pre 156 meseci
Jeste, CDI je uključen, negde sam prečitao u nekoj knjizi da ako možeš da biraš između @ManagedBean i @Named anotacija, da uvek odabereš ovu drugu, naravno ako app server to podržava, pošto su dosta "moćniji" :) ... Doduše nisam ništa dodavao beans.xml fajlu, samo mu stoji <root></root>.

Sad sam u metodu getObjects() FindUserBean-a stavio
Code:

...
      if(objekti==null){
          System.out.println("Poziva se get objekti, objekti su bili null...");
        this.objekti="objekti namesteni u getObjekti";

      }
        return objekti;

a string objekti sam inicijalizovao u konstruktoru, i na stranici se ispisuje upravo ta vrednost, znači nikad se ne ulazi u if blok getObjects()-a, ali se opet metoda poziva dvaput. Konstruktor se isto pozove dvaput, kao što si rekao.

Znači sve u svemu, ukoliko sam ja dobro razumeo, ako koristim CDI beanove u aplikaciji, njihov konstruktor (ili no-arg ili Inject) će se uvek pozvati dvaput, a i get metode koje se koriste za prikaz stringova na stranici (najbanalniji primer). Jedino što mogu da uradim je da vršim proveru da li je vrednost već inicijalizovana, pa da radim inicijalizaciju samo u slučaju kad nije. Ovo mi nekako deluje kao trošenje resursa, al šta ja znam :)

Recimo kad u konstruktoru stavim :
Code:

        System.out.println("Napravljen FindUserBean...");
        System.out.println("String je inicijalizovan u konstruktoru...");
        this.objekti="objekti namesteni u konstruktoru";
        this.objekti1="objekti1 namesteni u konstruktoru";
        this.objekti2="objekti2 namesteni u konstruktoru";

a na stanici :
Code:

...
        <h:outputText value="#{FindUserBean.objekti}"/>
        <h:outputText value="#{FindUserBean.objekti1}"/> // Stringovi, u geterima isto koristim if(objekti1==null){inicijalizuj...}
        <h:outputText value="#{FindUserBean.objekti2}"/>

dobijem output:

INFO: START PHASE RESTORE_VIEW 1
INFO: END PHASE RESTORE_VIEW 1
INFO: START PHASE RENDER_RESPONSE 6
INFO: Napravljen FindUserBean...
INFO: String je inicijalizovan u konstruktoru...
INFO: Napravljen FindUserBean...
INFO: String je inicijalizovan u konstruktoru...
INFO: Napravljen FindUserBean...
INFO: String je inicijalizovan u konstruktoru...
INFO: Napravljen FindUserBean...
INFO: String je inicijalizovan u konstruktoru...
INFO: Napravljen FindUserBean...
INFO: String je inicijalizovan u konstruktoru...
INFO: Napravljen FindUserBean...
INFO: String je inicijalizovan u konstruktoru...
INFO: END PHASE RENDER_RESPONSE 6


Znači 6 puta sveukupno...čudi me pošto je bean ViewScoped, zar ne bi trebalo da su,nakon njegove konstrukcije, svi atributi dostupni sve dok se ostaje na istom view-u tj. nema potrebe da se bean inicijalizuje svaki put kada se traži neki njegov atribut. Ako ima neki dobar tutorial ili blog/info/etc o ovome, rado ću ga pročitati :)

 
Odgovor na temu

branecns
Branislav Černić
Novi Sad

Član broj: 28805
Poruke: 40
*.static.kdsinter.net.



Profil

icon Re: pozivanje metode remote EJB-a, pitanje09.06.2011. u 14:58 - pre 156 meseci
Citat:
Hatori_henzo
Znači 6 puta sveukupno...čudi me pošto je bean ViewScoped, zar ne bi trebalo da su,nakon njegove konstrukcije, svi atributi dostupni sve dok se ostaje na istom view-u tj. nema potrebe da se bean inicijalizuje svaki put kada se traži neki njegov atribut. Ako ima neki dobar tutorial ili blog/info/etc o ovome, rado ću ga pročitati :)


Taj prazan beans.xml fajl je dovoljan da preko anotacija koristis cdi, zato cim server skonta da u aplikaciji postoji makar i prazan beans.xml, cdi je ukljucen. @Named anotacija ti treba da ne moras u faces-config da definises ime za svaki tvoj bean, a treba da je koristis u sklopu sa @scoped anotacijama kao sto i stoji kod tebe. E sad, posto koristis cdi, onda je najbolje da izbacis @ViewScoped i umesto nje iz nekog cdi paketa da koristis @ConversationScoped. Pa onda s time testiraj ponovo koliko puta ce se uci u konstruktor. On ne bi trebao da okine kreiranje jsf beana na svakom zahtevu. Uopste, sve scoped anotacije uvozi iz javax.enterprise.context, sad sam pogledao kako se tacno paket zove. A za pozivanje konstruktora redosled je uvek prvo no-arg konstruktor za client proxy, a onda drugi put vec tvoj konstruktor koga si zamislio, sto ce u vecini slucajeva verovatno biti neki @Inject konstruktor. Potrazi na netu JSR-299 i skini konacnu specifikaciju, a nacices na tu temu i po koji tutorial.
 
Odgovor na temu

Hatori_henzo
Yves Al Gadafi
Studentarija
Beograd

Član broj: 185220
Poruke: 17
*.dynamic.sbb.rs.



Profil

icon Re: pozivanje metode remote EJB-a, pitanje09.06.2011. u 18:37 - pre 156 meseci
Hvala na odgovorima branecns, evo ti i pivce koje sam obećao :)

Sad sam stavio da je ConversationScoped, i kada prvi put pristupim stranici dobijam

INFO: START PHASE RESTORE_VIEW 1
INFO: END PHASE RESTORE_VIEW 1
INFO: START PHASE RENDER_RESPONSE 6
INFO: Napravljen FindUserBean...
INFO: String je inicijalizovan u konstruktoru...
INFO: Napravljen FindUserBean...
INFO: String je inicijalizovan u konstruktoru...
INFO: Poziva se get objekti...
INFO: Poziva se get objekti1...
INFO: Poziva se get objekti2...
INFO: Poziva se get objekti...
INFO: Poziva se get objekti1...
INFO: Poziva se get objekti2...
INFO: END PHASE RENDER_RESPONSE 6


Znači 2 puta ce poziva konstruktor i po dva puta svaka od get metoda(stavio sam i unutar njih sout, čisto da znam), što je valjda i standard.
Kada opet pristupim toj stranici, konstruktor se pozove jednom(pošto je valjda onaj proxy već napravljen, to je moja interpretacija :) ) a metode opet po dva puta, što je valjda isto ok ako u svakoj budem vršio proveru da li je nešto već instancirano...

Treba još da pogledam Conversation objekat koji se Inject-uje, a koji sad nisam koristio...Hvala branecns, pogledaću još malo sve to pa postavljam opet pitanje ako nešto ne bude najjasnije :)
 
Odgovor na temu

[es] :: Java :: pozivanje metode remote EJB-a, pitanje

[ Pregleda: 1154 | Odgovora: 6 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.