Search code examples
javaformslistactionstruts-1

Adding custom class objects to list showing ambiguity


This is a sample test code I wrote to ensure what I know is right

class Form {
    List<Sample> samples;
    List<Sample> sampleList;
    public List<Sample> getSamples() {
        return samples;
    }
    public void setSamples(List<Sample> samples) {
        this.samples = samples;
    }
    public List<Sample> getSampleList() {
        return sampleList;
    }
    public void setSampleList(List<Sample> sampleList) {
        this.sampleList = sampleList;
    }
    void setInitialData() {
        this.samples = new ArrayList<Sample>();
        this.sampleList = new ArrayList<Sample>();
    }
}

class Sample {

}

public class ListAddingAmbiguity {

    public static void main(String[] args) {
        Form form = new Form();
        form.setInitialData();
        Sample sample = new Sample();
        form.getSamples().add(sample);
        form.getSampleList().add(sample);
        System.out.println(form.getSamples().size());
        System.out.println(form.getSampleList().size());
    }
}

The output coming is

1
1

And it is correct, samples and sampleList are two different references pointing to two different memory locations, so adding to samples won't change the size of sampleList.

But in my project code it is different, this is my Form class

public class InvoiceForm extends BaseActionForm {
    private List<ProductTO> products;
    private List<ProductTO> productList;
    // getters and setters
}

This is the code in my Action class

private void setProductsToInvoice(InvoiceForm invoiceForm) throws Exception {

        if(invoiceForm.getProducts() != null && !invoiceForm.getProducts().isEmpty()){
            ProductTO productTO = new ProductTO();//ProductEntryHandler.getInstance().prepareProductsForInvoice();
            invoiceForm.getProducts().add(productTO);
            invoiceForm.getProductList().add(productTO);
        }else {
            List<ProductTO> productTOs = new ArrayList<ProductTO>();
            productTOs.add(ProductEntryHandler.getInstance().prepareProductsForInvoice());
            invoiceForm.setProducts(productTOs);
            invoiceForm.setProductList(productTOs);
        }
    }

Both the products and productList are having a size of 1 initially, so in the above code if block will execute. The commented portion is the earlier code. Even if it is the new code ProductTO productTO = new ProductTO(); or the old code ProductTO productTO = ProductEntryHandler.getInstance().prepareProductsForInvoice(); the problem is the same.

Like I said when execution comes to the method both the lists are having a size of 1. When the line invoiceForm.getProducts().add(productTO); is executed the size of products and productList size becomes 2, which is in conflict with my test code. Now when the nest line invoiceForm.getProductList().add(productTO); is executed both the list size is becoming 3. I don't know why its happening, can anybody help?


Solution

  • The following code else case in setProductsToInvoice set both products and productList to the same list:

    List<ProductTO> productTOs = new ArrayList<ProductTO>();
    productTOs.add(ProductEntryHandler.getInstance().prepareProductsForInvoice());
    invoiceForm.setProducts(productTOs);
    invoiceForm.setProductList(productTOs);
    

    The correct way, or at least the less incorrect way, is something like this:

    ProductTO newProd = 
        ProductEntryHandler.getInstance().prepareProductsForInvoice());
    invoiceForm.setProducts(new ArrayList<ProductTO>());
    invoiceForm.getProducts().add(newProd);
    
    invoiceForm.setProductList(new ArrayList<ProductTO>());
    invoiceForm.getProductList().add(newProd);
    

    I'd suggest an investigation to determine why there are two lists apparently being maintained in parallel in the first place. At first glance, it has a bit of a smell to it...