Last time, we introduced the concept of handling errors using Exceptions. Another improvement to our application will be data storage. In the next chapter, we will use a database for this, but for now let’s try to save our suppliers in a text file. Since the application is already structured into specialized layers, we only need to work with the storage layer.
In addition to our existing application, we should add some different functionalities:
The file will look like this:
1,Fresh lemons,freshlemons@email.com
2,Sweet Sugar,sweetsugar@email.com
3,Cold Ice,coldice@email.com
On the first column, we have the ID (“1”), then on the following columns are rest of the supplier’s attributes: name (“Fresh lemons”) and email (“freshlemons@email.com”).
We mentioned that we need to modify only the storage layer. The rest of our application will remain unchanged.
To achieve this, we need to extend our existing memory Repository by adding two new features: reading from a file and writing to a file. We can do this by creating a new Repository Class that will inherit all the behavior of the previous one. In addition, it will implement the new methods: saveToFile and writeToFile. The newly created SupplierFileRepository will have an attribute: filename.
public class SupplierFileRepository extends SupplierRepository {
private String filename;
...
}
Keeping this in mind, we need to create a method which reads all the data from the .csv file:
public List readSuppliersFromFile() {
List suppliers = new ArrayList<>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filename));
String line;
while ((line = reader.readLine()) != null) {
String[] elems = line.split(",");
int id = Integer.parseInt(elems[0]);
String name = elems[1];
String contactEmail = elems[2];
Supplier supplier = new Supplier(id, name, contactEmail);
suppliers.add(supplier);
}
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return suppliers;
}
When an instance of SupplierFileRepository is created, all the data from the file should be loaded into memory:
public SupplierFileRepository(String filename) {
super();
this.filename = filename;
loadSuppliersFromFile();
}
private void loadSuppliersFromFile() throws IDNotUniqueException {
List suppliers = readSuppliersFromFile();
for(Supplier supplier: suppliers){
this.save(supplier);
}
The next step is to create a method to write suppliers in the file:
private void writeToFile() {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(filename));
Iterable suppliers = findAll();
for (Supplier supplier : suppliers) {
String line = supplier.getId() + "," + supplier.getName() + "," + supplier.getContactEmail();
writer.write(line);
writer.newLine();
}
writer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
The final step is to Override the saving method so that the supplier is saved to the file after being added to our list of suppliers. We need to apply on a similar approach to all the methods.
@Override
public Supplier save(Supplier supplier) throws IDNotUniqueException {
Supplier savedSupplier = super.save(supplier);
writeToFile();
return savedSupplier;
}
The final class will look like this:
public class SupplierFileRepository extends SupplierRepository {
private String filename;
public SupplierFileRepository(String filename) throws IDNotUniqueException {
super();
this.filename = filename;
loadSuppliersFromFile();
}
@Override
public Supplier save(Supplier supplier) throws IDNotUniqueException {
Supplier savedSupplier = super.save(supplier);
writeToFile();
return savedSupplier;
}
@Override
public Supplier update(Supplier supplier) {
Supplier updatedSupplier = super.update(supplier);
writeToFile();
return updatedSupplier;
}
@Override
public void delete(int supplierId) {
super.delete(supplierId);
writeToFile();
}
public List readSuppliersFromFile() {
List suppliers = new ArrayList<>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filename));
String line;
while ((line = reader.readLine()) != null) {
String[] elems = line.split(",");
int id = Integer.parseInt(elems[0]);
String name = elems[1];
String contactEmail = elems[2];
Supplier supplier = new Supplier(id, name, contactEmail);
suppliers.add(supplier);
}
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return suppliers;
}
private void loadSuppliersFromFile() throws IDNotUniqueException {
List suppliers = readSuppliersFromFile();
for(Supplier supplier: suppliers){
this.save(supplier);
}
}
private void writeToFile() {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(filename));
Iterable suppliers = findAll();
for (Supplier supplier : suppliers) {
String line = supplier.getId() + "," + supplier.getName() + "," + supplier.getContactEmail();
writer.write(line);
writer.newLine();
}
writer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Let’s create some tests with our newly created class:
public class SupplierFileRepositoryTest {
private String filename;
public SupplierFileRepositoryTest(String filename) {
this.filename = filename;
}
private void clearFile() {
try (FileOutputStream fos = new FileOutputStream(filename)) {
// the file is emptied
} catch (IOException e) {
e.printStackTrace();
}
}
public void shouldSaveToFileOneElement_whenSaveIsCalled() throws IDNotUniqueException {
clearFile();
SupplierFileRepository fileRepository = new SupplierFileRepository(filename);
Supplier firstSupplierToSave = new Supplier(1, "Lemonades", "contact@lemonades.com");
Supplier firstSavedSupplier = fileRepository.save(firstSupplierToSave);
List suppliersFromFile = fileRepository.readSuppliersFromFile();
assert suppliersFromFile.size() == 1;
assert fileRepository.findById(1) != null;
clearFile();
}
public void testAllSupplierFileRepository() throws IDNotUniqueException {
shouldSaveToFileOneElement_whenSaveIsCalled();
}
}
public class MainTest {
public void runAllTest() {
try {
SupplierTest domainTests = new SupplierTest();
domainTests.testAllSupplier();
SupplierRepositoryTest repositoryTests = new SupplierRepositoryTest();
repositoryTests.testAllSupplierRepository();
SupplierFileRepositoryTest repositoryFileTests = new SupplierFileRepositoryTest("test-file.csv");
repositoryFileTests.testAllSupplierFileRepository();
SupplierServiceTest serviceTests = new SupplierServiceTest();
serviceTests.testAllSupplierService();
System.out.println("All tests have ran successful!");
} catch (ValidationException | IDNotUniqueException e) {
System.out.println("The tests have failed, e=" + e.getMessage());
}
}
}
Finally we should add our class to the main program:
public class Main {
public static void main(String[] args) throws ValidationException, IDNotUniqueException {
SupplierFileRepository supplierRepository = new SupplierFileRepository("suppliers.csv");
SupplierValidator supplierValidator = new SupplierValidator();
SupplierService supplierService = new SupplierService(supplierRepository, supplierValidator);
UserInterface userInterface = new UserInterface(supplierService);
MainTest mainTest = new MainTest();
mainTest.runAllTest();
userInterface.runMenu();
}
}
The file “suppliers.csv” should be placed in the root of our program, at the same level as the Main class. Below is the new structure of our project:
We want to change the representation of the data in our files by adding a header and using “|” as the separator. An example is provided below.
Where do we need to make changes in our application?
id|name|email
1|Fresh lemons|freshlemons@email.com
2|Sweet Sugar|sweetsugar@email.com
3|Cold Ice|coldice@email.com
In this tutorial, we enhanced our application by implementing file storage. We learned that by using layers, we can modify only the necessary part, ensuring that the rest of the application remains intact. In our next tutorial, we will discover how to handle the second entity in our given problem.
Learn advanced concepts, work on real-world projects, and fast-track your journey to becoming a proficient Java developer. Start now and unlock your full potential in the world of Java programming!
Start now and unlock your full potential in the world of Java programming!
The place where you can start your Java journey.
© All Rights Reserved.