Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restricted generics with CDI

The JSR-299 specification states in §3.1:

If the managed bean class is a generic type, it must have scope @Dependent. If a managed bean with a parameterized bean class declares any scope other than @Dependent, the container automatically detects the problem and treats it as a definition error.

Effectively meaning that you can't do this:

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

What are the technical reasons for this decision?

Will it be remedied in an upcoming version of CDI by any chance?

Is there a best practice for dealing with /working around this?

Thank you

EDIT - a workaround I can often use is to inject a generic POJO-bean into a bean with the needed scope. Often, but not always.

like image 668
kostja Avatar asked Jun 21 '12 12:06

kostja


2 Answers

Here's a generic, non-dependent bean class:

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

How many instances of this bean will there be in the application?

Here is an injection site:

@Inject
private FavouriteChooser<String> favouriteWord;

And here's another:

@Inject
private FavouriteChooser<Integer> favouriteNumber;

Would you like to change your answer? :D

Ooh, and here's another:

@Inject
private FavouriteChooser<CharSequence> favouriteLetters;

EDIT. If you want a solution, i would suggest making your generic class abstract, and adding concrete subclasses which bind the type. So:

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

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

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

It's boilerplate, but it's only three lines per type. Bear in mind that would give you one instance per session per type, which you might not want.

like image 86
Tom Anderson Avatar answered Nov 15 '22 18:11

Tom Anderson


All non-dependent scoped beans have to be proxied - AFAIK this is not possible with generic types.

UPDATE:

I'd love to be able to explain that in more detail, but I'm not ;-) Weld uses javassist, and they state that proxying generic types is possible in principle - though not directly supported by the toplevel API. But we are talking about the specification, not the implementation of Weld...

Maybe someone else can fill the gap?

like image 29
Jan Groth Avatar answered Nov 15 '22 17:11

Jan Groth