Could I have thread safety problems using this aproach? - java

I'm working with EJB/JPA and I've created a static method called createDataset that will lookup for a Dataset object. Each time that I have to insert, update, remove, etc an entity, I retrieve a DatasetObject calling DatasetFactory.createDataset() and I call the appropriate method (insert, update, etc).
The codes:
public class DatasetFactory {
public static Dataset createDataset() {
try {
return (Dataset) new InitialContext().lookup("java:global/.../Dataset");
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
public interface Dataset<T> {
void insert(T entity);
//...
}
#Stateless
#EJB(name = "java:global/.../Dataset", beanInterface = Dataset.class)
public class DatasetBean<T> implements Dataset<T> {
#PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
#Override
public void insert(T entity) {
entityManager.persist(entity);
}
//...
}
Could I have thread safety problems using this aproach? If so, what modifications should I have to do? Should I put the synchronized modifier in the DatasetFactory.createDataset()?
Thanks a lot!

You don't ever have to synchonize any method of an EJB, because the EJB specification specifies that an EJB instance may not be called by two concurrent threads. The EJB container handles the synchonization and thread safety for you. That's one of the points in using EJBs.

From a thread-safety point of view, your code looks good.
But it looks like you are implementing a DAO (Data Access Object) just you are calling your DAO a Dataset instead and it is not a good idea to implement DAOs using EJBs as the EJB container loads and verifies all your EJBs at startup and this can slow things down. And usually EJBs keep only a certain number of EJBs in memory (EJB pool) but if you don't implement your DAOs as EJBs you can create as many of them as you want and Java's GC cleans them up for you.

if your entitymanager is thread-save then there is no risk with using your insert method

Related

JBOSS EAP 6 blocked to call ejb method after asynchronous method

I have a stateless bean that insert some data using asynchronous method of other bean ( local injection). This data insertion takes a time , so I do not wait to finish for this operation. After this data insertion, I am calling another method of same bean. When I put a debug point to method, server waits for approximately 90 seconds to reach this point. May be Jboss waits for transaction to complete for asynchronous method. I do not know what is going on. .
#Stateless
public class SimulationNodePersistenceBean implements SimulationNodePersistenceRemote, SimulationNodePersistenceLocal {
#Resource
SessionContext context;
#EJB
private SimulationResultGraphPersitenceBean graphPersistenceBean;
#Asynchronous
#TransactionAttribute(TransactionAttributeType.REQUIRED)
private void addResultGraphsToDatabase(long id, Graph[] graphList) {
ResultGraph paramGraph;
ResultGraphPoint dataPoint;
Graph graph;
for (int i = 0; i < graphList.length; i++) {
graph = graphList[i];
paramGraph = new ResultGraph();
try {
graphPersistenceBean.persistGraph(paramGraph);
} catch (Exception databaseException) {
// TODO add error message to the contingency simulation messages
// list
logger.error("Error saving ResultGraph:" + paramGraph);
}
}
long duration = System.nanoTime() - startTime;
logger.debug("Graphs inserted to DB in (sec) :" + (duration / NANO_SECOND_CONVERSION_FACTOR));
}
// #Asynchronous
public void persistSimulationResults(long contingencySimulationId, Graph[] graphList,
List<AB> reiList) {
if (graphList != null) {
addResultGraphsToDatabase(contingencySimulationId, graphList);
}
if (reiList != null) {
//another method
}
calculateContSimStability(contingencySimulationId);
}
#Override
public void calculateSimIndex(long id) {
}
This is other bean called from main bean
#Stateless
public class SimulationResultGraphPersitenceBean {
#PersistenceContext(unitName = "DBService")
private EntityManager em;
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
#Asynchronous
public void persistGraph(ResultGraph graph) throws SiGuardPersistenceException {
try {
ResultGraphService service = new ResultGraphService(em);
service.create(graph);
em.flush();
} catch (Exception ex) {
throw new PersistenceException("Error persisting graph", ex);
}
}
This is client calls main bean.This works asynchronously.
getSimulationEJB().persistSimulationResults(id, tsaParser.getLstFile().getGraphArray());
After calling this method, I call another method of SimulationNodePersistenceBean.This method waits for some minutes.
getSimulationEJB().calculateSimIndex(contSimId);
I have created a thread dump using jstack. Actually I do not have this problem in Jboss As 6. I migrated my application to Jboss EAP 6. 4. May be I need to make some configuration changes in configuration. But I do not know what should I do.
I checked thread dump. I did not find any thread in BLOCKING state. Should I look for other keywords?
As I already pointed out in the comments, you are mixing the calling of Asynchronous and Synchronous methods. In your example, you are calling the addResultGraphsToDatabase method (Which is a Asynch method) from persistSimulationResults method (which is a synch method - since you have commented out the asynchronous annotation on top of it). Therefore, right now the addResultGraphsToDatabase method is behaving like a Synchronous method despite the Asynchronous annotation.
I am not sure if you took a look at the link that I posted in the comments but you need to call the Asynch method using the SessionContext. Something like this:
At the class level:
#Inject
SessionContext ctx;
The, within the persistSimulationResults method:
ctx.addResultGraphsToDatabase
For a more detailed example, please take a look at the link I have posted in the comments.

Hibernate session thread safety

I know that sessions are not thread safe. My first question: is it safe to pass an entity to another thread, do some work to it, then pass it back to the original thread and update.
public class Example1 {
MyDao dao;
...
public void doWork() {
MyEntity entity = dao.getEntity();
Runnable job = new Job(entity);
Thread t = new Thread(job);
t.run();
t.join();
dao.merge(entity);
}
}
My second question: is it safe to new up an entity in one thread and save it in another?
public class Example2 {
MyDao dao;
...
public void doWork() {
MyEntity entity = new Entity();
new Thread(new Job(dao, entity)).run();
}
}
public class Job implements Runnable {
private MyDao dao;
private MyEntity entity;
...
#Override
public void run() {
dao.save(entity);
}
}
Edit I forgot to mention that the entities are specifically configured for eager loading
No. The entity is attached to the session and contains proxies linked to the session (in order to lazy-load themselves). Doing that would thus use the session from multiple threads. Since the session is not thread-safe, this is not a good idea.
While the entity is transient (i.e. you've just created it with new), it's not attached to the session, Hibernate doesn't know about it, and the entity is a plain old Java object. So no problem doing that.I don't have all the details of your DAO though. If the method of your DAO is supposed to be invoked as part of an existing transaction, that won't work, since the transaction is tied to the current thread.

No EntityManager bound to this thread JPA

I have a POJO(Myclass in this example) which I persist/update/delete in my app.
I detect changes to that object using a listener class and then in listener class I save the changes to another table.
Here is my class (dummy example) :
EntityListeners({MyListener.class})
class MyClass {
String name;
String surname;
/*...getters...setter..etc */
public void save() {
JPA.em().persist(this);
return this;
}
public void update() {
JPA.em().merge(this);
}
}
class MyListener {
#preUpdate
public void preUpdate() {
/*...some logic to save the changes irrelevant*/
someAuditObj.createWithData(.......);
someAuditObj.save();
}
}
I'm building my web app using play framework v2.1.3, and all this was working great, I was really happy the way it works.
Today I updated play framework to a newer version v2.2.1.
And the for some reason when instance of MyClass changes and the listener picks up the change and it tries to save the changes the transaction fails and I find this in the log :
Caused by: java.lang.RuntimeException: No EntityManager bound to this thread
So it took me a while to figure out that for some reason transaction is not propagated to listener and then I tried something to fix it (Listener class):
#preUpdate
public void preUpdate() {
/*...some logic to save the changes irrelevant*/
JPA.withTransaction(new F.Callback0() {
#Override
public void invoke() throws Throwable {
someAuditObj.createWithData(.......);
someAuditObj.save();
});
}
So this fixes it, and it works like before without issues.
My question(s) is :
Why did it work before without meddling manually with transactions with earlier version of play framework
Is there a better way of achieving the same thing more elegantly (I'm not sure that is the right word for it)?
Update
This is my controller method :
#Transactional
public Result updateName(Long id, String name){
MyClass c = MyClass.findById(id);
c.setName(name);
c.update();
return ok();
}
So transaction should be propagated to all methods right? but why not to listener as well?
My estimate was this :
if a method has #Transactional annotation then all calls that happens inside should be in a transaction?
Seems that you got same problem as mine. Look at my issue: https://github.com/playframework/playframework/issues/2042
Same JPA code works with 2.1.0 but not working with 2.2.1
So i think it's a bug.
Why did it work before without meddling manually with transactions
with earlier version of play framework
Is there a better way of
achieving the same thing more elegantly (I'm not sure that is the
right word for it)?
We have just to wait till this issue will solved or wait some explanation about using threads with JPA transaction from play2 developers in this issue. At this moment issue is open.
In our view, the problem is that JPA.withTransaction() (and #Transactional uses this too) blocks cannot be nested since .withTransaction() unbinds the em unconditionally, and if its an inner .withTransaction(), the outer block will be left without a bound em.
So this test fails at c.save() (save persists the entity in our case)
#Test
public void nestedJPACalls() {
JPATestEntity a = new JPATestEntity();
JPATestEntity b = new JPATestEntity();
JPATestEntity c = new JPATestEntity();
JPA.withTransaction(() -> {
a.save();
JPA.withTransaction(() -> {
b.save();
});
c.save();
});
}
The .withTransaction() methods should check if the em is already bound, and if so, neither bind nor unbind it. I've added that to the discussion at https://github.com/playframework/playframework/issues/2042
We're working on a clean solution now. A temporary but ugly solution is to just try/catch and run your code inside JPA.withTransaction() only if you get the "No EntityManager bound to this thread" exception.
// Create receipt asynch
Akka.future(new Callable() {
public Object call() {
// Issue Receipt
JPA.withTransaction(new F.Callback0() {
#Override
public void invoke() throws Throwable {
// TODO Auto-generated method stub
issueReceipt(pgTxn); // test
}
});
return null;
}
});

DAO pattern multithreading

I work on an multithreading Java application, it is a web server that provide REST services, about 1000 requests per second. I have a relational database, and I use hibernate for accessing it. The database has about 300-400 request per second. I am wondering if DAO pattern is correct, from the multi threading perspective.
So, there is one BaseModel class that looks like this:
public class BaseModelDAO
{
protected Session session;
protected final void commit() {
session.getTransaction().commit();
}
protected final void openSession() {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
}
}
Then I have a DAO class for every table from database:
public class ClientDAOHibernate extends BaseModelDAO implements ClientDAO
{
private Logger log = Logger.getLogger(this.getClass());
#Override
public synchronized void addClient(Client client) throws Exception {
try {
openSession();
session.save(client);
commit();
log.debug("client successfully added into database");
} catch (Exception e) {
log.error("error adding new client into database");
throw new Exception("couldn't add client into database");
} finally {
session.close();
}
}
#Override
public synchronized Client getClient(String username, String password) throws Exception {
Client client = null;
try {
openSession();
client = (Client) session.createCriteria(Client.class).createAlias("user", "UserAlias").add(Restrictions.eq("UserAlias.username", username)).add(Restrictions.eq("UserAlias.password", password)).uniqueResult();
commit();
} catch (Exception e) {
log.error("error updating user into database");
throw new DBUsersGetUserException();
} finally {
session.close();
}
return client;
}
}
Here are my questions:
It is ok to open and close the session for every access to db, taking in consideration the number of concurrent requests?
Now DAO classes are accessed directly from application business logic. Should be used a DAO manager insted? If yes, what should be a good design to implement it?
No, your implementation is not a good one:
transactions should be around business logic, not around data access logic: if you want to transfer money from one account to another, you can't have a transaction for the debit operation, and another transaction for the credit operation. The transaction must cover the whole use-case.
by synchronizing every method of the DAO, you forbid two requests to get a client at the same time. You should not have a session field in your DAO. The session should be a local variable of each method. By doing this, your DAO would become stateless, and thus inherently thread-safe, without any need for synchronization
As Michael says in his comment, using programmatic transactions makes the code verbose, complex, and not focused to the business use-case. Use EJBs or Spring to enjoy declarative transaction management and exception handling.

dao as a member of a servlet - normal?

I guess, DAO is thread safe, does not use any class members.
So can it be used without any problem as a private field of a Servlet ? We need only one copy, and
multiple threads can access it simultaneously, so why bother creating a local variable, right?
"DAO" is just a general term for database abstraction classes. Whether they are threadsafe or not depends on the specific implementation.
This bad example could be called a DAO, but it would get you into trouble if multiple threads call the insert method at the same time.
class MyDAO {
private Connection connection = null;
public boolean insertSomething(Something o) throws Exception {
try {
connection = getConnection()
//do insert on connection.
} finally {
if (connection != null) {
connection.close();
}
}
}
}
So the answer is: if your DAO handles connections and transactions right, it should work.

Categories