I want to read in a csv file once, and later request information from it. Later this is going to be in a website/Rest-API. I am new to the world of java-website-development, but I hope this way is the way to do it:
I create a class that reads in the data (I want that this happens once, so I use a static variable for that).
When the csv is read in by opencsv, the data are stored in a bean. For this I create the Car
-class as a bean.
I use a third class to do the processing and the logic. Later this is supposed to be the website that processes the data.
Here are the classes:
The bean:
Car.java
package org.example;
import com.opencsv.bean.CsvBindByName;
import java.math.BigDecimal;
public class Car {
@CsvBindByName
private int id;
@CsvBindByName(column = "name")
private String brand;
@CsvBindByName
private BigDecimal price;
public int getId() {
return id;
}
public String getBrand() {
return brand;
}
public BigDecimal getPrice() {
return price;
}
public void setId(int id) {
this.id = id;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public void setBrand(String brand) {
this.brand = brand;
}
@Override
public String toString() {
return "Car{" +
"id=" + id +
", brand='" + brand + '\'' +
", price=" + price +
'}';
}
}
abc.csv:
id,name,price
1,Audi,52642
2,Mercedes,57127
3,Skoda,9000
4,Volvo,29000
5,Bentley,350000
6,Citroen,21000
7,Hummer,41400
8,Volkswagen,21600
9,Toyota,26700
ReadCSVFile.java
package org.example;
import com.opencsv.bean.CsvToBeanBuilder;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.List;
public class ReadCSVFile {
static String fileName = "src/main/resources/abc.csv";
public static List<Car> cars;
static {
try {
cars = new CsvToBeanBuilder(new FileReader(fileName))
.withType(Car.class).build().parse();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
}
Main.java
package org.example;
import com.opencsv.CSVReader;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
System.out.println();
for (Car car : ReadCSVFile.cars) {
System.out.println(car.toString());
}
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 10; i++) {
System.out.println("Enter id to get more details about the car.");
int id_number = sc.nextInt();
System.out.println("Your selected id is "+id_number);
Car selected_car = null;
for (Car car : ReadCSVFile.cars) {
if (car.getId() == id_number) {
selected_car = car;
}
}
if (selected_car == null) {
System.out.println("No car found that matches your id.");
} else {
System.out.println("Selected car matches: " + selected_car.toString());
}
System.out.println();
}
}
}
This works fine, but when I add a constructor in the Car.java
public Car(int id, String brand, BigDecimal price) {
this.id = id;
this.brand = brand;
this.price = price;
}
then I get an error: Caused by: java.lang.RuntimeException: com.opencsv.exceptions.CsvBeanIntrospectionException: Instantiierung des angegebenen Typs (und eventuell vorhandene Untertypen) ist unm�glich.
I do not know how to switch this error message to English; it means something like "It is not possible to instantiate the wanted type (and possibly also present subtypes)".
Does opencsv generally have problems with constructors? Is this a wanted behaviour? Do beans generally lack constructors? Because I feel like I want to have a constructor in the future in my class...
Please feel free to add comments about my general approach how I organize the code.
OpenCSV‘s introspection works by creating object instances via a no-args constructor. Therefore, you are required to provide one, even if you have specialized constructors as posted in your question.
By default, there will be a no-arg constructor in Java, however, once you have a custom one, the no-arg one must be explicitly defined in your Java class.
To cure the problem, just add back in a no-arg constructor, eg in a protected
form:
protected Car() {}
This way, the code should just work fine at runtime.