Breve storia: Sviluppiamo e gestiamo una libreria che può essere utilizzata in altri progetti utilizzando JavaEE7/CDI/JPA. Le applicazioni verranno eseguite con Glassfish-4.0 e utilizzeranno l'implementazione JPA di Hibernate per una persistenza PostgreSQL sottostante. Questo fa parte di uno sforzo di migrazione a lungo termine per riscrivere le vecchie applicazioni scritte in Spring/Struts/Hibernate nel nuovo mondo di JavaEE7/CDI/JTA.Come intercettare gli eventi delle transazioni JTA e ottenere un riferimento al EntityManager corrente associato alla transazione
Il problema: Per scopi di audit, la nostra biblioteca ha bisogno di intercettare tutte le transazioni di database e includono istruzioni SQL personalizzato prima vengono eseguite le istruzioni dell'utente. A questo punto, il nome utente e l'indirizzo IP correnti devono essere inseriti in una variabile di database temporanea (funzione specifica del fornitore) in modo che un trigger del database possa leggerli per creare la traccia di controllo per qualsiasi modifica di riga. This particular post was very helpful providing alternatives, e il nostro team è andato giù per la strada principale a causa di un patrimonio precedentemente stabilito.
TUTTAVIA: Siamo profondamente deluso di come JTA gestisce gli eventi di transazione. Esistono numerosi modi per intercettare le transazioni, ma questo caso particolare sembra essere assolutamente impossibile. Nella vecchia architettura, utilizzando il gestore delle transazioni di Spring, abbiamo semplicemente utilizzato un Hibernate Interceptor che implementa Interceptor.afterTransactionBegin (...). Leggendo il official JTA-1.2 spec, abbiamo trovato che ha il supporto per Synchronization.beforeCompletion e Synchronization.afterCompletion. Dopo diverse ore di sessioni di debug, abbiamo chiaramente notato che l'implementazione di JTA da parte di Hibernate utilizza queste strutture. Ma JTA sembra mancare di eventi come primaBin in arrivo e dopo il BUGin (che IMHO sembra essere una mancanza di buon senso). E poiché non ci sono strutture per intercettarle, Hibernate è completamente compatibile con JTA e semplicemente non lo farà. Periodo.
Non importa cosa facciamo, non riusciamo a trovare un modo. Abbiamo tentato, ad esempio, di intercettare le annotazioni @Transactional ed eseguire il nostro codice subito dopo che l'impl JTA del container ha fatto il suo lavoro per aprire la transazione. Ma ci manca la capacità di acquisire dinamicamente l'EntityManager associato a quella particolare transazione. Ricorda: questa è una libreria, non l'applicazione web stessa. Non può formulare ipotesi su quali Unità di Persistenza siano dichiarate e utilizzate dall'applicazione. E, per quanto possiamo dire, abbiamo bisogno di sapere quale specifico nome Persistent Unit per iniettarlo nel nostro codice. Stiamo cercando di fornire una struttura di controllo ad altri temi che sia il più trasparente possibile.
Quindi chiediamo umilmente aiuto. Se qualcuno là fuori ha una soluzione, una soluzione, qualsiasi opinione, saremo felici di sentirlo.
Ignorare completamente JPA e aggiungere un intercettore sul lotto di connessione del database effettivo? So solo come farlo in Tomcat jdbc.pool, ma uno spera che Glassfish abbia un modo. – Affe
Potrebbe essere il caso, ma a questo livello non penso che abbiamo accesso alla sessione Http per acquisire qualsiasi utente che abbia effettuato l'accesso o il suo indirizzo IP del client. – JulioHM