Warp Persist in a multi threaded environment

58 views
Skip to first unread message

William Chu

unread,
May 20, 2010, 11:25:33 PM5/20/10
to warp...@googlegroups.com, Jason Mirra
Hello,

I'm having problems with warp-persist in a multi-threaded enviroment. I have an application that has a thread pool of 3 threads (thread A, B, C) .

I delete a model from our database in thread A.
I query the database for my model in thread B, C. The model exists and is returned. (It shouldn't exist! It should be deleted)
I query the database for my model in thread A. It doesn't exist and isn't returned.

How do I get warp persist to work in a multi threaded environment where all threads get the same data from the database?

Thanks for the help!
Will

--
You received this message because you are subscribed to the Google Groups "warp-core" group.
To post to this group, send email to warp...@googlegroups.com.
To unsubscribe from this group, send email to warp-core+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/warp-core?hl=en.

Dhanji R. Prasanna

unread,
May 21, 2010, 4:41:51 PM5/21/10
to warp...@googlegroups.com, Jason Mirra
This looks like a problem with the session not being flushed in thread
a, you should close the session after deleting your object or call
session.flush()

Warp persist is not doing anything fancy here, this is just how
hibernate/jpa work. You should investigate further with your jpa
provider on it's particular practices wrt sessions.

Dhanji.

will

unread,
May 21, 2010, 8:29:09 PM5/21/10
to warp-core

Hi Dhanji,

Thanks for the help!

I'm using warp-persist with JPA. How do I get the session?

Will

On May 21, 1:41 pm, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:
> This looks like a problem with the session not being flushed in thread
> a, you should close the session after deleting your object or call
> session.flush()
>
> Warp persist is not doing anything fancy here, this is just how
> hibernate/jpa work. You should investigate further with your jpa
> provider on it's particular practices wrt sessions.
>
> Dhanji.
>
>
>
> On Thursday, May 20, 2010, William Chu <will...@gmail.com> wrote:
> > Hello,
>
> > I'm having problems with warp-persist in a multi-threaded enviroment. I have an application that has a thread pool of 3 threads (thread A, B, C) .
>
> > I delete a model from our database in thread A.
> > I query the database for my model in thread B, C. The model exists and is returned. (It shouldn't exist! It should be deleted)
> > I query the database for my model in thread A. It doesn't exist and isn't returned.
>
> > How do I get warp persist to work in a multi threaded environment where all threads get the same data from the database?
>
> > Thanks for the help!
> > Will
>
> > --
> > You received this message because you are subscribed to the Google Groups "warp-core" group.
> > To post to this group, send email to warp...@googlegroups.com.
> > To unsubscribe from this group, send email to warp-core+...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/warp-core?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "warp-core" group.
> To post to this group, send email to warp...@googlegroups.com.
> To unsubscribe from this group, send email to warp-core+...@googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/warp-core?hl=en.

Dhanji R. Prasanna

unread,
May 21, 2010, 8:37:12 PM5/21/10
to warp...@googlegroups.com
The session is called the EntityManager in JPA. It has a method flush()

Dhanji.

will

unread,
May 21, 2010, 9:01:34 PM5/21/10
to warp-core
When I call em.get.flush()

I get the following exception: Caused by:
javax.persistence.TransactionRequiredException: no transaction is in
progress

Here is my method:

@Transactional
public void hardDelete(T model) {
EntityManager entityManager = em.get();
model = entityManager.merge(model);
entityManager.remove(model);
em.get().flush();
}


I also tried it without the @Transactional notation before the method
and I get the same exception. Any ideas?


I also have the following in my Repository Module: (which I thought
creates a new EntityManager for each transaction which would avoid any
need for session flushing ... or is this unrelated to my problem)

install(PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION).buildModule());
> > warp-core+...@googlegroups.com<warp-core%2Bunsu...@googlegroups.com>
> > .
> > > > For more options, visit this group athttp://
> > groups.google.com/group/warp-core?hl=en.
>
> > > --
> > > You received this message because you are subscribed to the Google Groups
> > "warp-core" group.
> > > To post to this group, send email to warp...@googlegroups.com.
> > > To unsubscribe from this group, send email to
> > warp-core+...@googlegroups.com<warp-core%2Bunsu...@googlegroups.com>
> > .
> > > For more options, visit this group athttp://
> > groups.google.com/group/warp-core?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "warp-core" group.
> > To post to this group, send email to warp...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > warp-core+...@googlegroups.com<warp-core%2Bunsu...@googlegroups.com>
> > .

Dhanji R. Prasanna

unread,
May 21, 2010, 9:12:08 PM5/21/10
to warp...@googlegroups.com
On Fri, May 21, 2010 at 6:01 PM, will <wil...@gmail.com> wrote:
When I call em.get.flush()

I get the following exception: Caused by:
javax.persistence.TransactionRequiredException: no transaction is in
progress

Here is my method:

@Transactional
public void hardDelete(T model) {
               EntityManager entityManager = em.get();
               model = entityManager.merge(model);
               entityManager.remove(model);
               em.get().flush();
}


I also tried it without the @Transactional notation before the method
and I get the same exception. Any ideas?

Looks like the transaction is not running, have you created this class with Guice? One way to check is to set a breakpoint in debug mode inside this method and look in the stack trace for JpaLocalTxnInterceptor. If it is missing then you have a problem with your configuration.

Dhanji.

will

unread,
May 21, 2010, 9:19:46 PM5/21/10
to warp-core
I don't see JpaLocalTxnIntercetpor, but I do see a lot of Guice stuff.
(My interface is called AssetRepository and my implementation is
called AssetRepositoryJPA)

Does the stack trace look incorrect?

AssetRepositoryJPA$$EnhancerByGuice$
$2667b099(Repository<T>).hardDelete(T) line: 57
AssetRepositoryJPA$$EnhancerByGuice$
$2667b099(AssetRepositoryJPA).hardDelete(Asset) line: 36
AssetRepositoryJPA$$EnhancerByGuice$$2667b099.CGLIB$hardDelete
$1(Asset) line: not available
AssetRepositoryJPA$$EnhancerByGuice$$2667b099$$FastClassByGuice$
$5e8b3445.invoke(int, Object, Object[]) line: not available
MethodProxy.invokeSuper(Object, Object[]) line: 228
ProxyFactory$1.intercept(Object, Method, Object[], MethodProxy) line:
53
AssetRepositoryJPA$$EnhancerByGuice$$2667b099.hardDelete(Asset) line:
not available
AssetRepositoryJPA$$EnhancerByGuice$
$2667b099(AssetRepositoryJPA).hardDelete(PersistenceModel) line: 1
AssetRepositoryJPA$$EnhancerByGuice$$2667b099.CGLIB$hardDelete
$0(PersistenceModel) line: not available
AssetRepositoryJPA$$EnhancerByGuice$$2667b099$$FastClassByGuice$
$5e8b3445.invoke(int, Object, Object[]) line: not available
MethodProxy.invokeSuper(Object, Object[]) line: 228
ProxyFactory$1.intercept(Object, Method, Object[], MethodProxy) line:
53
AssetRepositoryJPA$$EnhancerByGuice$
$2667b099.hardDelete(PersistenceModel) line: not available
AssetsController.deleteAsset(Asset) line: 28
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not
available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
ReflectionUtils.call(Method, Object, Object...) line: 201
ReflectionUtils.call(String, Object, Object...) line: 244
ClientConnectionHandler$1.run() line: 123
ThreadPoolExecutor$Worker.runTask(Runnable) line: 886
ThreadPoolExecutor$Worker.run() line: 908
Thread.run() line: 637


On May 21, 6:12 pm, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:

Dhanji R. Prasanna

unread,
May 21, 2010, 9:23:07 PM5/21/10
to warp...@googlegroups.com
No, it definitely looks wrong. Im guessing it's something very simple like you have not installed the PersistenceModule in the correct place. Can you paste your entire injector config?

Dhanji.

Dhanji R. Prasanna

unread,
May 21, 2010, 9:24:03 PM5/21/10
to warp...@googlegroups.com
Or have you imported a different @Transactional (check the imports top of the file, it should be com.wideplay.warp.persist.Transactional)?

will

unread,
May 21, 2010, 9:37:06 PM5/21/10
to warp-core
I have the correct @Transactional annotation. Here is my config:

Also one thing we do a little differently is:

Instead of doing @Inject, we do the following

AMPAssetsAPI assetsAPI =
GrabBag.getGuice().getInstance(AMPAssetsAPI.class);
assetsAPI.deleteAsset(asset);

(GrabBag is a class with some static fields that we use to keep
certain things around such as the Guice Injector)


package server;

import java.util.Properties;

import org.apache.log4j.Logger;

import server.global.repo.AMPDocumentHeaderRepository;
import server.global.repo.AdminRepository;
import server.global.repo.AdvisorRepository;
import server.global.repo.AnalystOpinionCommentRepository;
import server.global.repo.AnalystOpinionRepository;
import server.global.repo.AnalystRepository;
import server.global.repo.AnalystTopicRepository;
import server.global.repo.AssetRepository;
import server.global.repo.CashFlowItemRepository;
import server.global.repo.ClientRepository;
import server.global.repo.CustomWidgetRepository;
import server.global.repo.JobStatusRepository;
import server.global.repo.ReportPageRepository;
import server.global.repo.ReportTemplateRepository;
import server.global.repo.UserRepository;
import server.global.repo.jpa.AMPDocumentHeaderRepositoryJPA;
import server.global.repo.jpa.AdminRepositoryJPA;
import server.global.repo.jpa.AdvisorRepositoryJPA;
import server.global.repo.jpa.AnalystOpinionCommentRepositoryJPA;
import server.global.repo.jpa.AnalystOpinionRepositoryJPA;
import server.global.repo.jpa.AnalystRepositoryJPA;
import server.global.repo.jpa.AnalystTopicRepositoryJPA;
import server.global.repo.jpa.AssetRepositoryJPA;
import server.global.repo.jpa.CashFlowItemRepositoryJPA;
import server.global.repo.jpa.ClientRepositoryJPA;
import server.global.repo.jpa.CustomWidgetRepositoryJPA;
import server.global.repo.jpa.JobStatusRepositoryJPA;
import server.global.repo.jpa.ReportPageRepositoryJPA;
import server.global.repo.jpa.ReportTemplateRepositoryJPA;
import server.global.repo.jpa.UserRepositoryJPA;

import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.Singleton;
import com.web.repository.AnalystInviteRepository;
import com.web.repository.AnalystInviteRepositoryJPA;
import com.wideplay.warp.persist.PersistenceService;
import com.wideplay.warp.persist.UnitOfWork;
import com.wideplay.warp.persist.jpa.JpaUnit;
import common.global.GrabBag;
import common.global.MachinePrefs;

public class RepositoryModule extends AbstractModule {

private static final Logger logger =
Logger.getLogger(RepositoryModule.class);

@Override
protected void configure() {
bind(Key.get(Properties.class,
JpaUnit.class)).toInstance(getHibernateProperties());
bindConstant().annotatedWith(JpaUnit.class).to("AMP_JPA_UNIT");

install(PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION).buildModule());
doBindings();
}

private Properties getHibernateProperties() {

MachinePrefs machinePrefs =
GrabBag.getGuice().getInstance(MachinePrefs.class);

Properties properties = new Properties();

String databaseIP = machinePrefs.get("database_ip",
GrabBag.DATABASE_SERVER_IP);
int databasePort = machinePrefs.getInt("database_port",
GrabBag.DATABASE_SERVER_PORT);

properties.put("hibernate.connection.url", "jdbc:mysql://" +
databaseIP + ":" + databasePort
+ "/amp?
autoReconnect=true&amp;zeroDateTimeBehavior=round&amp;useUnicode=true&amp;characterEncoding=utf-8");

return properties;
}

protected void doBindings() {

bind(AnalystOpinionRepository.class).to(AnalystOpinionRepositoryJPA.class).in(Singleton.class);

bind(AnalystTopicRepository.class).to(AnalystTopicRepositoryJPA.class).in(Singleton.class);

bind(AnalystOpinionCommentRepository.class).to(AnalystOpinionCommentRepositoryJPA.class).in(Singleton.class);


bind(UserRepository.class).to(UserRepositoryJPA.class).in(Singleton.class);

bind(AdvisorRepository.class).to(AdvisorRepositoryJPA.class).in(Singleton.class);

bind(ClientRepository.class).to(ClientRepositoryJPA.class).in(Singleton.class);

bind(AnalystRepository.class).to(AnalystRepositoryJPA.class).in(Singleton.class);


bind(AssetRepository.class).to(AssetRepositoryJPA.class).in(Singleton.class);

bind(ReportTemplateRepository.class).to(ReportTemplateRepositoryJPA.class).in(Singleton.class);

bind(ReportPageRepository.class).to(ReportPageRepositoryJPA.class).in(Singleton.class);

bind(CustomWidgetRepository.class).to(CustomWidgetRepositoryJPA.class).in(Singleton.class);

bind(CashFlowItemRepository.class).to(CashFlowItemRepositoryJPA.class).in(Singleton.class);

bind(JobStatusRepository.class).to(JobStatusRepositoryJPA.class).in(Singleton.class);

bind(AnalystInviteRepository.class).to(AnalystInviteRepositoryJPA.class).in(Singleton.class);

bind(AdminRepository.class).to(AdminRepositoryJPA.class).in(Singleton.class);

bind(AMPDocumentHeaderRepository.class).to(AMPDocumentHeaderRepositoryJPA.class).in(Singleton.class);
bind(Initializer.class).asEagerSingleton();
}

@Singleton
public static class Initializer {
private final PersistenceService service;
private static Initializer instance;

@Inject
Initializer(PersistenceService service) {
instance = this;
this.service = service;

logger.debug("Starting persistance service...");
service.start();
}

public static Initializer getInstance() {
return instance;
}

public void shutdown() {
service.shutdown();
}
}
}


On May 21, 6:24 pm, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:
> Or have you imported a different @Transactional (check the imports top of
> the file, it should be com.wideplay.warp.persist.Transactional)?
>
> On Fri, May 21, 2010 at 6:23 PM, Dhanji R. Prasanna <dha...@gmail.com>wrote:
>
>
>
> > No, it definitely looks wrong. Im guessing it's something very simple like
> > you have not installed the PersistenceModule in the correct place. Can you
> > paste your entire injector config?
>
> > Dhanji.
>
> >> warp-core+...@googlegroups.com<warp-core%2Bunsu...@googlegroups.com>
> >> .
> >> > For more options, visit this group athttp://
> >> groups.google.com/group/warp-core?hl=en.
>
> >> --
> >> You received this message because you are subscribed to the Google Groups
> >> "warp-core" group.
> >> To post to this group, send email to warp...@googlegroups.com.
> >> To unsubscribe from this group, send email to
> >> warp-core+...@googlegroups.com<warp-core%2Bunsu...@googlegroups.com>
> >> .

will

unread,
May 21, 2010, 9:57:55 PM5/21/10
to warp-core
I changed it to @Inject and I'm still getting the same error and exact
same stack trace. Any ideas?
> ...
>
> read more »

Dhanji R. Prasanna

unread,
May 21, 2010, 10:04:05 PM5/21/10
to warp...@googlegroups.com
The interceptor is just not running =(

Try changing this line:

install(PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION).buildModule());

to:

install(PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION)
       .forAll(any(), annotatedWith(Transactional.class))
       .buildModule());

You may also want to try and bind a dummy interceptor of your own that just calls logs something to console so you can debug where this is going wrong (it maybe a Guice issue and not WP).

Dhanji.

will

unread,
May 21, 2010, 10:25:50 PM5/21/10
to warp-core

I'm getting a compile error on the methods any() and
annotatedWith(...)

My class extends com.google.inject.AbstractModule... Any ideas?

install(PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION).forAll(any(),
annotatedWith(Transactional.class)).buildModule());



On May 21, 7:04 pm, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:
> The interceptor is just not running =(
>
> Try changing this line:
>
> install(PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION).buildModule());
>
> to:
>
> install(PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION)
>        .forAll(any(), annotatedWith(Transactional.class))
>        .buildModule());
>
> You may also want to try and bind a dummy interceptor of your own that just
> calls logs something to console so you can debug where this is going wrong
> (it maybe a Guice issue and not WP).
>
> Dhanji.
>

Dhanji R. Prasanna

unread,
May 21, 2010, 11:54:51 PM5/21/10
to warp...@googlegroups.com
You need to import static Matchers. Check out the Guice docs on how to make an interceptor...

Dhanji.

will

unread,
May 24, 2010, 8:29:34 PM5/24/10
to warp-core

I have added a simple interceptor to my module and my methods get
intercepted - I see the logging statements "before" and "after". So my
interceptors are working correctly... Any ideas?


public class ServerModule extends AbstractModule {

@Override
protected void configure() {
AllMethodsInterceptor allMethodsInterceptor = new
AllMethodsInterceptor();
bindInterceptor(Matchers.any(), Matchers.any(),
allMethodsInterceptor);
if (pre) {
preDatabaseLoaded();
} else {
postDatabaseLoaded();
}
}

package com.web;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AllMethodsInterceptor implements MethodInterceptor {

@Override
public Object invoke(MethodInvocation invocation) throws Throwable
{

try {
System.out.println("before");
return invocation.proceed();

} finally {
System.out.println("after");
}

}

}

On May 21, 8:54 pm, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:
> You need to import static Matchers. Check out the Guice docs on how to make
> an interceptor...
>
> Dhanji.
>
Reply all
Reply to author
Forward
0 new messages