A multi-tiered application that I am developing accesses its database through a Payara application server. Originally I was using webservices (jax-ws) to provide the access. That decision was prompted by the ease of creating the services by using the @WebService and @Stateless annotations on my entity facade classes.
Due to some limitations of webservices (things like equals and hashCode methods not being created in the webservice interface), I decided to try to use EJB's to accomplish the same functionality. Using the webservices I was able to successfully perform all CRUD functionality on all of the database entities. All of my entity classes extend an AbstractEntity class, which is annotated @MappedSuperClass.
@MappedSuperclass
public abstract class AbstractEntity {
@Column(name = "UUID")
@Basic
private String uuid;
@Version
@Access(AccessType.FIELD)
@Column(name = "Revision")
@Basic
private long revision;
public AbstractEntity() {
uuid = UUID.randomUUID().toString();
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* @return entity's database primary key if persisted
*/
public abstract Long getId();
public long getRevision() {
return revision;
}
public void setRevision(long revision) {
this.revision = revision;
}
/**
* @return true if this entity is persisted to database, false
otherwise.
*/
public boolean isPersisted() {
return getId() != null;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof AbstractEntity) {
return this.uuid.equals(((AbstractEntity) obj).uuid);
}
return false;
}
@Override
public int hashCode() {
return uuid.hashCode();
}
}
The client application correctly looks up the remote interfaces through JNDI, and I'm able to run my methods to query the data and return result lists exactly the same as I can using webservices. The problem, however, is in the version number and uuid that are returned with each entity instance. In all cases, the revision number that is returned is 0, and the revision and uuid don't match the revision and uuid stored in the database. I have verified that the result of my query on the server contains entities that have the correct version numbers, but when the entities get to the client, all of them are set to 0. Of course, if I make any changes to the entity on the client and then try to update the entity, I get an optimistic locking exception on the update method.
Does this have something to do with the entities being detached from the database? The update method is:
@Override
public ShiplistItem updateShipList(ShiplistItem shipitem) {
LOGGER.log(Level.INFO, "Entering updateShipList.");
LOGGER.log(Level.INFO, "shipitem: {0}", shipitem.toString());
if (shipitem.isPersisted()) {
return em.merge(shipitem);
} else {
em.persist(shipitem);
return shipitem;
}
}
I don't understand why the webservice would return the entities correctly, but the ejb seems to neglect the stored values for revision and uuid.
All help is appreciated!!
EDIT - Entity class snippet
public class ShiplistItem extends AbstractEntity implements
Serializable, Comparable<ShiplistItem> {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private Long id;
....
EDIT #2
@Override
public List<ShiplistItem> listShipListByDate(String date) {
Query query = em.createQuery("SELECT s from ShiplistItem s
where s.shipdate = :shipdate", ShiplistItem.class)
.setParameter("shipdate", date);
LOGGER.log(Level.INFO, "SQL: {0}.", query.toString());
List<ShiplistItem> result = new ArrayList<>();
try {
result = (List<ShiplistItem>) query.getResultList();
} catch (Exception ex) {
LOGGER.log(Level.INFO, "No shipping list for date {0}", date);
}
for (ShiplistItem shiplistItem : result) {
LOGGER.log(Level.INFO, "revision: {0}",shiplistItem.getRevision());
}
LOGGER.log(Level.INFO, "shiplist size: {0}", result.size());
return result;
}