2010-10-29 14 views
14

L'applicazione Java EE 6 è composta da un modulo war e ejb contenuto in un file ear. Sto usando CDI per DI (ad esempio, ho un file beans.xml in entrambi i moduli). Voglio usare un intercettore di logging che è definito anche nel modulo ejb nel modulo war. Ho permesso l'intercettore in beans.xml del bean:CDI: utilizzo di Interceptor su diversi moduli/archivi bean

<beans> 
    <interceptors> 
     <class>com.test.interceptor.LoggingInterceptor</class> 
    </interceptors> 
</beans> 

Questo funziona solo per le classi che sono annotati con l'intercettore nel modulo EJB . Le classi nel modulo war non vengono intercettate (sebbene siano annotate anche con l'intercettatore). Pensavo che la soluzione sarebbe stata quella di abilitare l'intercettore nell'intercettore della guerra, come pure (come sopra). Ma l'applicazione non può essere distribuito con il seguente messaggio:

GRAVI: eccezione durante il caricamento dell'app: WELD-Enabled 001.417 com.test.interceptor.LoggingInterceptor intercettore classe di classe non è né @Interceptor annotato né registrate attraverso un'estensione portatile

mio LoggingInterceptor si presenta così:

@Log 
@Interceptor 
public class LoggingInterceptor { 
    private static final Logger logger = Logger.getLogger(LoggingInterceptor.class.getName()); 

    static { 
     logger.setLevel(Level.ALL); 
    } 

    @AroundInvoke 
    public Object logMethod(InvocationContext ctx) throws Exception { 
     logger.log(Level.FINE, "ENTRY {0} {1}", 
       new Object[]{ ctx.getTarget().getClass().getName(), ctx.getMethod().getName() }); 
     long startTime = System.nanoTime(); 
     try { 
      return ctx.proceed(); 
     } finally { 
      long diffTime = System.nanoTime() - startTime; 
      logger.log(Level.FINE, "RETURN {0} {1}", 
       new Object[]{ ctx.getTarget().getClass().getName(), ctx.getMethod().getName() }); 
      logger.log(Level.FINE, "{0} took {1} ms", new Object[]{ ctx.getMethod(), 
        TimeUnit.MILLISECONDS.convert(diffTime, TimeUnit.NANOSECONDS)}); 
     } 
    } 

} 

E vincolante l'intercettore:

@InterceptorBinding 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD, ElementType.TYPE}) 
public @interface Log {} 

Come posso utilizzare l'intercettore per entrambi i moduli?

+0

Hai trovato la soluzione a questo problema? Sarebbe interessante vederlo. – mik

+1

@milk no, non l'ho fatto. Ho consolidato tutti i moduli in un modulo war, cosa possibile a partire da Java EE 6. – Theo

+0

wow, grazie per averlo esposto così chiaramente. Stavo avendo lo stesso identico problema e il consolidamento di tutto questo in un modulo lo ha risolto. A volte J2EE cerca di rendere le cose difficili su ya ... – JoshC13

risposta

1

Mi chiedo se la tua GUERRA non abbia la visibilità del classloader nel tuo barattolo di ejb? Penso che idealmente i 299 interceptor si troverebbero nel loro jar, visibili sia all'EJB che ai moduli web e abilitati in entrambi i loro bean.xml.

5

È troppo tardi, ma se qualcuno ha ancora questo problema. Entrambi i moduli devono essere caricati dallo stesso classloader per rendere possibile l'utilizzo dell'intercettore tra diversi moduli, almeno in WebSphere 8b2. In WebSphere questa impostazione può essere attivata nella console di amministrazione: Applicazioni> Tipi di applicazioni> Applicazioni enterprise WebSphere> [nome della propria app]> Rilevamento caricamento e aggiornamento classe> Politica caricatore classe WAR = Caricatore classe singola per applicazione.
L'intercettatore deve essere abilitato solo una volta in bean.xml.

+0

Non è mai tardi per la risposta corretta, thx :-) –

+2

Anche se è consentito (e comune) in WebSphere, questo non è raccomandato per l'applicazione JEE. I caricatori di classe sono separati per un motivo. –

0

Ho lo stesso problema su JBoss AS 6.0/6.1 (nightly build) e l'ho risolto con disabling separate classloaders (opzione 1), ma sii estremamente attento con questo. La separazione dei classloader non è stata introdotta per nessun motivo, così apparentemente ci sono nuovi problemi sulla strada da percorrere ...

This è il rapporto jira, si prega di votare fino :-)

8

specifiche J2EE 7 dice (reference):

Gli intercettori specificati nel file beans.xml si applicano solo a classi nello stesso archivio. Utilizzare l'annotazione @Priority secondo intercettori globalmente per un'applicazione che consiste di molteplici moduli

Questa soluzione ha il vantaggio di essere fornitore indipendente.

Un esempio:

@Logged 
@Interceptor 
@Priority(Interceptor.Priority.APPLICATION) 
public class LoggedInterceptor implements Serializable { ... } 
+0

Posso confermare che funziona su WildFly 10.1.0.Final – schnatterer

0

ho avuto esattamente lo stesso problema con il mio logging interceptor su JBoss 7 e fissato dal sovrapponendo vaso del intercettore completa nell'applicazione.

<build> 
    <plugins> 
     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-war-plugin</artifactId> 
      <version>2.4</version> 
      <configuration> 
       <overlays> 
        <overlay> 
         <groupId>com.github.t1</groupId> 
         <artifactId>logging-interceptor</artifactId> 
         <type>jar</type> 
         <targetPath>WEB-INF/classes</targetPath> 
        </overlay> 
       </overlays> 
      </configuration> 
     </plugin> 
    </plugins> 
</build> 

<dependencies> 
    <dependency> 
     <groupId>com.github.t1</groupId> 
     <artifactId>logging-interceptor</artifactId> 
     <version>1.1</version> 
     <optional>true</optional> 
    </dependency> 
</dependencies> 

Avrai ancora attivare l'intercettore nell'applicazione del breans.xml.

Non bello, ma funziona. In Java EE 7, funziona senza l'attivazione annotando l'intercettore come @Priority.

Problemi correlati