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>