Why is this List<> throwing NullPointerException? - java

so i've been sitting above this code for a while , ready the NullPointerException threads, and still can't figure out what is going wrong in my code, so i turn to you.
public class Main {
public static void main(String[] args){
/* Making catalog, loading last state */
Collection catalog = new Collection();
try {
catalog.readFromFile();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
catalog.addShip(new Ship("ABC123", "John", "Suzuki", 50));
}
}
And my Collection class looks like this:
public class Collection {
private List<Ship> shipList;
private String fileName = "catalog.txt";
private int income;
private int space;
public Collection() {
shipList = new ArrayList<Ship>();
income = 0;
space = 500;
File f = new File("catalog.txt");
if(!f.exists()) {
try {
f.createNewFile();
writeToFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void addShip(Ship SHIP){
space -= SHIP.LENGTH;
income += SHIP.COST;
shipList.add(SHIP);
}
public Ship getShip(int INDEX){
return shipList.get(INDEX);
}
public void writeToFile() throws IOException {
FileOutputStream f = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(f);
out.writeObject(shipList);
out.close();
}
#SuppressWarnings("unchecked")
public void readFromFile() throws IOException, ClassNotFoundException {
FileInputStream f = new FileInputStream(fileName);
ObjectInputStream in = new ObjectInputStream(f);
shipList = (ArrayList<Ship>)in.readObject();
in.close();
}
public int getIncome(){
return income;
}
public int getSpace(){
return space;
}
}
My problem is, when i call in main catalog.addship() i get nullptr error. After following the console errors, it says i get the nullptrexc when i call the addShip() on the catalog, following from there i get the error when i add() a Ship to the Collection's shipList. So what i concluded, it is because the shipList in the Collection is uninitialized. But in the constructor i write shipList = new ArrayList<Ship>(); so it is clearly initialized.
The exception stacktrace is the following:
Exception in thread "main" java.lang.NullPointerException
at collection.Collection.addShip(Collection.java:31)
at main.Main.main(Main.java:100)

In your main method, you initialize the ArrayList properly. But then, you make a
catalog.readFromFile()
call. In the readFromFile() method, you re-initialize the ArrayList
shipList = (ArrayList<Ship>)in.readObject();
the in.readObject() is returning null. That is why your shipList variable is null.
Hope this helps!

Related

i can not write more than one object on a file in java

import java.io.*;
import java.util.ArrayList;
public class Main {
static ArrayList<test> testArrey = new ArrayList<test>();
public static void main(String[] args) {
output(new test(18, "aren"));
output(new test(22, "ahmad"));
input();
read();
}
public static void read() {
for (test a : testArrey) {
System.out.println(a.age);
}
}
public static void input() {
try {
FileInputStream fileInput = new FileInputStream("open.ses");
ObjectInputStream ObjectInput = new ObjectInputStream(fileInput);
Object a1 = ObjectInput.readObject();
test b1 = (test) a1;
testArrey.add(b1);
Object a2 = ObjectInput.readObject();
test b2 = (test) a2;
testArrey.add(b2);
ObjectInput.close();
} catch (Exception ex) {
System.out.println("input error");
ex.printStackTrace();
}
}
public static void output(test a) {
try {
FileOutputStream fileOut = new FileOutputStream("open.ses");
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(a);
objectOut.close();
} catch (Exception ex) {
System.out.println("output error");
ex.printStackTrace();
}
}
public static class test implements Serializable {
int age ;
String name ;
public test(int age , String name ) {
this.age = age;
this.name = name;
}
}
}
as you can see a called output() method two time with new to object of (test)as argument ,and it must write two object on (open.ses)file but when i want to call (.readobject)two times it gives me an error that says one object is saved ............
how to write more than one object with the help of method like the one i wrote ??

How to access value of an abstract method in a different class?

AbstractInputFile is an abstract class and has the following code below:
public abstract class AbstractInputFile {
static final public int MIN_BILLING_CYCLE = 1;
static final public int MAX_BILLING_CYCLE = 12;
private File file;
public AbstractInputFile() {
}
public abstract List<Request> readFile() throws IOException, BarsException;
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
}
CSVInputFileImpl is a subclass of AbstractInputFile, thus inheriting the readFile() method. What it does is it reads the contents of a csv file using a buffered reader, stores it in an arraylist, and returns it.
public List<Request> readFile() throws IOException, BarsException {
List<Request> requests = new ArrayList<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
String line = "";
//READ CSV FILE
try {
BufferedReader br = new BufferedReader(new FileReader(getFile()));
int row = 1;
int index = 0;
while ((line = br.readLine()) != null) {
String[] data = line.split(",", 3);
//Validate if billing cycle ranges 1-12
try {
int billingCycle = Integer.parseInt(data[0]);
if(billingCycle <= MAX_BILLING_CYCLE && billingCycle >= MIN_BILLING_CYCLE) {
request.setBillingCycle(billingCycle);
} else {
log.error(BILLING_CYCLE_NOT_ON_RANGE + row);
throw new BarsException(BILLING_CYCLE_NOT_ON_RANGE + row);
}
} catch (BarsException e) {
log.error(INVALID_BILLING_CYCLE + row);
throw new BarsException(INVALID_BILLING_CYCLE + row);
}
//Validate start date
try {
LocalDate startDate = LocalDate.parse(data[1], formatter);
request.setStartDate(startDate);
} catch (DateTimeParseException e) {
log.error(INVALID_START_DATE_FORMAT + row);
throw new BarsException(INVALID_START_DATE_FORMAT + row);
}
//Validate end date
try {
LocalDate endDate = LocalDate.parse(data[2], formatter);
request.setStartDate(endDate);
} catch (DateTimeParseException e) {
log.error(INVALID_END_DATE_FORMAT + row);
throw new BarsException(INVALID_END_DATE_FORMAT + row);
}
row++;
//Add the requests to array list created previously
requests.add(index,new Request(request.getBillingCycle(), request.getStartDate(), request.getEndDate()));
index++;
}
//Validate if file exists
} catch (FileNotFoundException e) {
throw new BarsException(NO_SUPPORTED_FILE);
} catch (IOException e) {
throw new IOException(PATH_DOES_NOT_EXIST);
}
return requests;
}
In another public class FileProcessor, I am instructed to get the array list using List<Request> requests = abstractInputFile.readFile(); but is unable to do so because I am getting the error Non-static method 'readFile()' cannot be referenced from a static context.
public List<Request> execute(File file) throws BarsException {
InputFileFactory fact = InputFileFactory.getInstance();
try {
fact.getInputFile(file);
} catch (BarsException e) {
throw new BarsException(NO_SUPPORTED_FILE);
}
List<Request> requests = AbstractInputFile.readFile();
return requests;
}
My question is: How will I be able to retrieve the arraylist and return it in the execute(file) method? There might be a lot more errors in other areas of the code and logic but I'd appreciate any help and suggestions.
First things first, AbstractInputFile.readFile() can't be called for 2 reasons: readFile() in the AbstractInputFile class is abstract, and it is an instance method.
From what you wrote here, you implement the readFile() method in the subclass, CSVInputFileImpl. Therefore, in this case, your readFile() calls should be based on THIS class, not AbstractInputFile. However, this is still classified as an instance method, meaning you need to first create an instance of CSVInputFileImpl before you can call readFile(). I would correct the code like this (I'm making assumptions that the CSVInputFileImpl class is structured the same as AbstractInputFile, but make sure the file instance var is set):
CSVInputFileImpl csvInputFileImpl = new CSVInputFileImpl();
csvInputFileImpl.setFile(file);
List<Request> requests = csvInputFileImpl.readFile();
return requests;

Mock FileInputStream using Mockito/PowerMockito without having an existing file

I am writing a JUnit for a method that uses FileInputStream and in the constructor only the file name is passed. The file is created as part of a servlet request and this file is not stored any where.
I am trying to Mock FileInputStream using PowerMockito so that it gives me a mocked file object. Unfortunately I get FileNotFoundException which is valid but I am not sure how to test this method then because the file doesn't exist.
Method under test:
public String viewReport() throws Exception {
this.inputStream = new FileInputStream(DOCUSIGN_REPORT_FILE);
try {
boolean returnReport = validateRequest();
if (returnReport) {
intgList = this.generateViewIntegrationReportData(getESignUIConfig());
this.createCSVFile(intgList, new FileWriter(DOCUSIGN_REPORT_FILE));
} else {
failureResponse(msgs, 400);
return null;
}
} catch (Exception e) {
e.printStackTrace();
msgs.add(new Message(ESignatureIntegrationMessageTypeEnum.MESSAGE_TYPE_ERROR,
UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_CODE_500, UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_TEXT_SERVICE_ERROR));
failureResponse(msgs, 500);
return null;
}
return UiIntegrationKeyConstants.REPORT_REPSONSE;
}
JUnit test so far.
#Test
public void testViewReport() throws Exception {
Map<String, Object> actionMap = new HashMap<>();
actionMap.put("application", "ESignatureIntegrationAction");
ActionContext.setContext(new ActionContext(actionMap));
FileInputStream inputStream = Mockito.mock(FileInputStream.class);
PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenReturn(inputStream);
action = new ESignatureIntegrationAction();
action.viewReport();
}
I get an exception when the code reaches to new FileInputStream(DOCUSIGN_REPORT_FILE);
Thanks for the help.
I would suggest to refactor your code in a way that allows testing without a mocking framework.
It could look somewhat like this:
public class YourClass {
// ...
public String viewReport() {
try {
boolean isValidRequest = validateRequest();
if (isValidRequest) {
IntegrationReportCsvFileHandler fileHandler = new IntegrationReportCsvFileHandler();
IntegrationReportData inputData = fileHandler.readData(new FileInputStream(DOCUSIGN_REPORT_FILE));
IntegrationReportGenerator generator = new IntegrationReportGenerator();
IntegrationReportData outputData = generator.processData(inputData, getESignUIConfig());
fileHandler.writeReport(outputData, new FileWriter(DOCUSIGN_REPORT_FILE));
} else {
failureResponse(msgs, 400);
return UiIntegrationKeyConstants.FAILURE_RESPONSE;
}
} catch (Exception e) {
e.printStackTrace();
msgs.add(new Message(ESignatureIntegrationMessageTypeEnum.MESSAGE_TYPE_ERROR,
UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_CODE_500, UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_TEXT_SERVICE_ERROR));
failureResponse(msgs, 500);
return UiIntegrationKeyConstants.FAILURE_RESPONSE;
}
return UiIntegrationKeyConstants.REPORT_RESPONSE;
}
// ...
}
public class IntegrationReportData {
// your custom data structure
// may as well just be a List<Data>
// may be different for input and output
}
public class IntegrationReportException extends Exception {
// your custom exception
public IntegrationReportException(String message) { super(exception); }
}
public class IntegrationReportGenerator {
public IntegrationReportData processData(IntegrationReportData data, ESignConfig config) throws IntegrationReportException {
// here's your logic that requires testing
}
}
public class IntegrationReportCsvFileHandler {
public IntegrationReportData readData(InputStream input) throws IOException {
// read data from given input stream
}
public void writeData(IntegrationReportData data, OutputStreamWriter outputWriter) throws IOException {
// write data to given output stream
}
}
That way the IntegrationReportGenerator would be easily testable.

Cannot write to file ArrayList with class objects

I've reasearched a lot of websites and I couldn't find answear. I'm trying to write to .txt file my ArrayList which constains class objects. Every time I try to do it I`m getting exception. With reading is the same problem. Here is my code:
public static void write()
{
try
{
FileOutputStream out = new FileOutputStream("clients.txt");
ObjectOutputStream oout = new ObjectOutputStream(out);
oout.writeObject(lista);
oout.close();
}
catch(Exception ioe)
{
System.out.println("writing Error!");
welcome();
}
}
public static void read()
{
try
{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("clients.txt"));
lista = (List<Client>) ois.readObject();
}
catch (ClassNotFoundException ex)
{
System.out.println("Koniec pliku");
}
catch(IOException ioe)
{
System.out.println("Error!");
welcome();
}
}
I guess you're looking for the Serializable interface of Java. In order to save objects you're class have to implement it.
The question is: What execatly do you want to save? The content of the list so that you can save it in a file and load it afterwards?
This simple example works for me (for the scenario I mention above):
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public User(String name, int ag) {
this.name = name;
this.age = age;
}
#Override
public String toString() {
return (this.name + ' ' + this.age);
}
}
public class Main {
private static List<User> l;
public static void main(String[] args) {
l = new ArrayList<User>();
user1 = new User("John", 22);
user2 = new User("Jo", 33);
l.add(user1);
l.add(user2);
write();
}
public static void write() {
try {
FileOutputStream fos = new FileOutputStream("testout.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(l);
oos.close();
} catch (Exception ioe) {
System.out.println("writing Error!");
}
}
}
Ok I have changed a bit (not each function just the read and write functionality) and this work.
Link to Code.
One important thing is that the Scanner class is not serializable. Therefore, you have to make it static for example.

Can't resolve java.io.EOFException?

This is my first file
public class ObjectStream
{
public static void main(String args[]) throws FileNotFoundException, IOException
{
java.io.File f=new java.io.File("D:Employee.outt") ;
Employee e=new Employee("John");
Employee e1=new Employee("Mary");
Employee e2=new Employee("Christian");
OutputStream os=new java.io.FileOutputStream(f);
java.io.ObjectOutputStream oos= new ObjectOutputStream(os);
oos.writeObject(e);
oos.writeObject(e1);
oos.writeObject(e2);
}
}
This is my second file
public class Employee implements java.io.Serializable
{
private static int count=100;
private int eid;
private String ename;
public Employee()
{
count++;
this.eid=count;
}
public Employee(String ename)
{
this();
this.ename=ename;
}
public static int getCount() {
return count;
}
public static void setCount(int count) {
Employee.count = count;
}
public int getEid() {
return eid;
}
public void setEid(int eid) {
this.eid = eid;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
}
This is my third file
public class MainClass
{
public static void main(String args[]) throws FileNotFoundException, IOException, ClassNotFoundException
{
File f=new File("D:Employee.outt");
byte data[]=new byte[(int)f.length()];
InputStream is=new java.io.FileInputStream(f);
java.io.ObjectInputStream ois=new java.io.ObjectInputStream(is);
Object o=ois.readObject();
while(o!=null)
{
Employee e=(Employee)o;
System.out.println(e.getEid());
System.out.println(e.getEname());
o=ois.readObject();
}
ois.close();
is.close();
}
}
I am trying to read objects stored in Employee.outt in via this third file but it is reading all the objects but at the end throwing
Exception in thread "main" java.io.EOFException.
I don't know how to resolve it.
while(o!=null)
This isn't a valid way to read an ObjectInputStream. The readObject() method only returns a null if you wrote a null. At end of stream it throws, guess what, an EOFException, so the correct way to read the stream is to loop calling `readObject() until you catch that exception, then break and close the stream.
at the end of file it is giving EOF exception
That's exactly what EOFException means.
You should close ObjectOutputStreamin ObjectStream class.
oos.writeObject(e);
oos.writeObject(e1);
oos.writeObject(e2);
oos.close();
In the MainClass you can use a try-finally block to close the inputstream.
try
{
InputStream is=new java.io.FileInputStream(f);
java.io.ObjectInputStream ois=new java.io.ObjectInputStream(is);
// READ logic here
}
finally
{
ois.close();
is.close();
}
You really should flush and close the object output stream in "first file".
You only need to close 'ois' in "third file". The other stream is automatically closed for you.
If you know how many objects you're going to write, change "first file" to write the number of objects following first, then change "third file" to read that number and only read that many objects. That way, you never get the EOF exception, because you stop reading when you've read the last object.
As EJP pointed out, you still have to catch the EOFException, because the file you're reading might be damaged.
In First File:
...
oos.writeInt(3);
oos.writeObject(e);
...
In Third File:
...
try {
int numObjects = ois.readInt();
for( int a = 0; a < numObjects; ++a ) {
...
}
} catch( EOFException e ) {
...
}

Categories