Menu

#222 StatefulBeanToCsv should not consider static methods/fields as part of bean

v1.0 (example)
closed-invalid
None
5
2021-07-03
2021-04-09
aanno
No

OpenCsv 5.4
StatefulBeanToCsv should not consider static methods/fields as part of bean.

Example Bean:

public class OnDemandResource<T> {

    private static final double DELTA = 0.0000001;

    private static final Comparator<OnDemandResource<?>> PRICE_COMP = new Comparator<OnDemandResource<?>>() {
        @Override
        public int compare(OnDemandResource<?> onDemandResource, OnDemandResource<?> t1) {
            int result = (int) ((onDemandResource.price - t1.price) / DELTA);
            if (result == 0) {
                result = onDemandResource.id.compareTo(t1.id);
            }
            return result;
        }
    };

    public static Comparator getPriceComparator() {
        return PRICE_COMP;
    }

    private String unit;
    private double price;
    private String currency;
    private String id;
    private T resource;

   // ... getter and setters

Leads to:

"CURRENCY","DELTA","ID","PRICE","PRICE_COMP","RESOURCE","UNIT"
"USD","1.0E-7","t4g.nano","0.0048","com.github.aanno.jaws.csv.OnDemandResource$1@1135c707","ComputeResource{id=t4g.nano, memory=0.5 GiB, vcpu=2, storage=EBS only, clockSpeed=2.5 GHz, networkPerformance=Up to 5 Gigabit, physicalProcessor=AWS Graviton2 Processor, normalizationSizeFactor=0.25, processorFeatures=null, instanceFamily=General purpose}","Hrs"

Remark: The example bean here also contains a one-to-one relation to another Bean of type T. It would be great if there would be support for 'flattening' bean T into the output...

Discussion

  • Andrew Rucker Jones

    Last concern first: There is a way of flattening. It's the annotation CsvRecurse. Take a look at the documentation for more details.

    As for the static values and methods, perhaps you're right, and I'll consider it. I would offer this, though: DELTA, as relevant only to the Comparator, really ought to be in the Comparator itself, and not the surrounding bean. The Comparator, for its part, is referenced only once, in getPriceComparator(), so there's nothing stopping you from simply returning it as an anonymous class directly from that method instead of defining it as a static class in the bean.

     
  • aanno

    aanno - 2021-04-16

    Dear Andrew,

    well, what about an annotation like @CsvIgnore to ignore a field as far as OpenCsv is concerned?

    I also tried @CsvRecurse. This are my findings:
    On my example (with generic type), it seems not to work at all
    If I change the example to use a concrete type, it does work, but only in conjunction with annotations like @CsvBindByName on fields to include.

    Here some items that came to my mind:
    Perhaps @CsvBindByName should be allowed on class level as well for allowing to include all fields of the (recurse) bean in CSV? Perhaps a attribute like @CsvBindByName.prefix would be handy as well to prefix all (or the annotated) fields with a prefix?
    In the case above @CsvIgnore would be handy as well.

    Would you consider a contribution of the functionality described above?

    Kind regards,

    aanno

     
    • Andrew Rucker Jones

      You do know that we already have an annotation CsvIgnore to do exactly what you describe, right?

       
    • Andrew Rucker Jones

      CsvRecurse cannot be used on generic types, because generic types cannot be instantiated. This may not be relevant for writing (I haven't thought it through), but I try to maintain mirrored functionality in opencsv: things that work for reading must work for writing and vice versa.

      As for CsvRecurse only working on fields with binding annotations, binding works on one bean the same way it does for embedded beans: if binding annotations are used on the top-level bean, they must be used in embedded beans. If the top-level binding is done implicitly through a lack of any binding annotations (which will always lead to a header name binding), all fields will be bound in the top-level bean as well as embedded beans. This is consistent and by design.

      That said, you caught functionality for which we had no tests (the implied bindings + recursion). I just wrote the tests and fixed one little bug. So, thank you.

      I don't know what you mean by your prefix suggestion.

       
  • aanno

    aanno - 2021-04-16

    Well, right now @CsvIgnore is only for fields. It does not help with getPriceComparator() from my example...

     
    • Andrew Rucker Jones

      getPriceComparator() from your example is not being used at all. opencsv is reading PRICE_COMP directly from the bean. Since PRICE_COMP is a class, the class signature is being written. Simply annotate PRICE_COMP with CsvIgnore.

      opencsv does not use bean introspection, which would allow you to specify the names of accessor methods for variable. It uses reflection and assumes a variable named PRICE_COMP would have an accessor method named getPRICE_COMP().

       
  • Andrew Rucker Jones

    • status: open --> closed-invalid
    • assigned_to: Andrew Rucker Jones
     
  • Andrew Rucker Jones

    Closed for lack of activity. It also looks resolved.

     

Log in to post a comment.