Uploaded image for project: 'Seam Faces'
  1. Seam Faces
  2. SEAMFACES-165

@Inject for Validators doesn't work with MyFaces

    Details

    • Affects:
      Compatibility/Configuration

      Description

      @Inject doesn't work for validators when using MyFaces. The fields are always null.

      If I run the application with Mojarra instead of MyFaces everything works fine.

      I'm note completely sure if it is a Seam Faces or a MyFaces issue.

        Gliffy Diagrams

          Issue Links

            Activity

            Hide
            chkal Christian Kaltepoth added a comment -

            I did some more research on this. Actually this seems to be a bug in Weld 1.1.0 and not in Seam Faces. Let me explain:

            SeamApplicationWrapper waits for the PostConstructApplicationEvent and then obtains the ApplicationFactory from the FactoryFinder. Then it calls ApplicationFactory.setApplication() to install the Seam Faces wrapper.

            With MyFaces the SeamApplicationWrapper gets the WeldApplicationFactory from the FactoryFinder. Unfortunately SeamApplicationWrapper ignores calls to setApplication() and simply delegates them to the underlying ApplicationFactory. The problem here is that SeamApplicationWrapper already holds a reference to the Application instance that it returns for getApplication() and doesn't update this reference when setApplication() is called. Therefore SeamApplicationWrapper will return the old Application instance on future calls to getApplication().

            See the code of WeldApplicationFactory:

            https://github.com/weld/core/blob/master/environments/servlet/core/src/main/java/org/jboss/weld/environment/servlet/jsf/WeldApplicationFactory.java

            For Mojarra the situation is a bit different. When using Mojarra Seam Faces calls setApplication() on Mohjarra's InjectionApplicationFactory, which wraps SeamApplicationWrapper. As InjectionApplicationFactory implements setApplication() correctly, the bug doesn't occur on Mojarra.

            Does this sound reasonable? If you agree to my explanation I could open a ticket for Weld regarding this.

            Show
            chkal Christian Kaltepoth added a comment - I did some more research on this. Actually this seems to be a bug in Weld 1.1.0 and not in Seam Faces. Let me explain: SeamApplicationWrapper waits for the PostConstructApplicationEvent and then obtains the ApplicationFactory from the FactoryFinder . Then it calls ApplicationFactory.setApplication() to install the Seam Faces wrapper. With MyFaces the SeamApplicationWrapper gets the WeldApplicationFactory from the FactoryFinder . Unfortunately SeamApplicationWrapper ignores calls to setApplication() and simply delegates them to the underlying ApplicationFactory . The problem here is that SeamApplicationWrapper already holds a reference to the Application instance that it returns for getApplication() and doesn't update this reference when setApplication() is called. Therefore SeamApplicationWrapper will return the old Application instance on future calls to getApplication() . See the code of WeldApplicationFactory : https://github.com/weld/core/blob/master/environments/servlet/core/src/main/java/org/jboss/weld/environment/servlet/jsf/WeldApplicationFactory.java For Mojarra the situation is a bit different. When using Mojarra Seam Faces calls setApplication() on Mohjarra's InjectionApplicationFactory , which wraps SeamApplicationWrapper . As InjectionApplicationFactory implements setApplication() correctly, the bug doesn't occur on Mojarra. Does this sound reasonable? If you agree to my explanation I could open a ticket for Weld regarding this.
            Hide
            pmuir Pete Muir added a comment -

            Raise an issue in Weld

            Show
            pmuir Pete Muir added a comment - Raise an issue in Weld
            Hide
            chkal Christian Kaltepoth added a comment -

            I just created WELD-913 for this!

            Show
            chkal Christian Kaltepoth added a comment - I just created WELD-913 for this!
            Hide
            chkal Christian Kaltepoth added a comment -

            Just a small update for everyone who gets hit by this. I'm currently using another ApplicationFactory wrapper as a workaround for this bug:

            public class WeldBugfixApplicationFactory extends ApplicationFactory {
             
              private final ApplicationFactory delegate;
             
              private Application application;
              
              public WeldBugfixApplicationFactory(ApplicationFactory delegate) {
                this.delegate = delegate;
              }
              
              @Override
              public Application getApplication() {
                if(application == null) {
                  application = delegate.getApplication();
                }
                return application;
              }
             
              @Override
              public void setApplication(Application application) {
                this.application = application;
                delegate.setApplication(application);
              }
             
            }
            

            This factory has to be added to your faces-config.xml like this:

            <?xml version="1.0" encoding="UTF-8"?>
            <faces-config ....>
             
              <factory>
                <application-factory>com.example.WeldBugfixApplicationFactory</application-factory>
              </factory>  
             
            </faces-config>
            

            This works fine for me. Not a very nice workaround but now the injection also works with MyFaces.

            Show
            chkal Christian Kaltepoth added a comment - Just a small update for everyone who gets hit by this. I'm currently using another ApplicationFactory wrapper as a workaround for this bug: public class WeldBugfixApplicationFactory extends ApplicationFactory {   private final ApplicationFactory delegate;   private Application application; public WeldBugfixApplicationFactory(ApplicationFactory delegate) { this.delegate = delegate; } @Override public Application getApplication() { if(application == null) { application = delegate.getApplication(); } return application; }   @Override public void setApplication(Application application) { this.application = application; delegate.setApplication(application); }   } This factory has to be added to your faces-config.xml like this: <?xml version="1.0" encoding="UTF-8"?> <faces-config ....>   <factory> <application-factory>com.example.WeldBugfixApplicationFactory</application-factory> </factory>   </faces-config> This works fine for me. Not a very nice workaround but now the injection also works with MyFaces.
            Hide
            bleathem Brian Leathem added a comment -

            Christian is this workaround compatible with Mojarra? It would be nice to include this in Faces.

            Show
            bleathem Brian Leathem added a comment - Christian is this workaround compatible with Mojarra? It would be nice to include this in Faces.
            Hide
            chkal Christian Kaltepoth added a comment -

            I think it should work fine with Mojarra. I see no reason why it shouldn't. The only important thing is that this factory must decorate WeldApplicationFactory and not the other way around.

            However I'm not sure if it is a good idea to include such a workaround in Seam Faces. Wouldn't it be nicer to simply add a SeamFacesApplicationFactory that creates wrapped Application instances in its getApplication() method? Just like SeamExternalContextFactory and CatchExceptionHandlerFactory do it? This way there would be no need to call setApplication() and so we won't be affected by the Weld bug any more.

            I'll build a prototype for this at the weekend. I think it will work fine this way.

            Show
            chkal Christian Kaltepoth added a comment - I think it should work fine with Mojarra. I see no reason why it shouldn't. The only important thing is that this factory must decorate WeldApplicationFactory and not the other way around. However I'm not sure if it is a good idea to include such a workaround in Seam Faces. Wouldn't it be nicer to simply add a SeamFacesApplicationFactory that creates wrapped Application instances in its getApplication() method? Just like SeamExternalContextFactory and CatchExceptionHandlerFactory do it? This way there would be no need to call setApplication() and so we won't be affected by the Weld bug any more. I'll build a prototype for this at the weekend. I think it will work fine this way.
            Hide
            chkal Christian Kaltepoth added a comment -

            This pull request shows one way to fix this issue. Instead of getting the current ApplicationFactory and setting the SeamApplicationWrapper via setApplication() this patch registers a custom ApplicationFactory that handles the creation of the Application wrapper. This way we won't be affected by WELD-913 any more.

            https://github.com/seam/faces/pull/39

            I think this is the most elegant solution for this issue.

            Show
            chkal Christian Kaltepoth added a comment - This pull request shows one way to fix this issue. Instead of getting the current ApplicationFactory and setting the SeamApplicationWrapper via setApplication() this patch registers a custom ApplicationFactory that handles the creation of the Application wrapper. This way we won't be affected by WELD-913 any more. https://github.com/seam/faces/pull/39 I think this is the most elegant solution for this issue.
            Hide
            lightguard Jason Porter added a comment -

            Code was push to the repo back in June

            Show
            lightguard Jason Porter added a comment - Code was push to the repo back in June

              People

              • Assignee:
                Unassigned
                Reporter:
                chkal Christian Kaltepoth
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Development