Threadsafe persist in multithread environment?
hurzeler Nov 9, 2008 4:52 AMI have a simple multithreaded action on JBoss 4.2.3, JRE 1.6.0_02, Seam 2.1 GA where I would like to harness the database connection pool of the container for performance reasons.
However an exception is thrown at the persist method call. I suspect this is because the EntityManager is not threadsafe.
How would I persist in a threadsafe way?
package com.risk.session; import java.io.IOException; import java.util.Calendar; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.framework.EntityController; import org.jboss.seam.log.Log; import com.risk.entity.TestEvent; @Name("processor") public class Processor extends EntityController { /** * */ private static final long serialVersionUID = -8691085937149866076L; @Logger Log log; @Transactional public void process() throws IOException { log.info("Processing..."); // Spawn threads to optimise the process ExecutorService threadExecutor = Executors.newFixedThreadPool(2); for (int i = 0; i < 2; i++) { threadExecutor.execute(new ProcessThread(i)); } } class ProcessThread implements Runnable { private int threadNo; public ProcessThread(int threadNo) { this.threadNo = threadNo; } // This method is called when the thread runs public void run() { log.info("Thread #0 ...", threadNo); TestEvent event = new TestEvent(); event.setDate(Calendar.getInstance().getTime()); persist(event); } } }
Here is the Entity:
package com.risk.entity; import java.io.Serializable; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import javax.persistence.Table; @Entity @Table(name = "tbl_testevent") public class TestEvent implements Serializable, Idable { /** * */ private static final long serialVersionUID = -7793151651824653553L; // seam-gen attributes (you should probably edit these) private Long id; private Date date; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "testEvent_id_sequence") // name of the generator @SequenceGenerator(name = "testEvent_id_sequence", sequenceName = "TESTEVENT_ID_SEQ") public Long getId() { return id; } public void setId(Long id) { this.id = id; } /** * @return the creationDate */ public Date getDate() { return date; } /** * @param creationDate * the creationDate to set */ public void setDate(Date date) { this.date = date; } }
And the page:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <h:form id="progressForm"> <div class="actionButtons"><h:commandButton value="Process" action="#{processor.process}" /></div> </h:form> </ui:composition>