users@glassfish.java.net

Problems with EntityManager.remove() on Glassfish (Build 48)

From: Craig McClanahan <Craig.McClanahan_at_Sun.COM>
Date: Thu, 25 May 2006 12:55:31 -0700

I'm experimenting with the new JPA APIs by writing some simple
CRUD-based examples. Add, update, and display all work great ... but
I'm running into an exception (documented below) when trying to remove a
detail row. I am using Glassfish Build 48, and building the test code
with NB 5.5 beta.

I've got two entity classes that, among other things, have a
bidirectional one-to-many relationship with each other:

@Entity
public class User implements Serializable {
    ....
    @OneToMany(mappedBy="user")
    private List<Subscription> subscriptions;
    ...
    public List<Subscription> getSubscriptions() { return
this.subscriptions; }
    public void setSubscriptions(List<Subscription> subscriptions) {
        this.subscriptions = subscriptions;
    }
    ...
}


@Entity
public class Subscription implements Serializable {
    ...
    @ManyToOne
    private User user;
    ...
    public User getUser() { return this.user; }
    public void setUser(User user) { this.user = user; }
    ...
}

Note that the above classes correctly implement hashCode() and equals()
as well ... without that the comparisons performed would be failing.

According to the JPA specification, it is the application's
responsibility to maintain the properties that implement the
relationship, so I've added a convenience method to the User class like
this:

    public void removeSubscription(Subscription subscription) {
        if ((subscriptoin == null) || (subscriptions == null)) {
            return;
        }
        if (subscriptions.contains(subscription)) {
            subscriptions.remove(subscription);
            subscription.setUser(null);
        }
    }

Now, my business logic looks like this:

    @PersistenceContext
    EntityManager em; // Injected for me

    @Resource
    UserTransaction utx; // Injected for me

    Subscription subscription = ...; // A detached copy of a
Subscription entity
    // Start a transaction
    utx.begin();
    // Merge the detached entity back in
    em.merge(subscription);
    // Attempt to remove the subscription
    subscription.getUser().removeSubscription(subscription);
    // Remove the subscription from the database too
    em.remove(subscription);
    // Complete the transaction
    utx.commit();

However, I get an exception from TopLink Essentials that looks like this:

java.lang.NullPointerException
        at
oracle.toplink.essentials.internal.indirection.UnitOfWorkValueHolder.instantiate(UnitOfWorkValueHolder.java:217)
        at
oracle.toplink.essentials.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:82)
        at
oracle.toplink.essentials.indirection.IndirectList.buildDelegate(IndirectList.java:193)
        at
oracle.toplink.essentials.indirection.IndirectList.getDelegate(IndirectList.java:315)
        at
oracle.toplink.essentials.indirection.IndirectList.contains(IndirectList.java:249)
        at myjpaexample.User.removeSubscription(User.java:99)


where line 99 in User is the line inside removeSubscription() that calls
"subscriptions.contains()". Various attempts to remove the subscription
from the list by other means all seem to end up with an NPE at the same
place.

Any ideas?

Craig McClanahan