FacesContext poza requestem

0

Kontynuując mój poprzedni wątek (Cykliczne zadanie umieszczone w aplikacji webowej) mam problem z dostępem do beansów z wątku - prawdopodobnie FacesConfig nie istnieje poza requestami.
Stąd też nie mam jak otrzymać instancji tego singletonu oraz pobrać wymaganych przeze mnie beansów.

Kod wątku:

@Override
public void run()
{
    while (true)
    {
        try
        {
            TimeView timeView = (TimeView)FacesContext.getCurrentInstance().
                    getExternalContext().getApplicationMap().get("timeView"); 
            // FacesContext.getCurrentInstalce() returns null

            timeView.update();
            Thread.sleep(10000);
        }
        catch (InterruptedException ex)
        {
            System.out.println(ex);
        }
    }
}

Nagłówek beanu TimeView:

@ManagedBean(eager=true, name="timeView")
@ApplicationScoped
public class TimeView implements Serializable
{
    private int hour;
    private int minutes;
    private int seconds;

    public TimeView()
    {
        update();
    }

    public void update()
    {
        Date date = new Date();
        setHour(date.getHours());
        setMinutes(date.getMinutes());
        setSeconds(date.getSeconds());
    }

faces-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">

    <managed-bean>
        <managed-bean-name>timeView</managed-bean-name>
        <managed-bean-class>foogame.viewBeans.TimeView</managed-bean-class>
        <managed-bean-scope>application</managed-bean-scope>
    </managed-bean>
</faces-config>

Tak więc - moje pytanie - jak uzyskać dostęp do tych beanów, lub, jaki jest alternatywny sposób na generowanie contentu strony co x sekund (aby pominąć powtarzania tych samych zapytań).

0

A czemu korzystasz tutaj z external context?
Wstrzyknij po prostutego bina aplikacyjnego w miejsce grze będziesz startował wątek (listener? RequestScopedBean?)
Będzie to wyglądało mniejwięcej tak:

@ManagedBean
public class mojGenialnyBean
{
@ManagedProperty(name="#{timeView})
TimeView wstrzyknietyTimeView;

...


na końcu gettery i settery do timeview są niezbędne (bardziej settery tutaj - jednen:P)
}
1

jesli twoj bean jest typu @ApplicationScoped to mozesz sobie ten object wyciagnac z ServletContext.

ServletContext context = contextObject; //listener, spring, ...etc
TimeView bean = (TimeView) context .getAttribute("timeView");

to co pisze Antoniossss jest troche bez sensu, bo:

  • pojerzewam ze uruchumiasz nowy thread przy utworzeniu objektu (??) jesli zrobic odzielny watek w twoim beanie a bean jest typu request albo view to zapchasz sobie procesor tysiacami utworzonych watkow. Bean typu request bedzie tworzony przy kazdym zapytaniu a bean typu view za kazdym razem jak odswiezsz strone.

  • @ManagedProperty musi byc utworzene w klasie oznaczonej jako @MangedBean ( http://docs.oracle.com/javaee/6/api/javax/faces/bean/ManagedProperty.html ) , wiec nie mozesz wstrzyknac applicationBean gdzie indziej.

0

Visher chce miec z watku dostep do Beana TimeView. Nie moze przez FacesContext.getCurrentInstance(), bo jak wywola to poza JSF Lifecycle, to FacesContext.getCurrentInstance() zwroci mu null. Dlatego szuka innego sposobu zeby dostac sie do tego TimeView. Ty dales przyklad z klassa mojGenialnyBeanales, ale tez piszesz, ze watek moze byc zdefiniowany w innym miejscu niz w mojGenialnyBeanales. To po cholere jest ten mojGenialnyBean?? zeby tylko miec referencje do TimeView?? ale po co ? on nie chcial referencji do TimeView z jakiegos bean'a tylko z watku! . Czyli jak jego watek lezy w innej klasie niz mojGenialnyBean, to mu twoje rozwiazanie nic nie daje, bo mam ten sam problem. JAK DOSTANE SIE DO TimeView BEAN Z WATKU ??? Dlatego jesli twoj przyklad mial by dzialac to ten watek powinien byc uruchomniony w klasie mojGenialnyBean, co nie jest dobrym pomyslem, co juz napisalem post wyzej.

ty piszesz: "Wstrzyknij po prostutego bina aplikacyjnego w miejsce grze będziesz startował wątek (listener? RequestScopedBean?)"

nie moze go wstrzyknac do listener. ManagedBean moga byc tylko wstrzykiwane do innych ManagedBean. W nawiasie podajesz ze moze "bina" aplikacyjnego wstrzyknac do RequestScopedBean (przypominam cale zdanie "Wstrzyknij po prostutego bina aplikacyjnego w miejsce grze będziesz startował wątek (listener? RequestScopedBean?)"). Czyli proponujesz zeby watek byl wystartowany w RequestScopedBean . W komentarzu piszesz mi ze "ja nic nie proponuje o watkach" w odpowiedzi na moj komentarz "proponujesz wystartowac nowy watek w ManagedBean". Mam takie dziwne wrazenie, ze zaprzeczasz sam sobie. Chyba ze RequestScopedBean to nie jest zadne ManagedBean? To przepraszam, ale po co wtedy ten przyklad z mojGenialnyBean?? przyznaje sie, ja tego nie rozumiem...

Mam nadzieje, dosc jasno sie wyrazilem

0

Problem rozwiązany, dzięki mwill za odpowiedź.

Mój wątek rozwinąłem o konstruktor wymagający ServletContext, który otrzymuję w listenerze przy wywołaniu contextInitialized.

public class BeansRefresher extends Thread
{
    private ServletContext servletContext;
    
    public BeansRefresher(ServletContext servletContext)
    {
        this.servletContext = servletContext;
    }
    
    @Override
    public void run()
    {
        while (true)
        {
            try
            {
                Enumeration<String> attrNames = servletContext.getAttributeNames();
                boolean exists = false;
                
                while (attrNames.hasMoreElements() && !exists)
                    if (attrNames.nextElement().equals("timeView"))
                        exists = true;
                    
                if (exists)
                {
                    TimeView timeView = (TimeView)servletContext.getAttribute("timeView");
                    timeView.update();
                }

                Thread.sleep(10000);
            }
            catch (InterruptedException ex)
            {
                System.out.println(ex);
            }
        }
    }
}

Niestety, muszę sprawdzać czy bean istnieje, w momencie tworzenia contextu jest jeszcze za wcześnie.

0

Nie musisz iterowac przez wszystke atrybuty zapisane w ServletContext (i tak ich nie ma tam duzo). Nie lepiej bylo by takie cos ?

    TimeView timeView = (TimeView)servletContext.getAttribute("timeView");
    if(timeView  != null)  timeView.update();

0
@ManagedBean
@ApplicationScoped /*sesiion view request - czy to sensowne - nie temat roważania - można? można! */
public class mojGenialnyBean /* extends Runnable? /*
{
@ManagedProperty(name="#{timeView})
TimeView wstrzyknietyTimeView;
 
/* jak nie extends to new Thread(new Runnable()) i jak niżej z dołożeniem dodatkowego final TimeView tmp=wstrzyknietyTimeView */
@override
public void run()
{
    wstrzyknietyTimeView.update();
}
...

}

i tą całość w wątek; będzie dostęp z wątku? będzie

0

@ApplicationScoped bylo byl juz najrozsadniejszym rozwiazaniem, ale wtedy by niemusial by nic wstrzykiwac, Thread moglby byc wytartowany w samym TimeView. Odnosnie twojego pytania dotyczacego zlych praktyk: jesli bean byl by request scope, to nowy watek byl byl za kazdym razem uruchomiany przy tworzeniu bean'a. zeby temu zapobiedz musial bys jakos sprawdzac czy watek nie został juz wystartowany. To wiaze sie z dodatkowymi zasobami, dodatkowym kodem. Kompleksowosc aplikacji rosnie. Uwazam to za zla praktyke, jesli mozna to inaczej i w bardzo prosty sposob rozwiazac, bez tej dodatkowej zbednej logiki.

0
mwili napisał(a):

jesli bean byl by request scope, to nowy watek byl byl za kazdym razem uruchomiany przy tworzeniu bean'a.

jeżeli byśmy byli na tyle "mądrzy". Jak to mawiał mój Profesor - "Oczywista oczywistość"

mwili napisał(a):

zeby temu zapobiedz musial bys jakos sprawdzac czy watek nie został juz wystartowany.

Właśnie o tym pisałem powyżej.

Generalnie zdaje się, że opisaliśmy to samo z tą różnicą, że ja na pytanie "Czy można głową wbijać gwoździe" odpowiedziałem że tak, Ty zaś zasugerowałeś, że owszem, ale są do tego młotki;]
Thx

1 użytkowników online, w tym zalogowanych: 0, gości: 1