4 Replies Latest reply on Feb 10, 2012 12:38 AM by zeeman

    How to execute an action when the custom composite component

    hantsy

      I created a custome composite component in my applciation, and want to do some initialization in the component when the component was initialzed.

       

      I created  @FacesComponents, but it can not inject other CDI Bean.

       

       

      @FacesComponent(UIInputPriceContainer.COMPONENT_TYPE)
      public class UIInputPriceContainer extends UIComponentBase implements
              NamingContainer {
          /**
           * The standard component type for this component.
           */
          public static final String COMPONENT_TYPE = "com.telopsys.siorc.faces.InputPriceContainer";
      
          private static final Logger log = org.slf4j.LoggerFactory
                  .getLogger(UIInputPriceContainer.class);
          
          @Inject
          @Named("baseCurrency")
          Currency baseCurrency;
          
          @Override
          public String getFamily() {
              return UINamingContainer.COMPONENT_FAMILY;
          }
      
          @Override
          public void encodeBegin(FacesContext context) throws IOException {
              if (log.isDebugEnabled()) {
                  log.debug("call encodeBegin...");
              }
              PriceInstance _priceInstance = (PriceInstance) this.getValueExpression(
                      "price").getValue(context.getELContext());
              
              if(log.isDebugEnabled()){
                  log.debug("price attribute@"+_priceInstance);
              }
              
              if(_priceInstance !=null && _priceInstance.getId()==null){
      
                  _priceInstance.setCurrency(baseCurrency);
                  _priceInstance.setFixing(baseCurrency.getCurrentRate().getFixing());
              }
      
              if(log.isDebugEnabled()){
                  log.debug("price instance initiliztion@"+_priceInstance);
              }
          
              getAttributes().put("price", _priceInstance);
      
              super.encodeBegin(context);
      
          }
      
      }
      

       

      I got a NPE because the baseCurrency can not be inject.

       

      I noticed there are some other solutions in the internet, such as the JSF event, but I have not tried it now.

       

      Is there a solution for this purpose(assume you must get data from other CDI bean or database, not simply from the JSF UIComponent)? Thanks.

        • 1. Re: How to execute an action when the custom composite component
          lightguard

          This would be one of those holes in JSF 2 and CDI integration which will be fixed in JSF 2.2. You could lookup the BeanManager via JNDI and query that way.

          • 2. Re: How to execute an action when the custom composite component
            hantsy

            Is there another solution for this purpose...?

             

            I can not find a example about writing a Custom Component for the composite component, and provide custom action/method/event for the custome Component and how to interact with the children of the custom Component...

             

            Any help here?

            • 3. Re: How to execute an action when the custom composite component
              bleathem
                  @Inject
                  @Named("baseCurrency")
                  Currency baseCurrency;
              

               

              FYI: Even if you could @Inject into a component, this is a wrong use of @Named.  @Inject is resolved by type, not by name.

               

              As Jason said, you cannot currently use CDI injection in a JSF component.  You'll have to ask the BeanManager for it, which is pretty simple to do. 

               

              Backstory: Seam Faces stores a reference to the BeanManager in the Faces ServletContext, and provides access to the BeanManager using the BeanManagerProvider interface. 

               

              Solution: This can be leveraged in your FacesComponent by using the Solder BeanManagerLocator#getBeanManager method.  Once you have a reference to the BeanManager, use one of the BeanManager#getBeans methods to look for the bean you were trying to inject.

               

              However, that being said, typically one feeds data into a component with a value binding.  You would bind "baseCurrency" to an attribute of your object, and look it up using the UIComponent#getAttribute method.

              • 4. Re: How to execute an action when the custom composite component
                zeeman

                I tried doing some custom components and they're a hack in JSF2. There are many issues with them.

                 

                I saved myself a lot of pain by staying away from custom components. The best componetization you'll get with JSF2 is passing params to pages and include those pages where you need them.