0
votes

I essentially have a ticketing system where a ticket has a number which is stored with data about a user who registered it. The ticket number set is large, but not unique so I need to prevent data overwrites if two identical ticket numbers are sent to the datastore close enough in time that they could collide. Is this possible using GAE JPA? An example:

@Entity(name = "Ticket")
public class Ticket {
    @Id
    private String id;
    private String kisokId;
}


public class TicketActivationServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException , ServletException{
        Ticket ticket = new Ticket();
        ticket.setTicketId(req.getParameter("ticketId"));
        ticket.setKioskId(req.getParameter("kisokId"));

        EntityManager em = null;
        try{
            em = EMF.get().createEntityManager();
            //can I first check for the existence of this ticket
            Ticket persistedTicket = em.find(Ticket.class, ticketId);
            if(persistedTicket != null)
                //now what? Can't make any assumption this won't change before the next call.

            //then can I lock out other persist calls to the same ticket before persisting this object?
            em.persist(ticket);
        }
        finally{
            if(em != null)
                em.close();
        }
    }
}

Now if two calls come to the servlet at nearly the same time

http://localhost:8888//ticketactivation?ticketId=12345&kioskId=1

http://localhost:8888//ticketactivation?ticketId=12345&kioskId=2

I need to respond with success for the first and respond with a rejection of the last one. Is this possible in this scheme?

1

1 Answers

1
votes

Add a version number to your ticket and do your updates in a transaction.

in the transaction {

  • Read the version number of the existing ticket in the datastore
  • update the ticket you want to save with (version + 1)
  • overwrite ticket in datastore

}

If the ticket you read was updated during your transaction, then the transaction will rollback automatically because it has a collision.

on side note : switch to objectify instead of JPA, your life will be better.