Herausforderungen mit JSF

xentity

Mitglied
Hallo liebe Javaner,

ich habe eine Applikation, die auf folgende Dinge setzt:
  • JSF 2.2
  • Java 11
  • Wildfly 14 als Application Server (vorrangig weil ich CDI nutze und damit fällt der Tomcat raus, TomEE habe ich nicht hinbekommen)
  • MySQL/MariaDB
  • Hibernate/JPA 2.1, managed JTA-DataSource vom Wildfly
Meine Schwierigkeiten sind:
  • Ich benötige leider zwei persistence units (eine als JTA und eine als RESOURCE_LOCAL, die von RunnableClasses genutzt werden), die Datenbank ist aber die gleiche. Ich finde das sehr unschön...
  • Änderungen direkt in der Datenbank werden von Hibernate nicht (immer) erkannt. Mitunter muss die Applikation neugestartet werden, damit die Änderungen im Web zu sehen sind.
  • Wildfly erstellt sehr viele Threads, wenn diese Application deployed ist, dabei ist noch nicht viel darauf los. Ist das in meinem Setup normal oder wie könnte ich das Troubleshooten?
Hat jemand von euch schon einmal diese Probleme gehabt?
 

mihe7

Top Contributor
Änderungen direkt in der Datenbank werden von Hibernate nicht (immer) erkannt. Mitunter muss die Applikation neugestartet werden, damit die Änderungen im Web zu sehen sind.
Cache. Second-Level-Cache abschalten und/oder in der Anwendung
Java:
        Cache cache = em.getEntityManagerFactory().getCache();
        cache.evictAll();
aufrufen - kannst Du z. B. einfach mittels JAX-RS deployen und dann von extern nach einer Änderung aufrufen.

Wildfly erstellt sehr viele Threads, wenn diese Application deployed ist, dabei ist noch nicht viel darauf los. Ist das in meinem Setup normal oder wie könnte ich das Troubleshooten?
Schau Dir mal mit jvisualvm an, um welche Art von Threads es sich überhaupt handelt.
 

Flown

Administrator
Mitarbeiter
Ich benötige leider zwei persistence units (eine als JTA und eine als RESOURCE_LOCAL, die von RunnableClasses genutzt werden), die Datenbank ist aber die gleiche. Ich finde das sehr unschön...
ich hab noch sehr wenig use cases gesehen, wo man in einem container umfeld resource_local benötigt. Kannst du das mal etwas erläutern?
Änderungen direkt in der Datenbank werden von Hibernate nicht (immer) erkannt. Mitunter muss die Applikation neugestartet werden, damit die Änderungen im Web zu sehen sind.
Kommt jetzt drauf an. Du musst dann deine Entities anders laden und öfters mal #refresh auf Entities anwenden.
Wildfly erstellt sehr viele Threads, wenn diese Application deployed ist, dabei ist noch nicht viel darauf los. Ist das in meinem Setup normal oder wie könnte ich das Troubleshooten?
Es gibt schon vorgewärmte reservierte Threads in den Threadpools, die nur auf Runnables warten. Nur weil sie da sind, heißt das nicht, dass sie auch Resourcen verbrauchen.
 

xentity

Mitglied
ich hab noch sehr wenig use cases gesehen, wo man in einem container umfeld resource_local benötigt. Kannst du das mal etwas erläutern?

Da die Applikation auch Nutzer-unabhängige Aktionen durchführt und ich keinen komfortablen Weg gefunden habe, von außen einen HTTP-Request auf JSF abzufeuern (zudem fand ich den Umstand ohne externen Trigger auszukommen sehr charmant), habe ich einen Runnable implementiert:

Java:
@Named
@RequestScoped
public class Cronjob implements Runnable {
    private EntityManager em;

    public Cronjob() {
        this.em = Persistence.createEntityManagerFactory("RLPU").createEntityManager();
    }

    public void Runner() {
        try {
            this.Demand();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
    
    private void Demand() {
        this.em.getTransaction().begin();
        this.em.createNativeQuery("...").executeUpdate();
        this.em.getTransaction().commit();
    }
}

Die Klasse wird von einem java.util.concurrent.ScheduledExecutorService alle 60 Minuten aufgerufen. Meine JTA DataSource heißt nur "PU", die konnte ich hier jedoch nicht nehmen, sondern musste eine Resource_Local verwenden, daher "RLPU". Es funktioniert, aber ich habe das Gefühl, das ist alles andere als elegant und bin für Alternativen für einen Crondienst offen.
 

mihe7

Top Contributor
Da die Applikation auch Nutzer-unabhängige Aktionen durchführt und ich keinen komfortablen Weg gefunden habe, von außen einen HTTP-Request auf JSF abzufeuern (zudem fand ich den Umstand ohne externen Trigger auszukommen sehr charmant), habe ich einen Runnable implementiert:
Java:
@Singleton
class Whatever {
    @PersistenceContext
    private EntityManager em;

    @Schedule(hour="*/1", minute="0", second="0", persistent=false)
    public void doSomethingEveryHour() {
        // mach was mit em
    }
}
könnte funktionieren.
 

Flown

Administrator
Mitarbeiter
Da die Applikation auch Nutzer-unabhängige Aktionen durchführt und ich keinen komfortablen Weg gefunden habe, von außen einen HTTP-Request auf JSF abzufeuern (zudem fand ich den Umstand ohne externen Trigger auszukommen sehr charmant), habe ich einen Runnable implementiert:
du kannst ja eine jax-rs schnittstelle bieten genau für solche Sachen. JSF ist ja nur ein View-Layer. Die Business Logik passiert hier nicht.
 

xentity

Mitglied
Java:
@Singleton
class Whatever {
    @PersistenceContext
    private EntityManager em;

    @Schedule(hour="*/1", minute="0", second="0", persistent=false)
    public void doSomethingEveryHour() {
        // mach was mit em
    }
}
könnte funktionieren.

Das war früher auch mein Ansatz und funktioniert auch mit allerhand Dingen, ABER wenn ich den Code auf @Schedule umstelle, bekomme ich das hier
A JTA EntityManager cannot use getTransaction() auf Grund solcher Zeilen:
Java:
this.em.getTransaction().begin();
this.em.persist(lt);
this.em.getTransaction().commit();

Ich hatte einiges mit UserTransactions wie auch in den normalen Named Beans versucht, aber das war eher try'n'error. Vor allem error. Mit dem RESOURCE_LOCAL konnte ich zumindest Transactions verwenden.
 

mihe7

Top Contributor
Das war früher auch mein Ansatz und funktioniert auch mit allerhand Dingen, ABER wenn ich den Code auf @Schedule umstelle, bekomme ich das hier
A JTA EntityManager cannot use getTransaction() auf Grund solcher Zeilen:
...
Ich hatte einiges mit UserTransactions wie auch in den normalen Named Beans versucht, aber das war eher try'n'error. Vor allem error. Mit dem RESOURCE_LOCAL konnte ich zumindest Transactions verwenden.
Ja, RESOURCE_LOCAL brauchst Du hier nicht. Die Klasse Whatever ist eine EJB. Der EJB-Container kümmert sich standardmäßig um die Transaktionsverwaltung, d. h. beim Aufruf der Methode wird sichergestellt, dass diese in einer Transaktion abläuft, die durch den EJB-Container auch wieder abgeschlossen wird. Wenn die Verwaltung der Transaktion dagegen von der EJB durchgeführt werden soll, kannst Du das per @TransactionManagement(TransactionManagementType.BEAN) annotieren.

Bei CDI-Beans (z. B. @Named) verhält es sich andersrum: dort findet im Normalfall keine Transaktionsverwaltung statt. Man kann durch entsprechende Annotationen eine solche in CDI-Beans einführen, wobei ich aber keine Vorteile gegenüber EJBs erkennen kann. Wenn sowieso ein EJB-Container zur Verfügung steht, sehe ich keinen Sinn darin, auf die Transaktionsverwaltung von EJBs zu verzichten.
 

Flown

Administrator
Mitarbeiter
Muss gestehen, dass ich bislang noch keine Berührungspunkte mit JAX-RS hatte :-/ Die Business Logik habe ich komplett in den Named Beans.
Ist kein Problem. Just another Bean. Du kannst dir das in die JAX-RS Schnittstelle injecten lassen und auch die Sachen ausführen lassen. Wobei Service zu schreiben hier sauberer wären (wenn die EJBs mit Transkationsverwatlung wären).
 

xentity

Mitglied
Der EJB-Container kümmert sich standardmäßig um die Transaktionsverwaltung, d. h. beim Aufruf der Methode wird sichergestellt, dass diese in einer Transaktion abläuft, die durch den EJB-Container auch wieder abgeschlossen wird.

Heißt also, wenn ich den Code beispielhaft in einer EJB so ändere:
Java:
//this.em.getTransaction().begin();
this.em.persist(lt);
this.em.persist(car);
this.em.persist(driver);
//this.em.getTransaction().commit();

wird sichergestellt, dass alle drei Objekte via Hibernate/JPA persistiert werden?

(Notiz an mich: JAX-RS und EJB-Konzept lernen)
 

xentity

Mitglied
Meine erste Rückmeldung nach einer gewissen Zeit: Seitdem ich die zweite PU entfernt habe (Pkt. 1), ist auch die Threat Usage des Wildfly extrem gering (Pkt. 3). Sehr geil :)

Das habe ich zum Anlass genommen, den Wildfly auf einen aktuellen Stand zu hieven. Dabei konnte ich nun auch keine Cache-Probleme (Pkt. 2) mehr feststellen. Weiß jetzt nur dummerweise nicht, ob die Beseitigung von 1 sich auf Pkt. 2 ausgewirkt hat oder ob der aktuelle Wildfly einen besseren Cache hat. Auf jeden Fall habe ich mir dokumentiert, was ich tun muss, falls ich nochmal ein Thema damit habe.

Ich danke euch!
 

Neue Themen


Oben