1

I am writing a play application with Basket, Product and Basket_Product tables. Basket and Products have a many to many relationship which is stored in Basket_Product. I am using Ebean ORM and am getting this error

[error] Test models.ModelsTest.createAndRetrieveOrder failed: java.lang.NullPointerException: null, took 5.128 sec
[error]     at models.BasketProductPk.hashCode(BasketProductPk.java:43)
[error]     at java.util.HashMap.hash(HashMap.java:338)
[error]     at java.util.HashMap.get(HashMap.java:556)
[error]     at com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext$ClassContext.putIfAbsent(DefaultPersistenceContext.java:175)
[error]     at com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext$ClassContext.access$100(DefaultPersistenceContext.java:148)
[error]     at com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext.putIfAbsent(DefaultPersistenceContext.java:56)
[error]     at com.avaje.ebeaninternal.server.query.SqlTreeNodeBean.load(SqlTreeNodeBean.java:235)
[error]     at com.avaje.ebeaninternal.server.query.CQuery.readRow(CQuery.java:541)
[error]     at com.avaje.ebeaninternal.server.query.CQuery.readBeanInternal(CQuery.java:575)
[error]     at com.avaje.ebeaninternal.server.query.CQuery.hasNextBean(CQuery.java:702)
[error]     at com.avaje.ebeaninternal.server.query.CQuery.readTheRows(CQuery.java:689)
[error]     at com.avaje.ebeaninternal.server.query.CQuery.readCollection(CQuery.java:655)
[error]     at com.avaje.ebeaninternal.server.query.CQueryEngine.findMany(CQueryEngine.java:175)
[error]     at com.avaje.ebeaninternal.server.query.DefaultOrmQueryEngine.findMany(DefaultOrmQueryEngine.java:77)
[error]     at com.avaje.ebeaninternal.server.core.OrmQueryRequest.findList(OrmQueryRequest.java:263)
[error]     at com.avaje.ebeaninternal.server.core.DefaultServer.findList(DefaultServer.java:1502)
[error]     at com.avaje.ebeaninternal.server.querydefn.DefaultOrmQuery.findList(DefaultOrmQuery.java:890)
[error]     at com.avaje.ebeaninternal.util.DefaultExpressionList.findList(DefaultExpressionList.java:173)
[error]     at models.ModelsTest.createAndRetrieveOrder(ModelsTest.java:100)

Here is my Junit test thats throwing the error. Its when i try accessing the Basket_Product table. I have checked my DB and everything inserts properly i just keep getting the error when trying to access Basket_Product for a specific basket.

Model Test Method

@Test
public void createAndRetrieveOrder(){
    Customer walter = Customer.find.where().eq("email", "test@banana_now.com").findUnique();
    Product p1 = Product.find.where().idEq(1).findUnique();
    Product p2 = Product.find.where().idEq(2).findUnique();
    Basket b = new Basket(walter);

    b.save();
    new BasketProduct(p1, b, 2).save();
    new BasketProduct(p2, b, 2).save();

    Basket b1 = Basket.find.where().idEq(8).findUnique();

    List<BasketProduct> bplist = BasketProduct.find.where().eq("basket_id", b1.id).findList();

    assertNotNull(bplist);
}

Embedded Key

@Embeddable
public class BasketProductPk implements Serializable{
    @Column(name = "product_id")
    private Product product;
    @Column(name = "basket_id")
    private Basket basket;

    public BasketProductPk(Product product, Basket basket) {
        this.product = product;
        this.basket = basket;
    }
    @Override
    public boolean equals(Object otherOb) {
        if (this == otherOb) {
            return true;
        }
        if (!(otherOb instanceof BasketProductPk)) {
            return false;
        }
        BasketProductPk other = (BasketProductPk) otherOb;
        return (
                (product==null?other.product==null:product.equals
                        (other.product)
                )
                        &&
                        (basket  == other.basket)
        );
    }
    @Override
    public int hashCode() {
        return (
                (product==null?0:product.hashCode())
                        ^
                        (basket.hashCode())
        );
    }

}

Basket Product

@Entity
@Table(name = "basket_product")
public class BasketProduct extends Model {
    @EmbeddedId
    public BasketProductPk id;

    @ManyToOne(cascade= CascadeType.ALL)
    @JoinColumn(name="product_id")
    public Product product;

    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="basket_id")
    public Basket basket;

    public int quantity;
    public float subtotal;


    public BasketProduct(Product product, Basket basket, int quantity){
        this.id = new BasketProductPk(product, basket);
        this.product = product;
        this.basket = basket;
        this.quantity = quantity;
        this.subtotal = quantity * product.price;
    }
    protected BasketProduct() {}

    public static Finder<String, BasketProduct> find = new Finder<String, BasketProduct>(String.class, BasketProduct.class);
    // getters, setters
}

Product

@Entity
public class Product extends Model{
    @Id
    public int id;
    public String name;
    public Float price;
    public String category;
    public String subcategory;
    public String image_url;
    public String url;
    @ManyToOne
    private Store store;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "product")
    private List<BasketProduct> basket_product;

    public Product(String name, Float price, String category, String subcategory, String image_url, String url, Store store){
        this.name = name;
        this.price = price;
        this.category = category;
        this.subcategory = subcategory;
        this.image_url = image_url;
        this.url = url;
        this.store = store;
    }

    public static Finder<String, Product> find = new Finder<String, Product>(String.class, Product.class);

}

Basket

@Entity
public class Basket extends Model {
    @Id
    public int id;
    @CreatedTimestamp
    public Timestamp time;
    int complete;
    @ManyToOne
    public Customer customer;
    @ManyToOne
    public Employee employee;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "basket")
    public  List<BasketProduct> basket_product;

    public Basket(Customer customer){
        this.customer = customer;
        this.complete = 0;
    }
    public Basket(Customer customer, Employee employee){
        this.customer = customer;
        this.employee = employee;
    }

    public static Finder<String, Basket> find = new Finder<String, Basket>(String.class, Basket.class);

}
Neil Stockton
  • 11,383
  • 3
  • 34
  • 29
wwoodal1
  • 313
  • 3
  • 13
  • Was my answer helpful? Have it helped you to solve your problem? If so then consider accepting it. If not then please write why it is not enough and maybe I would be able to provide some more help. – rtruszk Dec 08 '14 at 19:29
  • @rtruszk Sorry havent actually fixed it yet. I have been working on other parts of the project. I will try and do that soon and will be sure to let you know. – wwoodal1 Dec 10 '14 at 01:01

1 Answers1

1

This error is because when BasketProductPk is loaded then Basket and Product are not loaded and they are both null.

I see that in your hashCode method you have:

(product==null?0:product.hashCode()) ^ (basket.hashCode())

So you check if product is null but you don't check if basket is null. So your NullPointerException is because basket is null.

To make this code work you have to make few changes in your code: See these answers for details:

Community
  • 1
  • 1
rtruszk
  • 3,902
  • 13
  • 36
  • 53