2012-06-21 13 views
7

La especificación JSR-299 en §3.1:genéricos restringidos con CDI

Si la clase bean gestionado es un tipo genérico, que deben tener un alcance @Dependent. Si un bean gestionado con una clase bean parametrizada declara cualquier ámbito que no sea @Dependent, el contenedor detectará automáticamente el problema y lo tratará como un error de definición.

Efectivamente lo que significa que no se puede hacer esto:

@Named 
@SessionScoped or @RequestScoped or similar 
public class MyProducer<T> {...} 

¿Cuáles son las razones técnicas de esta decisión?

¿Será remediado en una próxima versión de CDI por casualidad?

¿Existe alguna práctica recomendada para solucionar este problema?

Gracias

EDITAR - una solución alternativa que puede utilizar a menudo es inyectar un POJO-frijol genérica en un frijol con el alcance necesario. A menudo, pero no siempre

+0

Una gran pregunta, por cierto.No sabía acerca de esta restricción, y realmente te hace pensar. –

Respuesta

13

Esto es un no-dependiente de la clase genérica, frijol:

@ApplicationScoped 
public class FavouriteChooser<T> { 
    public T getFavourite() { 
     // ... 
    } 
} 

¿Cuántos casos de este frijol habrá en la aplicación?

Aquí es un lugar de inyección:

@Inject 
private FavouriteChooser<String> favouriteWord; 

Y aquí es otra:

@Inject 
private FavouriteChooser<Integer> favouriteNumber; 

¿Le gustaría cambiar su respuesta? : D

Oh, y aquí es otra:

@Inject 
private FavouriteChooser<CharSequence> favouriteLetters; 

EDITAR. Si quieres una solución, te sugiero que hagas un resumen genérico de clase y añadas subclases concretas que vinculen el tipo. Entonces:

public abstract class MyProducer<T> {...} 

@Named 
@SessionScoped 
public class MyStringProducer extends MyProducer<String> {} 

@Named 
@SessionScoped 
public class MyIntegerProducer extends MyProducer<Integer> {} 

Es un texto estándar, pero solo tres líneas por tipo. Tenga en cuenta que le daría una instancia por sesión por tipo, que es posible que no desee.

+0

Bueno, siempre y cuando no se nombre el frijol, ¿se puede inyectar? Si se preserva el alcance (¿es así? - ¿cada uno de ellos se inyecta en el ámbito de la aplicación FavouriteChooser?), ¿La única restricción sería que no puedo acceder a ellos con las explotaciones EL? Y no está en contradicción con la especificación? Se supone que es un frijol administrado después de todo. – kostja

+3

No, mi punto es que este código no puede funcionar. He declarado el alcance de la aplicación 'FavouriteChooser', lo que significa que solo puede haber una instancia. Pero hay dos sitios de inyección que * no pueden ser satisfechos por el mismo objeto *. Y eso, creo, es la razón por la que no puede inyectar instancias de clases genéricas en ningún ámbito que no sea dependiente. –

+0

Perdón por no haber sido más claro sobre lo que estaba tratando de decir cuando escribí esta respuesta. Simplemente me apresuré sin tener tiempo para explicarme correctamente: /. –

2

Todos los beans de ámbito no dependiente tienen que ser proxies - AFAIK esto no es posible con tipos genéricos.

ACTUALIZACIÓN:

Me encantaría ser capaz de explicar que con más detalle, pero no estoy ;-) Weld utiliza javassist, y afirman que proxying generic types is possible in principle - aunque no apoyado directamente por el API de nivel superior . Pero estamos hablando de la especificación, no de la implementación de Weld ...

¿Quizás alguien más pueda llenar el vacío?

+0

Gracias, jan. Ya arroja algo de luz sobre el asunto - sería genial si también pudieras explicar por qué los tipos genéricos no pueden ser procesados ​​(supongo que tiene que ver con el principal james némesis - tipo de borrado, pero no puedo poner mi dedo en ello). – kostja