简体   繁体   中英

Inject within Guice to ManagedBean JSF

i have a problem injecting within a Guice ( @Inject ) a repository class to a @ManagedBean class (JSF), which is using EntityManager to get info from db. I've read a lot of old articles with strange ways to do it, but nothing worked. Here is the code:

public class InitConfigListener extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServletModule() {

            @Override
            protected void configureServlets() {
                install(new JpaPersistModule("db-manager"));

                filter("/*").through(PersistFilter.class);
            }
        }, new RepositoryModule());
    }

}
public class RepositoryModule extends AbstractModule {

    public void configure() {
        bind(IBookRepository.class).to(BookRepository.class).asEagerSingleton();
        bind(IUserRepository.class).to(UserRepository.class).asEagerSingleton();
    }

}

@ManagedBean
@ViewScoped
public class BooksView {

    private List<Book> bookList;
    private IBookRepository booksRepository;

    public BooksView() { }

    @Inject
    public BooksView(IBookRepository booksRepository) {
        this.booksRepository = booksRepository;
    }

    @PostConstruct
    public void initBookList() {
        bookList = booksRepository.getAll();
    }

    public List<Book> getBookList() {
        return bookList;
    }

    public void setBookList(List<Book> bookList) {
        this.bookList = bookList;
    }

}

EntityManager was injected in repositories. After bindings of repositories, @Inject in class BooksView didn't executed, @PostConstruct was and repository injected was null.

Thanks for help.

Guice works a little bit differently to CDI as BalusC mentioned.

What is happening is that the CDI is executing properly and calling the post constructs on the methods. JSF Classes are also not Guice managed but CDI Managed so you need to call guice from your front end (which is correct) unless you are using servlet based web fronts, where you use guice-servlet can get around this. Method annotations also require aopalliance .

You can initialize Guice through a filter (example : https://github.com/GedMarc/JWebSwing-Undertow/blob/master/src/main/java/za/co/mmagon/jwebswing/undertow/UndertowJWebSwingHandlerExtension.java ) for undertow based containers, or as a ServletContextListener as mentioned here ( https://github.com/google/guice/wiki/ServletModule ) if you would like to startup before a @PostConstruct in a JSF view.

An interesting thing as well, is in an EE environment, the @PostConstruct timing is different in @Singleton's. In standalone environments you can place the injection builder in this location to load injections for ejb and servlets (from a module in the war)

You can use Guice as long as you configure JSF Appropriately.

In a nutshell, to do this you need to enable two things - Set a custom application factory - Configure EL to get the bindings from Guice

Set the application factory via the faces-config.xml file

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd">
    <factory>
        <application-factory>com.jwebmp.guicedservlets.jsf.FacesApplicationFactoryWrapper</application-factory>
    </factory>

</faces-config>

A servlet context parameter (web.xml) or for undertow/embeddeds a deployment info

com.sun.faces.facesInitializerMappingsAdded=true

deploymentInfo.addServletContextAttribute(RIConstants.FACES_INITIALIZER_MAPPINGS_ADDED, Boolean.TRUE)
                 .addListener(new ListenerInfo(com.sun.faces.config.ConfigureListener.class));

Then in your module - Use your choice mechanism of scanning, and bind all @javax.inject.Named and @ManagedBean to keys you are going to use in the Guice EL Resolver replacing the CDI/CustomInject/any form on injection that JSF uses with Guice.

Module Binder Example Here

Guice EL Resolver Example Here

Faces Application Wrapper

Optional View Scope Impl


Below is a bundled implementation which you can simply attach, using the Guiced EE framework for JDK 11 and up in modular JPMS (backwards compatible to 1.8)

Note * because of the invalid ServiceProviders in the javax.faces library, the framework references a local javax.faces which at time of updating this was at 2.3.9 with the providers removed to enable you building your JRE with JLink or simply executing your application in JPMS

https://github.com/GedMarc/Guiced-Servlets-JSF

https://search.maven.org/artifact/com.jwebmp.guicedee.servlets/guiced-servlets-jsf/0.68.0.1/jar
<dependency>
  <groupId>com.jwebmp.guicedee.servlets</groupId>
  <artifactId>guiced-servlets-jsf</artifactId>
  <version>0.68.0.1</version>
</dependency>

Then you can just use @ManagedBean and/or @Named (JSF2.3) appropriately with all injections in pretty much any environment, except Servlet 4 which guice-servlet does not yet support

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM