kostja
kostja

Reputation: 61538

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.

Upvotes: 12

Views: 10736

Answers (2)

Tom Anderson
Tom Anderson

Reputation: 47163

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.

Upvotes: 17

Jan Groth
Jan Groth

Reputation: 14636

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?

Upvotes: 2

Related Questions