2013-05-13 4 views
5

Immaginate di avere un filtro che avvia una transazione di database, elabora la richiesta e quindi tenta di eseguire il commit della transazione.È possibile eseguire il filtraggio servlet tradizionale con JAX-RS/Jersey?

doFilter(...) { 
    ... 
    transaction.begin(); 
    filterChain.doFilter(request, response); 
    transaction.commit(); 
} 

Utilizzando Jersey, ci sono alcuni problemi:

  1. utilizzando un filtro, il Jersey Servlet Container impegna/svuota il risposta prima esecuzione torna al vostro filtro. Quindi, se il commit fallisce, non è possibile modificare il codice di ritorno in modo errato. Inoltre, eccezioni non verranno rilevate da un ExceptionMapper JAX-RS.
  2. Utilizzo di ContainerRequestFilter/ContainerResponseFilter.

    filtro ContainerRequest pubblico (richiesta ContainerRequest) { ...}
    filtro ContainerResponse pubblico (richiesta ContainerRequest, risposta ContainerResponse) { ...}

Questo permette eccezioni a ribollire ad un ExceptionMapper, ma divide la logica su 2 metodi/interfacce separate. Il problema è che se c'è un'eccezione che non si associa a una risposta, ContainerResponseFilter non viene mai chiamato, quindi non è possibile eseguire la pulizia.

Qual è il modo migliore di gestirlo in un ambiente JAX-RS? C'è un modo per configurare lo svuotamento della risposta, o c'è una classe o un'interfaccia che sto trascurando?

+0

Quello che descrivi è comunemente noto come il pattern "aperto in vista" (anti-). Vedi [questa domanda SO] (http://stackoverflow.com/q/1103363/131929) per una discussione. Passa anche a JBoss (Hibernate/Seam) per ulteriori discussioni, ad es. https://community.jboss.org/docs/DOC-13954 –

+0

C'è sicuramente qualche discussione su cosa sia esattamente una "vista", ma questa è solo un'applicazione REST. I metodi di risorse jax-rs sono il livello di servizio e utilizzano direttamente la persistenza. L'oggetto risposta è il risultato della chiamata di servizio. Sto cercando di evitare di avere la gestione delle transazioni in ogni metodo, e la risposta è qualcosa che assomiglia a un filtro, o collego l'intercettazione CDI (che vorrei evitare a questo punto del progetto, se posso). – Shaun

risposta

3

Ho svolto ricerche un po 'anche per un'applicazione JAX-RS/RESTEasy. Le due opzioni Stavo considerando prima di leggere questa domanda:

  1. Scrivere un ExceptionMapper<Throwable> (o ExceptionMapper<DaoException> con un costume DaoException) e gestirlo lì o nel ContainerResponseFilter che andranno eseguiti a causa della gestione di tutte le eccezioni ExceptionMapper<?>.
  2. Prima di transaction.begin(), controllare lo stato corrente della transazione e eseguire il rollback se necessario.

Ci sono problemi con entrambe le opzioni.

  1. trovo un ExceptionMapper<Throwable> troppo ampia, mentre la ExceptionMapper<DaoException> potrebbe perdere qualche altra eccezione, ancora una volta lasciando la transazione non ripulito.
  2. Il rollback della transazione sulla richiesta successiva potrebbe richiedere molto tempo, causando probabilmente problemi di blocco per altre transazioni.

Così, dopo aver letto la tua domanda, attualmente sto pensando:

  • Utilizzando un ContainerRequestFilter per iniziare le operazioni (in combinazione con la costruzione @NameBinding annotazione).
  • Utilizzo di un ContainerResponseFilter per il commit delle transazioni (se il metodo di risorsa non lo ha ancora chiuso).
  • Utilizzare un Filter per assicurarsi che la transazione sia stata chiusa e, in caso contrario, ripristinarla.
+0

Come intendi "ExceptionMapper troppo ampio"? Se si controlla la sessione per una transazione attiva in un ExceptionMapper , si può essere certi che qualcosa è andato storto e il rollback. Se nessuna transazione attiva, non fare nulla. Il problema che vedo è se il transaction.commit() non riesce nel ContainerResponseFilter, l'oggetto risposta dovrebbe essere modificato. Non sai cosa succede se un'eccezione viene lanciata in ContainerResponseFilter, verrà rilevata da ExceptionMapper? – joscarsson

+0

Troppo ampio nel senso che potresti avere anche un 'ExceptionMapper '. Quale 'ExceptionMapper ' gestirà l'eccezione? Prima quella per 'SpecificException' e poi quella per' Throwable'? Oppure il secondo ingerirà una 'SpecificException'? – drvdijk

Problemi correlati