5 Replies Latest reply on Sep 16, 2008 3:24 PM by gjeudy

    Some Seam components not injected in JSF Converter

    siderean

      I have a Seam/IceFaces/(IceFaces)Facelets application running on GlassFish.  The application is an enterprise application made of up an ejb app and a web app.  I have 'actions' (POJOs) in my web application which make calls to business components (stateless session beans) in my ejb app.


      One one of my pages I have a selectOneMenu backed by a List of objects.  I wrote a custom converter (yes, I know I can use Seam's entityConverter tag, but that gives me different problems).  The converter has another seam managed component in the web application injected in order to get a list of entities from the database to do the conversion.  The converter also has a Seam @Logger injected.


      I set a breakpoint at the start of the getAsObject() method.  When the method is called Seam has injected the logger but the reference to the seam managed POJO is null.


      The converter is a seam component, as is the POJO I'm trying to inject.  I'm not sure what addition code would help people to understand the problem.  If you have any ideas or need more info, I'd be more than happy to post additional details!


      Thanks for any ideas or help anyone might have!!
      Oh, I'm using:
      Seam 2.0.1.GA
      IceFaces 1.7.0


        • 1. Re: Some Seam components not injected in JSF Converter
          gjeudy

          Can you post the xhtml code, converter code, and the code of the POJO  you are trying to inject?


          Please trim the irrelevant code parts. (I'm specifying because sometimes people just dump the full thing in the post)

          • 2. Re: Some Seam components not injected in JSF Converter
            siderean

            Thanks for your response.


            The page is:




              <ui:composition template="layout/template.xhtml">
            
                <ui:define name="title">#{messages.text_services_title}</ui:define>
                <ui:define name="siteSection">services</ui:define>
            
                <ui:define name="content">
            
                  <ice:outputText value="#{messages.text_newService_banner}"
                      rendered="#{applicationAction.application.applicationPK.applId == null}" />
                  <ice:outputText value="#{messages.text_existingService_banner}"
                      rendered="#{applicationAction.application.applicationPK.applId != null}"/>
            
                  <h:messages globalOnly="true"/>
                  <ice:form id="pageForm">
                    <ice:panelGrid columns="3">
            
                    <ice:outputLabel id="nameLabel" for="name" styleClass="fieldlabel"
                      value="#{messages.form_label_appliaction_name}" />
                    <ice:inputText id="name" value="#{applicationAction.application.name}"
                                 required="true" size="30">
                        <f:validateLength minimum="1" maximum="128" />
                    </ice:inputText>
                    <h:message id="nameMessage" style="color: red;" for="name" />
            
                    <ice:outputLabel id="applInfoLabel" for="applInfo" styleClass="fieldlabel"
                      value="#{messages.form_label_appliaction_applInfo}" />
                    <ice:inputTextarea id="applInfo" value="#{applicationAction.application.applInfo}"
                                 required="false" rows="3" cols="40">
                    </ice:inputTextarea>
                    <h:message id="applInfoMessage" style="color: red;" for="applInfo" />
            
                    <ice:outputLabel id="applIdLabel" for="applId" styleClass="fieldlabel"
                      value="#{messages.form_label_appliaction_applId}" />
                    <ice:inputText id="applId" value="#{applicationAction.application.applicationPK.applId}"
                                 required="true" size="5" />
                    <h:message id="applIdMessage" style="color: red;" for="applId" />
            
                    <ice:outputLabel id="carrierIdLabel" for="carrierId" styleClass="fieldlabel"
                      value="#{messages.form_label_appliaction_carrierId}" />
                    <h:selectOneMenu id="carrierId" value="#{applicationAction.application.applicationPK.carrierId}"
                                 required="true">
                      <f:selectItems id="allCarriers" value="#{applicationAction.carrierItems}"/>
                      <f:validateLongRange minimum="0"/>
                    </h:selectOneMenu>
                    <h:message id="carrierIdMessage" style="color: red;" for="carrierId" />
            
                    <ice:outputLabel id="versionLabel" for="version" styleClass="fieldlabel"
                      value="#{messages.form_label_appliaction_version}" />
                    <ice:inputText id="version" value="#{applicationAction.application.applicationPK.version}"
                                 required="true" size="5">
                        <f:validateLength minimum="1" maximum="5" />
                    </ice:inputText>
                    <h:message id="versionMessage" style="color: red;" for="version" />
            
                    <ice:outputLabel id="carrierIdLabel" for="carrierId" styleClass="fieldlabel"
                      value="#{messages.form_label_appliaction_carrierId}" />
                    <h:selectOneMenu id="carrierId" value="#{applicationAction.application.applicationPK.carrierId}"
                                 required="true">
                      <f:selectItems id="allCarriers" value="#{applicationAction.carrierItems}"/>
                      <f:validateLongRange minimum="0"/>
                    </h:selectOneMenu>
                    <h:message id="carrierIdMessage" style="color: red;" for="carrierId" />
            
                    <ice:outputLabel id="statusLabel" for="status" styleClass="fieldlabel"
                      value="#{messages.form_label_appliaction_status}" />
                    <h:selectOneMenu id="status" value="#{applicationAction.application.status}"
                                 required="true">
                      <f:selectItems id="allAppStates" value="#{applicationAction.applicationStates}"/>
                      <f:validateLongRange minimum="0"/>
                    </h:selectOneMenu>
                    <h:message id="statusMessage" style="color: red;" for="status" />
            
                    <ice:outputLabel id="releaseDateLabel" for="releaseDate" styleClass="fieldlabel"
                      value="#{messages.form_label_appliaction_releaseDate}" />
                    <ice:selectInputDate id="releaseDate"
                      popupDateFormat="yyyy-MM-dd" required="true"
                      value="#{applicationAction.application.releaseDate}" renderAsPopup="true">
                      <f:convertDateTime pattern="yyyy-MM-dd" />
                    </ice:selectInputDate>
                    <h:message id="releaseDateMessage" style="color: red;" for="releaseDate" />
            
                    <ice:outputLabel id="buildLabel" for="build" styleClass="fieldlabel"
                      value="#{messages.form_label_appliaction_build}" />
                    <ice:inputText id="build" value="#{applicationAction.application.build}"
                                 required="true" size="5" />
                    <h:message id="buildMessage" style="color: red;" for="build" />
            
                      <h:commandButton id="submitcreate" type="submit" value="#{messages.button_create}"
                        action="#{applicationAction.createApplication}" 
                        rendered="#{applicationAction.application.applicationPK.applId == null}"/>
            
                      <h:commandButton id="submitupdate" type="submit" value="#{messages.button_update}"
                        action="#{applicationAction.updateApplication}" 
                        rendered="#{applicationAction.application.applicationPK.applId != null}"/>
            
                    </ice:panelGrid>
                  </ice:form>
            
                </ui:define>
            
              </ui:composition>
            


            The Converter code is:


            @Name("appStatusConverter")
            public class ApplicationStateConverter implements Converter {
            
              @Logger private static Log logger;
              @In(create=true)
              private ApplicationServiceLocal applicationServiceProxy;
              
              public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
                if (arg2 == null)
                  return null;
                List<ApplicationState> states = applicationServiceProxy.findApplicationStates();
                for (ApplicationState state : states) {
                  if (arg2.equals(state.getStateId().toString()))
                    return state;
                }
                logger.warn("Name '" + arg2 + "' was not found in any state.");
                return null;
              } // end getAsObject()
              
              public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
                ...
              } // end getAsString()
            
            } // end ApplicationStateConverter Class
            



            And finally, I'm creating the injected POJO using a factory because it's actually a proxy to the EJB (a proxy that can be wrapped in a proxy, mostly to make auditing easier and custom remoting)...



            @Name("proxyFactory")
            @Scope(ScopeType.APPLICATION)
            public class ProxyFactory {
            
              @In(create=true)
              private ApplicationServiceLocal applicationService;
            
              @Factory(value = "applicationServiceProxy", scope=ScopeType.SESSION)
              public ApplicationServiceLocal getApplicationService() {
                log.debug("creating application serivce proxy");
                return (ApplicationServiceLocal)wrapService(
                        ApplicationServiceLocal.class, applicationService);
              }
              
              private Object wrapService(Class intf, Object object) {
                      Class<?>[] interfaces = new Class<?>[1];
                      interfaces[0] = intf;
                return Proxy.newProxyInstance(object.getClass().getClassLoader(), 
                                interfaces, 
                    new LoggingProxy(new DeferringProxy(interfaces, object)));
              }
            } // end ProxyFactory Class
            



            Thanks for any ideas or insights you might have into this problem.
            //Don


            • 3. Re: Some Seam components not injected in JSF Converter
              siderean

              I should mention that the applicationServiceProxy get injected into 'action' POJOs without any problems.  The same component does not get injected into the converter, though.


              • 4. Re: Some Seam components not injected in JSF Converter
                wilczarz.wilczarz.gmail.com

                Hi Don, have you tried this?



                import org.jboss.seam.annotations.faces.Converter;
                ...
                @Name("appStatusConverter")
                @Converter
                @BypassInterceptors
                public class ApplicationStateConverter implements javax.faces.convert.Converter {
                
                private static Log logger = Logging.getLog( ApplicationStateConverter.class );
                private ApplicationServiceLocal applicationServiceProxy = (ApplicationServiceLocal) Component.getInstance( "applicationServiceProxy" ) ;




                and



                <h:selectOneMenu id="status" value="#{applicationAction.application.status}" required="true" converter="appStatusConverter" >








                • 5. Re: Some Seam components not injected in JSF Converter
                  gjeudy

                  Tomasz suggestion should work, aside from this you probably want to check how Seam implements it's own JSF converters. You need Converter annotation at the very least. I'm not sure why you have to annotate with BypassInterceptors. I would try with or without BypassInterceptors and see how it goes. Not having interceptors implies you won't be able to use bijection. Worst case use Component.getInstance() lookup and it should work.


                  Seam entityConverter declaration example :


                  @Name("org.jboss.seam.ui.EntityConverter")
                  @Scope(CONVERSATION)
                  @Install(precedence = BUILT_IN)
                  @Converter
                  @BypassInterceptors
                  public class EntityConverter implements
                           javax.faces.convert.Converter, Serializable



                  As Tomasz pointed out you need to reference your converter by name in your xhtml page if you want to use it.


                  Let us know how it goes.