4

I'm using JSF and am running in a problem for quite awhile, I've searched at a lot of places but couldn't find any suitable answer.

Can I have dependency injection working in an abstract (or more generally a class higher in the hierarchy) class ? Also, how should we handle annotations when working with inheritance ? I've read that the common practice would be not to annotate the abstract class, only the concrete one, but then, it would imply no injection for that abstract ?

My problem is that one (check the last comment) :

Abstract class

@ManagedBean
@ViewScoped
public abstract class AbstractController<T extends VersionedObject> implements Serializable {
    @ManagedProperty("#{libraryVersionController}")
    private LibraryVersionController libraryVersionController;

public List<T> loadFromDatasource(IVersionedServiceBase<T> service) {
        log.info("Loading generic VO from data source");

        VersionedObjectFilter filter = new VersionedObjectFilter();
        filter.setSelectedLibVersion(libraryVersionController.getSelectedItem());
        // etc
    }
    // getters, setters...
}

Concrete class

@ManagedBean
@ViewScoped
public class DomainController extends AbstractController<Domain> implements Serializable {
private List<Domain> allItems;
   private Domain[] selectedItem;

   @ManagedProperty(value = "#{domainService}")
   private DomainService domainService;

   @PostConstruct
   public void loadFromDatasource() {
    allItems = super.loadFromDatasource(domainService);
        // !! DOES NOT WORK, null pointer exception on abstract class (libraryVersionController)
   // etc
}

Getters and setters are correctly set up, as I could read in my .xhml it is the concrete class that I'm referencing (#{domainController.allItems}), there is only one @PostConstruct. I'm using JSF2.1 and Mojarra.

Thanks for your help !

Qualaelay
  • 713
  • 2
  • 10
  • 21
  • JSF DI does not reckon with abstract implementations. See [this answer](http://stackoverflow.com/a/6662875/1530938) – kolossus Jan 21 '13 at 03:56
  • @kolossus That's a pity, it seems like a big gap. And is there a way to do it with a concrete super-class instead of an abstract one ? – Qualaelay Jan 21 '13 at 09:40
  • @kolossus: that question/answer concerns a different problem. The OP of that question is merely asking if it's possible to omit `@ManagedBean` and `@XxxScope` from the concrete class and use the ones declared on the abstract class. That is indeed not possible. But the current question isn't about that at all (although the `@ManagedBean @ViewScoped` on the `AbstractController` are completely superflous as they would be ignored anyway). – BalusC Jan 21 '13 at 11:38
  • Qualaelay: what Mojarra version? This works just fine for me on 2.1.17. Note that it's somewhat strange to use JSF managed beans as service classes. One would have used EJBs for this. Before posting an answer, I'd like to see how you declared `LibraryVersionController` as managed bean. Your problem indicates that it's not a managed bean at all and thus not found in EL scope. – BalusC Jan 21 '13 at 11:51
  • Sorry for the delay in responding, personal things to fix up :/ Anyway @BalusC your hint was good as `LibraryVersionController` had a problem (it was `@Component` and `@ManagedBean`), it worked fine when I removed the `@Component` (so both my Class and Superclass are annotated as managed beans now, injection works correctly in each). The reason why it's ManagedBean as service is that the services class are Spring+JPA, so I assumed it was the way to go, but please do not hesitate to comment if this is not a good approach. – Qualaelay Feb 03 '13 at 19:51

1 Answers1

0

As to your NullPointerException, my guess is that AbstractController.setLibraryVersionController is missing. As I understand it, when the AbstractController is constructed (presumably it has an implicit constructor even though it's abstract), that method is needed to fill in the appropriate value.

I know you said all getters and setters are there, but this one seems tricky, so possibly you missed it. If you add logging to this method, you can check that JSF is attempting to fill in the value, and also check whether the value is null or not.

On the general question of how dependency injection works with the inheritance hierarchy, I would guess that your approach is OK, and that dependencies are injected for the base class and then for the derived class, down the chain.

Hew Wolff
  • 1,489
  • 8
  • 17