java record support/value extraction
Brought to you by:
aruckerjones,
sconway
Hi, is there plan to add support out of the box ? I think that would be great addition.
I was doing some tests with custom mapping strategies that I wanted to add on my side without change request. Unfortunately currently populateNewBean
defined in AbstractMappingStrategy
by default calls no args constructor which won't work with records.
Hence my idea was to simply override populateNewBean
, but there is one missing piece to make that work.
Maybe if you don't want to support records out of the box it would be possible to get access to most of the code in setFieldValue
from AbstractBeanField ? Most notably getting value as that was only issue that I blocked me in implementing that on my own.
Hello Kamil
Sorry but there is no plans to support Java Records in opencsv. Java Records was added in Java 14 and standardized in Java 16 while we are committed to maintaining compatibility with Java 8.
Now for the second part I am very happy to open access (as little as possible - Least Privlege and all that) to allow you to override as neccessary. But I would like a definitive list as to what you want opened and why. The reason I am being picky is your request actually confused me.... okay that shouldn't be a surprise I am easily confused. But both the populateNewBean in AbstractMappingStrategy and setFieldValue in AbstractBeanField are public so you can override them to your hearts content with your own implementation. Digging a little deeper into the setFieldValues there were only two method calls that were private and those were preProcessValue and validateValue which simply calls the processString or validate on an interface to a class the user (that is you) has to define so I see no reason to open that up - if anything if it was that important I figure you would come up with your own implementation and call it in your override of setFieldValue.
So yes please send me a list of what needs to be opened up and how that would be helpful. As long as life is not raining down on me I can get those changes out pretty quickly. I just want to make sure there is a balance between extensibility, security and safety.
Scott :)
Hi Scott, thank you for taking your time to look into my request.
I fully understand why you don't want to add support for records due to compatibility reasons.
In order to provide more details (and to make sure that my approach would work) I created this simple POC: https://github.com/Svanar/opencsv-record-strategy.
Main logic part is in classes
RecordColumnPositionMappingStrategy
andRecordHeaderColumnNameMappingStrategy
.The core functionality being method:
As you can see I copied code from
AbstractBeanField#setFieldValue
class from opencsv.Crucial part is that reflective call to method
convert
that is currently hidden.From my perspective it would be great if BeanField had something along those lines:
* Added new method like (I'm bad at naming methods) that will allow to implement my strategy without reflection. That is basically current implementation of
setFieldValue
, but public and does not actually set value.setFieldValue
would simply look like:Ofcourse that is just my simplest idea and one that works for my use case.
I hope now it is a bit clearer what I'm trying to achieve and what parts I'm missing.
I'm happy to provide more details.
Once again, thanks!
Kamil
Kamil is your github project private because I am getting a 404 when I try and view it.
hi, I checked and it is public, however for some reason dot was added as part of url. This should work fine: https://github.com/Svanar/opencsv-record-strategy
convert is not hidden - it is an abstract method that is defined by whomever extends the AbstractBeanField.
You can see examples of that in BeanFieldSplit, BeanFieldSingleValue, ConvertLanguageToBoolean.
That said I can change preProcessValue and validateValue in AbstractBeanField from private to protected if you want to call them directly from the class you are using that extends the AbstractBeanField.
Short term you can copy out the two methods and put them in your class. Or if you do not use the PreProcessors and PreValidators you can remove them entirely - we do not use them we created them to allow users of opencsv a way of injecting their own custom validations and string processors. I have defined a few preprocessors and validators but they are only used in unit tests.
Scott :)
Yes, you are of course right, but maybe I haven't been precise enough. What I really wanted to say by hidden is that, my code cannot access that method from outside of the converter itself, but this is the method that gets the actual value that will be set in field. While I can override that method I can never call it by myself and that is problem in my approach to make records work.
If you check mapping strategies that I created they are now using reflections to call the convert method in order to obtain the value of the srgument. As far as my understanding goes currently there is no method in BeanField to only get the value that would be set to the particular field, rather getting value is always followed by setting it in the field which does not work for records.
This is the reason of my proposal to add new method to BeanField interface that will only convert value, but not set it.