2013-08-27 11 views
16

Vorrei creare una classe i cui oggetti possono essere iniettati usando l'annotazione @Context (o meglio ancora un'annotazione personalizzata per i casi in cui ho bisogno di passare un argomento all'annotazione) in metodi di risorse. In Jersey 1. * Avrei usato InjectableProvider (nel mio caso insieme a AbstractHttpContextInjectable). Quello che sto cercando di ottenere è qualcosa come @Auth [1] da dropwizard (che utilizza Jersey 1.7).Jersey 2. *. Come sostituire InjectableProvider e AbstractHttpContextInjectable di Jersey 1. *

Le capacità di iniezione di Jersey sono state sostituite da HK2 per quanto ne so e non sono riuscito a trovare alcun esempio di ciò che sto descrivendo.

Modifica: Vedere this question per ulteriori problemi che ho riscontrato durante il tentativo di seguire la guida di Michal.

risposta

20

È necessario implementare l'interfaccia InjectionResolver<T> da HK2. Date un'occhiata a implementazioni esistenti che sono presenti in Jersey di lavoro:

Una volta ottenuto questo, è necessario estendere AbstractBinder da HK2 e associare il numero InjectionResolver tramite il numero #configure() metodo:

public class MyResolverBinder extends AbstractBinder { 

    @Override 
    protected void configure() { 
     bind(MyInjectionResolver.class) 
       .to(new TypeLiteral<InjectionResolver<MyAnnotation>>() {}) 
       .in(Singleton.class); 
    } 
} 

... e registrare un'istanza di questo legante nella vostra classe di applicazione (o tramite feature):

Feature:

public class MyFeature implements Feature { 

    @Override 
    public boolean configure(final FeatureContext context) { 
     context.register(new MyResolverBinder()); 
     return true; 
    } 
} 

registro MyFeature in Application:

public class JaxRsApplication extends Application { 

    @Override 
    public Set<Class<?>> getClasses() { 
     final HashSet<Class<?>> classes = new HashSet<Class<?>>(); 
     classes.add(MyFeature.class); 
     // Register other providers or resources. 
     return classes; 
    } 
} 

registro MyResolverBinder o Feature nel ResourceConfig

new ResourceConfig() 
     // Register either MyFeature 
     .register(MyFeature.class) 
     // or MyResolverBinder 
     .register(new MyResolverBinder()) 
     // Register other providers or resources 
     .packages("my.package"); 
+0

Grazie! Questo sembra essere esattamente ciò di cui ho bisogno. – TheCuriousOne

+0

Michal, ho provato a seguire la tua guida, ma ho riscontrato un avvertimento strano "... Un metodo HTTP GET ... non dovrebbe consumare alcuna entità.". Non sono sicuro di cosa farne (vedi modifica della mia domanda per maggiori dettagli).Avete qualche idea su cosa potrebbe causarlo? Grazie. – TheCuriousOne

+0

Grazie per la risposta. Tuttavia, non è chiaro per me come creare un oggetto, ad esempio, il 'ContainerRequestContext' e come smaltire correttamente l'oggetto iniettato, ad es. Chiamando' close() '. Non riesco a trovare alcun esempio online, hai suggerimenti? –

3

Fornendo un'implementazione di InjectionResolver aiuta solo con iniezione, non quando la risoluzione dei valori per i parametri di un metodo di risorsa.

Almeno con Jersey 2.11, è necessario definire un ValueFactoryProvider annotato con @Provider.

@Provider 
public class MyValueFactoryProvider implements ValueFactoryProvider { 

    @Inject 
    private MyFactory factory; 

    @Override 
    public Factory<?> getValueFactory(Parameter parameter) { 
     if (parameter.getAnnotation(MyAnnotationParam.class) != null) { 
      return factory; 
     } 

     return null; 
    } 

    @Override 
    public PriorityType getPriority() { 
     return Priority.NORMAL; 
    } 

} 

Se anche voi volete ottenere il valore iniettato in, per esempio, i membri ei parametri del costruttore, quindi InjectionResolver funziona bene.