Announcement Announcement Module
Collapse
No announcement yet.
custom converter Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • custom converter

    I've created a custom Converter to map a request-parameter to a custom domain object, and I've subclassed the DefaultConversionService to include this Converter, but the request-parameter isn't mapped to my model.

    here is some of the code.

    public class LocaleConverter implements Converter{
    public Object convert(Object obj, Class targetClass, Object context)
    throws Exception {
    System.out.println("obj " + obj);
    if (StringUtils.hasText((String) obj)) {
    return new Locale((String) obj);
    }
    return null;
    }

    public Class[] getSourceClasses() {
    return new Class[] {String.class};
    }

    public Class[] getTargetClasses() {
    return new Class[] {Locale.class};
    }
    }

    public class ConversionServiceImpl extends DefaultConversionService implements InitializingBean {
    private Set converters;

    public void setConverters(Set converters) {
    this.converters = converters;
    }

    public void afterPropertiesSet() throws Exception {
    if (converters == null) {
    throw new NullPointerException("Converters must be set");
    }

    for (Iterator iterator = converters.iterator(); iterator.hasNext() {
    Converter converter = (Converter) iterator.next();
    this.addConverter(converter);
    }
    }
    }

    public class ConversionServiceImpl extends DefaultConversionService implements InitializingBean {
    private Set converters;

    public void setConverters(Set converters) {
    this.converters = converters;
    }

    public void afterPropertiesSet() throws Exception {
    if (converters == null) {
    throw new NullPointerException("Converters must be set");
    }

    for (Iterator iterator = converters.iterator(); iterator.hasNext() {
    Converter converter = (Converter) iterator.next();
    this.addConverter(converter);
    }
    }


    <bean id="flowController" class="org.springframework.webflow.mvc.servlet.Flo wController">
    <property name="flowExecutor" ref="flowExecutor" />
    </bean>

    <!-- Executes flows: the central entry point into the Spring Web Flow system -->
    <webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry" >
    <webflow:flow-execution-repository max-executions="5" max-execution-snapshots="0" />
    </webflow:flow-executor>

    <!-- The registry of executable flow definitions -->
    <webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
    <webflow:flow-location id="request" path="/WEB-INF/flows/request.xml" />
    </webflow:flow-registry>

    <webflow:flow-builder-services
    id="flowBuilderServices"
    conversion-service="conversionService"
    view-factory-creator="mvcViewFactoryCreator"/>

    <bean id="conversionService" class="imi.controller.requests.ConversionServiceIm pl">
    <property name="converters">
    <set>
    <bean class="imi.controller.requests.LocaleConverter" />
    </set>
    </property>
    </bean>


    What am i doing wrong ?

  • #2
    Have you tried using a custom formatter? From what I know the binding is done using the formatters that converts from text to object and from object to text. They are used also for rendering.

    Comment


    • #3
      Using the formatters solves my problem. But what are the converter used for then?

      Thx

      Comment


      • #4
        Originally posted by visioner View Post
        Using the formatters solves my problem. But what are the converter used for then?

        Thx
        converters used to convert the <evaluate/> expression result to some other type
        joe

        Comment


        • #5
          Originally posted by visioner View Post
          Using the formatters solves my problem. But what are the converter used for then?

          Thx
          How do you got your Formatters to work? I'm having the problem, that my Custom Formatter don't get used.
          thx!

          Comment


          • #6
            You might want to look at the latest nightly build, as there have been some changes in the area of type conversion for 2.0.3 due to user feedback. Most notably, the Formatter system and Converter systems have been unified.

            Keith

            Comment


            • #7
              Originally posted by Keith Donald View Post
              You might want to look at the latest nightly build, as there have been some changes in the area of type conversion for 2.0.3 due to user feedback. Most notably, the Formatter system and Converter systems have been unified.

              Keith
              Hi!
              Thanks for the quick answer!
              I tried now Version 2.0.3.CI-530 with lots of changes :-) And no Formatters any more ;-)
              My List of Domainobjects (Deliverer) get now "Converted" to a List of SelectItem Objects
              which fills my DropDownBox (<h:selectOneMenu/>)

              I build my list of SelectItems for each Domainobject with following Converter:
              PHP Code:
              public class SelectItemsConverter implements Converter {

                  public Class 
              getSourceClass() {
                      return 
              Object.class;
                  }

                  public Class 
              getTargetClass() {
                      return 
              SelectItem.class;
                  }

                  public 
              Object convertSourceToTargetClass(Object source, Class targetClassthrows Exception {
                      if (
              source instanceof List){
                          List<
              SelectItemresult = new ArrayList<SelectItem>();
                          List 
              sourceList = (List) source;
                          for (
              Object next sourceList){
                              if (
              next != null) {
                                  
              result.add(new SelectItem(next,next.toString()));
                              }
                          }
                          return 
              result;
                      }else{
                          return 
              null;
                      }
                  }

              theirfor I thought I wouldn't need any converter because I put the whole Deliverer Object into the SelectItem but this does not work. The Items get rendered as
              PHP Code:
              <option value="com.bar.dm.deliverer.Deliverer@e1dfe61c">com.bar.dm.deliverer.Deliverer@e1dfe61c</option
              So I wrote a DelivererConverter as follows:
              PHP Code:
              public class DelivererConverter implements ConverterTwoWayConverter {
                  private 
              ProductService productService;

                  public Class 
              getSourceClass() {
                      return 
              String.class;
                  }

                  public Class 
              getTargetClass() {
                      return 
              Deliverer.class;
                  }

                  public 
              Object convertSourceToTargetClass(Object source, Class targetClassthrows Exception {
                      if (
              source instanceof String){
                          
              Long id Long.parseLong((String)source);
                          return 
              productService.getDeliverer(id);
                      }else{
                          return 
              null;
                      }
                  }

                  public 
              Object convertTargetToSourceClass(Object target, Class sourceClassthrows Exception {
                      if (
              target instanceof Deliverer){
                          
              Deliverer d = (Deliverertarget;
                          return 
              d.getId();
                      }else{
                          return 
              null;
                      }
                  }


                  public 
              ProductService getProductService() {
                      return 
              productService;
                  }

                  public 
              void setProductService(ProductService productService) {
                      
              this.productService productService;
                  } 
              But it is not used by JSF, not even called and I was also not able to configure the converter= Tag for the <h:selectOneMenu in my xhml file

              Have I forgotten something? Probably there is something needed to be configured in the faces-config.xml which now just has a com.sun.facelets.FaceletViewHandler configured but nothing else.

              Btw. when will 2.0.3 be released?

              Thank you very much for your time!

              -w

              Comment


              • #8
                did u registered ur converter?
                did u used it in the flow.xml file's result-type evaluate attribute
                joe

                Comment


                • #9
                  Hi!

                  Yes I registered both:
                  SelectItemsConverter and DelivererConverter with addConverter(Converter c) as a subclass of the org.springframework.binding.convert.service.Defaul tConversionService and configuring this at the
                  PHP Code:
                  <faces:flow-builder-services id="facesFlowBuilderServices"
                                                   
                  conversion-service="myConversionService"
                              
                  /> 
                  as myConversionService

                  To the 2nd question:
                  On the view-state to create a new product which shows the dropdown of deliverers I have an on-entry evaluate expression as follows:
                  PHP Code:
                  <evaluate expression="productService.getDeliverers()" result="flowScope.deliverers" result-type="selectItems"/> 
                  So that I can use the deliverers List for the <f:selectItems value in my xhtml which gets converted by the SelectItemsConverter:
                  PHP Code:
                  ...
                  <
                  h:selectOneMenu id="deliverersMenu" value="#{product.deliverer}" converter="#{delivererConverter}">
                     <
                  f:selectItems value="#{deliverers}" />
                  </
                  h:selectOneMenu>
                  ... 
                  But the DelivererConverter does not get called when the form is going to submit, just leaving the error-message:
                  PHP Code:
                  Conversion Error setting value 'com.foo.dm.deliverer.Deliverer@e7a61ef6' for 'null Converter'
                  I also have tried to set the DelivererConverter at the <h:selectOneMenu converter="???"/> shown above, (with alias, with complete ClassName, ...) but nothing helps.
                  How should this normally happen? Why isn't there any spring-example showing conversion to domain-specific object? (i.e. the booking example just uses Integers as SelectItem Values which get 1:1 saved to the Booking Object without any conversion needed. ;-)

                  Thanks & Greetings

                  Comment


                  • #10
                    Originally posted by wolfman22 View Post
                    How should this normally happen?
                    When working with <h:selectOneMenu> element you shoud use javax.faces.convert.Converter in order to map your domain object on HTML option's value represented as string.

                    Code:
                    <h:selectOneMenu id="product" value="#{mybean.product}" converter="myapp.ProductConverter" >
                          <f:selectItems value="#{products}"/>
                    </h:selectOneMenu>
                    where "products" - a collection of SelectItem and "myapp.ProductConverter" is registered in faces-config.xml as following:

                    Code:
                    <converter>
                    	<converter-id>myapp.ProductConverter</converter-id>
                    	<converter-class>my.package.ProductConverter</converter-class>
                    </converter>
                    ProductConverter class would be something like this:

                    Code:
                    public class ProductConverter implements javax.faces.convert.Converter {
                    	
                    	public Object getAsObject(FacesContext context, UIComponent component, String key) {
                    		if (NumberUtil.parseLongSafe(key) < 1){
                    			return null;
                    		}
                    		return getProductService(context).get(NumberUtil.parseLongSafe(key));
                    	}
                    
                    	public String getAsString(FacesContext context, UIComponent component, Object obj) {
                    		if (obj == null){
                    			return "0";
                    		}
                    		return String.valueOf(((Product)obj).getId());
                    	}
                    	
                    	private ProductService getProductService(FacesContext context){
                    		return (ProductService)FacesContextUtils.getWebApplicationContext(context).getBean("productService");
                    	}
                    }
                    Converting Product object into SelectItem - it's an another task which I do manually for now. Here's an example:

                    Code:
                    	public List<SelectItem> getProducts(){
                    		List<SelectItem> items = new ArrayList<SelectItem>();
                    		
                    		items.add(new SelectItem(null, "All"));
                    		
                    		for (Product product : productService.listAll()) {
                    			items.add(new SelectItem(product, product.getNameShort()));
                    		}
                    		
                    		return items;
                    	}

                    Comment


                    • #11
                      Originally posted by and View Post
                      Converting Product object into SelectItem - it's an another task which I do manually for now.
                      I think i would be valuable to convert a list of domain objects into list of SelectItems autmatically using result-type attribute by implementing org.springframework.binding.convert.Converter interface. But in SWF 2.0.2 I didn't manage to do this because Spring's conversion subsystem refuses to convert List into List and ignores my converter even when I explicitly specify result-type="selectItems".

                      Hope with 2.0.3 it will be possible.

                      Comment


                      • #12
                        Originally posted by and View Post
                        ...
                        But in SWF 2.0.2 I didn't manage to do this because Spring's conversion subsystem refuses to convert List into List and ignores my converter even when I explicitly specify result-type="selectItems".

                        Hope with 2.0.3 it will be possible.
                        Hi!

                        Thanks for you'r answer the part where you mentioned:
                        PHP Code:
                        private ProductService getProductService(FacesContext context){
                                return (
                        ProductService)FacesContextUtils.getWebApplicationContext(context).getBean("productService");
                            } 
                        will be very helpfull indeed :-)

                        To your next post:
                        The Converter from List to List is ignored because in org.springframework.binding.convert.service.Static ConversionExecutor in the method: public Object execute(Object source)
                        it is checked:
                        PHP Code:
                        if (targetClass.isInstance(source)) {
                                    
                        // source is already assignment compatible with target class
                                    
                        return source;
                                } 
                        so the original List is returned, because there is no check (probably not possible) if the Generics match List<Deliverer> converting to List<SelectItem>
                        Probably this could/should be considered in 2.0.3. i.e. when there is an alias explicitly setted it should not check for assignable before

                        Greetings!
                        Last edited by wolfman22; Jul 9th, 2008, 07:18 AM. Reason: detailing second part now as I'm sitting in front of the code ;-)

                        Comment


                        • #13
                          I am also having the similar problem in that I am unable to use some PropertyEditors (that formats String to String) with Webflow 2.0.3. This is due to the fact that it is checking of assignment compatibility between source and target types before calling your custom Conversion service. Has anyone got any solution to this? I have posted detailed description of my problem under a different thread (titled 'Custom Converter example'). I am unable to paste its URL here because I have not made atleast 15 posts to the forum!

                          Comment

                          Working...
                          X