Menu

#105 @CsvBindByName on Bean Methods

wont-fix
5
2019-09-01
2019-03-26
Matt Ouyang
No

I have an bean that delegates its getter implementations to other objects (see sample below). I would like to use @CsvBindByName to write to a text file but I can't because the annotation is only allowed on field methods. Additionally since I want my example bean to be immutable, I did not implement a setter method and I would not want OpenCSV to throw an error - it should only be an error if I attempt to build a bean from a CSV row. In short, the annotation should be allowed on either the getter or setter method and it should be applicable to both if defined.

If the development team is too busy to fulfill this request, I can try to find the time to implement it.

public class MyDelegatingBean {

    private SessionBean sessionBean = new SessionBean();

    public MyDelegatingBean(SessionBean sessionBean) {
        this.sessionBean = sessionBean;
    }

    @CsvBindByName(column = "session_id")
    public String getSessionId() { return sessionBean.getSessionId(); }

    public static void main(String[] args) {
        // should succeed
        MyDelegatingBean immutable = new MyDelegatingBean(new SessionBean());
        Writer writer = new FileWriter("yourfile.csv");
        StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer).build();
        beanToCsv.write(java.util.Arrays.asList(immutable));
        writer.close();

        // should fail because setter is not available
        List<MyDelegatingBean> beansFromFile = new CsvToBeanBuilder(new FileReader("yourfile.csv"))
           .withMappingStrategy(new HeaderColumnNameMappingStrategy<>())
           .build().parse();
    }
}

Discussion

  • Scott Conway

    Scott Conway - 2019-03-31

    This will take some thought - I will look into it a little deeper in after the 4.6 release.

    The big change you want is to put the annotation on a method not the field. If we were to go forward with this I would rather have new annotations (CsvBindByGetter and CsvBindBySetter) to call out the fact where they go and what they work with and leave the CsvBindByName alone.

    Short term I would recommend you do something like creating a child class that extends MyDelegatingBean that would actually have a sessionId with the CsvBindByName on it and a do nothing setter and a getter that returns super.getSesssionId() and use that in bean to csv class.

    Scott :)

     
  • Matt Ouyang

    Matt Ouyang - 2019-04-01

    I would rather have new annotations (CsvBindByGetter and CsvBindBySetter)

    After looking at the rest of the documentation, I agree that would be more consistent with the rest of the library.

     
  • Andrew Rucker Jones

    It may seem a bit weird, but all you really have to do is create a field for session_id, annotate it with @CsvBindByName, and create a getter method that returns the appropriate field of the wrapped class. (You can create a setter method too, if you want to.) opencsv always respects getters and setters if they exist. It doesn't really care if the field annotated is really truly the one that the getters or setters use. Sure, it's a useless field, but with a line or two of commenting, it should be clear enough.

     
  • Andrew Rucker Jones

    I forgot one more thing: if you want your class to be immutable even with opencsv, the best way to achieve that is by creating a setter that throws a java.lang.UnsupportedOperationException. It seems to me that that solution is very much in keeping with the philosophy behind Java.

     
  • Andrew Rucker Jones

    • status: open --> wont-fix
    • assigned_to: Andrew Rucker Jones
     

Log in to post a comment.