Author: norman
Date: Fri Apr 30 13:36:21 2010
New Revision: 939668
URL: http://svn.apache.org/viewvc?rev=939668&view=rev
Log:
Fix duplicated primary key problem on heavy load and add a unit test case
(IMAP-137)
Added:
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java
Removed:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/openjpa/
Modified:
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPATransactionalMapper.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailbox.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/user/JPASubscriptionMapper.java
Modified:
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java
(original)
+++
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java
Fri Apr 30 13:36:21 2010
@@ -30,7 +30,6 @@ import org.apache.james.imap.encode.main
import org.apache.james.imap.functional.ImapHostSystem;
import org.apache.james.imap.functional.InMemoryUserManager;
import org.apache.james.imap.jpa.JPASubscriptionManager;
-import org.apache.james.imap.jpa.MailboxSessionEntityManagerFactory;
import org.apache.james.imap.jpa.openjpa.OpenJPAMailboxManager;
import org.apache.james.imap.mailbox.MailboxSession;
import org.apache.james.imap.main.DefaultImapDecoderFactory;
@@ -66,15 +65,9 @@ public class JPAHostSystem extends ImapH
"org.apache.james.imap.jpa.mail.model.JPAMessage;" +
"org.apache.james.imap.jpa.mail.model.JPAProperty;" +
"org.apache.james.imap.jpa.user.model.JPASubscription)");
- // persimistic locking..
- properties.put("openjpa.LockManager", "pessimistic");
- properties.put("openjpa.ReadLockLevel", "read");
- properties.put("openjpa.WriteLockLevel", "write");
- properties.put("openjpa.jdbc.TransactionIsolation", "repeatable-read");
userManager = new InMemoryUserManager();
entityManagerFactory =
OpenJPAPersistence.getEntityManagerFactory(properties);
- MailboxSessionEntityManagerFactory factory = new
MailboxSessionEntityManagerFactory(entityManagerFactory);
- mailboxManager = new OpenJPAMailboxManager(userManager, new
JPASubscriptionManager(factory), factory);
+ mailboxManager = new OpenJPAMailboxManager(userManager, new
JPASubscriptionManager(entityManagerFactory), entityManagerFactory);
final DefaultImapProcessorFactory defaultImapProcessorFactory = new
DefaultImapProcessorFactory();
resetUserMetaData();
Added:
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java?rev=939668&view=auto
==============================================================================
---
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java
(added)
+++
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java
Fri Apr 30 13:36:21 2010
@@ -0,0 +1,144 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+package org.apache.james.imap.functional.jpa;
+
+import java.io.ByteArrayInputStream;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.mail.Flags;
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.commons.logging.impl.SimpleLog;
+import org.apache.james.imap.jpa.JPASubscriptionManager;
+import org.apache.james.imap.jpa.openjpa.OpenJPAMailboxManager;
+import org.apache.james.imap.mailbox.Mailbox;
+import org.apache.james.imap.mailbox.MailboxException;
+import org.apache.james.imap.mailbox.MailboxSession;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JPAStressTest {
+
+
+ private OpenJPAMailboxManager mailboxManager;
+
+
+ @Before
+ public void setUp() {
+ HashMap<String, String> properties = new HashMap<String, String>();
+ properties.put("openjpa.ConnectionDriverName", "org.h2.Driver");
+ properties.put("openjpa.ConnectionURL",
"jdbc:h2:mem:imap;DB_CLOSE_DELAY=-1");
+ properties.put("openjpa.Log", "JDBC=WARN, SQL=WARN, Runtime=WARN");
+ properties.put("openjpa.ConnectionFactoryProperties",
"PrettyPrint=true, PrettyPrintLineLength=72");
+ properties.put("openjpa.jdbc.SynchronizeMappings",
"buildSchema(ForeignKeys=true)");
+ properties.put("openjpa.MetaDataFactory",
"jpa(Types=org.apache.james.imap.jpa.mail.model.JPAHeader;" +
+ "org.apache.james.imap.jpa.mail.model.JPAMailbox;" +
+
"org.apache.james.imap.jpa.mail.model.AbstractJPAMailboxMembership;" +
+ "org.apache.james.imap.jpa.mail.model.JPAMailboxMembership;" +
+ "org.apache.james.imap.jpa.mail.model.AbstractJPAMessage;" +
+ "org.apache.james.imap.jpa.mail.model.JPAMessage;" +
+ "org.apache.james.imap.jpa.mail.model.JPAProperty;" +
+ "org.apache.james.imap.jpa.user.model.JPASubscription)");
+ // persimistic locking..
+ properties.put("openjpa.LockManager", "pessimistic");
+ properties.put("openjpa.ReadLockLevel", "read");
+ properties.put("openjpa.WriteLockLevel", "write");
+ properties.put("openjpa.jdbc.TransactionIsolation", "repeatable-read");
+ EntityManagerFactory entityManagerFactory =
OpenJPAPersistence.getEntityManagerFactory(properties);
+ //MailboxSessionEntityManagerFactory factory = new
MailboxSessionEntityManagerFactory(entityManagerFactory);
+
+ mailboxManager = new OpenJPAMailboxManager(null, new
JPASubscriptionManager(entityManagerFactory), entityManagerFactory);
+ }
+
+ @After
+ public void tearDown() {
+ MailboxSession session = mailboxManager.createSystemSession("test",
new SimpleLog("Test"));
+ try {
+ mailboxManager.deleteEverything(session);
+ } catch (MailboxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ session.close();
+ }
+ /**
+ * Proof of bug https://issues.apache.org/jira/browse/IMAP-137
+ *
+ * @throws InterruptedException
+ * @throws MailboxException
+ */
+ @Test
+ public void testStessTest() throws InterruptedException, MailboxException {
+
+ final CountDownLatch latch = new CountDownLatch(1000);
+ final ExecutorService pool = Executors.newFixedThreadPool(500);
+
+ MailboxSession session = mailboxManager.createSystemSession("test",
new SimpleLog("Test"));
+ mailboxManager.startProcessingRequest(session);
+
mailboxManager.createMailbox(OpenJPAMailboxManager.USER_NAMESPACE_PREFIX
+".INBOX", session);
+ mailboxManager.endProcessingRequest(session);
+ mailboxManager.logout(session, false);
+ final AtomicBoolean fail = new AtomicBoolean(false);
+
+ // fire of 1000 append operations
+ for (int i = 0 ; i < 1000; i++) {
+ pool.execute(new Runnable() {
+
+ public void run() {
+ if (fail.get()){
+ latch.countDown();
+ return;
+ }
+
+ MailboxSession session =
mailboxManager.createSystemSession("test", new SimpleLog("Test"));
+
+ try {
+ mailboxManager.startProcessingRequest(session);
+ Mailbox m =
mailboxManager.getMailbox(OpenJPAMailboxManager.USER_NAMESPACE_PREFIX
+".INBOX", session);
+
+ System.out.println("uid=" + m.appendMessage(new
ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(),
session, false, new Flags()));
+ mailboxManager.endProcessingRequest(session);
+ mailboxManager.logout(session,false);
+ } catch (MailboxException e) {
+ e.printStackTrace();
+ fail.set(true);
+ } finally {
+ latch.countDown();
+ }
+
+
+ }
+ });
+ }
+
+ latch.await();
+
+ org.junit.Assert.assertFalse("Unable to append all
messages",fail.get());
+ pool.shutdown();
+
+
+ }
+}
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
Fri Apr 30 13:36:21 2010
@@ -24,9 +24,7 @@ import java.util.Date;
import java.util.List;
import javax.mail.Flags;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityTransaction;
-import javax.persistence.Query;
+import javax.persistence.EntityManagerFactory;
import org.apache.james.imap.jpa.mail.JPAMailboxMapper;
import org.apache.james.imap.jpa.mail.JPAMessageMapper;
@@ -51,9 +49,9 @@ import org.apache.james.imap.store.mail.
*/
public abstract class JPAMailbox extends StoreMailbox<Long> {
- protected final MailboxSessionEntityManagerFactory entityManagerFactory;
+ protected final EntityManagerFactory entityManagerFactory;
- public JPAMailbox(final MailboxEventDispatcher dispatcher, final
Mailbox<Long> mailbox, final MailboxSessionEntityManagerFactory
entityManagerfactory) {
+ public JPAMailbox(final MailboxEventDispatcher dispatcher, final
Mailbox<Long> mailbox, final EntityManagerFactory entityManagerfactory) {
super(dispatcher, mailbox);
this.entityManagerFactory = entityManagerfactory;
}
@@ -73,10 +71,8 @@ public abstract class JPAMailbox extends
@Override
- protected MessageMapper<Long> createMessageMapper(MailboxSession session) {
- EntityManager manager = entityManagerFactory.getEntityManager(session);
-
- JPAMessageMapper mapper = new JPAMessageMapper(manager,
getMailboxId());
+ protected MessageMapper<Long> createMessageMapper(MailboxSession session)
{
+ JPAMessageMapper mapper = new JPAMessageMapper(entityManagerFactory,
getMailboxId());
return mapper;
}
@@ -105,21 +101,4 @@ public abstract class JPAMailbox extends
final Header header = new JPAHeader(lineNumber, name, value);
return header;
}
-
- /**
- * Reserve next Uid in mailbox and return the mailbox. We use a
transaction here to be sure we don't get any duplicates
- *
- */
- protected Mailbox<Long> reserveNextUid(MailboxSession session) throws
MailboxException {
- EntityManager entityManager =
entityManagerFactory.getEntityManager(session);
-
- EntityTransaction transaction = entityManager.getTransaction();
- transaction.begin();
- Query query =
entityManager.createNamedQuery("findMailboxById").setParameter("idParam",
getMailboxId());
- org.apache.james.imap.jpa.mail.model.JPAMailbox mailbox =
(org.apache.james.imap.jpa.mail.model.JPAMailbox) query.getSingleResult();
- mailbox.consumeUid();
- entityManager.persist(mailbox);
- transaction.commit();
- return mailbox;
- }
}
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java
Fri Apr 30 13:36:21 2010
@@ -19,7 +19,7 @@
package org.apache.james.imap.jpa;
-import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
import org.apache.james.imap.jpa.mail.JPAMailboxMapper;
import org.apache.james.imap.mailbox.MailboxException;
@@ -39,9 +39,9 @@ import org.apache.james.imap.store.trans
*/
public abstract class JPAMailboxManager extends StoreMailboxManager<Long> {
- protected final MailboxSessionEntityManagerFactory entityManagerFactory;
+ protected final EntityManagerFactory entityManagerFactory;
public JPAMailboxManager(final Authenticator authenticator, final
Subscriber subscriber,
- final MailboxSessionEntityManagerFactory entityManagerFactory) {
+ final EntityManagerFactory entityManagerFactory) {
super(authenticator, subscriber);
this.entityManagerFactory = entityManagerFactory;
}
@@ -60,6 +60,12 @@ public abstract class JPAMailboxManager
});
}
+ /**
+ * Delete all mailboxes
+ *
+ * @param maibloxSession
+ * @throws MailboxException
+ */
public void deleteEverything(MailboxSession maibloxSession) throws
MailboxException {
final MailboxMapper<Long> mapper = createMailboxMapper(maibloxSession);
mapper.execute(new TransactionalMapper.Transaction() {
@@ -72,17 +78,10 @@ public abstract class JPAMailboxManager
}
- @Override
- public void endProcessingRequest(MailboxSession session) {
- // close the entityManager after each request so we are sure
everything is flushed
- entityManagerFactory.closeEntityManager(session);
-
- }
@Override
protected MailboxMapper<Long> createMailboxMapper(MailboxSession session) {
- EntityManager manager = entityManagerFactory.getEntityManager(session);
- return new JPAMailboxMapper(manager);
+ return new JPAMailboxMapper(entityManagerFactory);
}
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java
Fri Apr 30 13:36:21 2010
@@ -18,7 +18,7 @@
****************************************************************/
package org.apache.james.imap.jpa;
-import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
import org.apache.james.imap.jpa.user.JPASubscriptionMapper;
import org.apache.james.imap.jpa.user.model.JPASubscription;
@@ -33,9 +33,9 @@ import org.apache.james.imap.store.user.
*
*/
public class JPASubscriptionManager extends StoreSubscriptionManager {
- private final MailboxSessionEntityManagerFactory factory;
+ private final EntityManagerFactory factory;
- public JPASubscriptionManager(final MailboxSessionEntityManagerFactory
factory) {
+ public JPASubscriptionManager(final EntityManagerFactory factory) {
super();
this.factory = factory;
}
@@ -44,10 +44,8 @@ public class JPASubscriptionManager exte
* (non-Javadoc)
* @see
org.apache.james.imap.store.StoreSubscriptionManager#createMapper(org.apache.james.imap.mailbox.MailboxSession)
*/
- protected SubscriptionMapper createMapper(MailboxSession session) {
- EntityManager manager = factory.getEntityManager(session);
-
- JPASubscriptionMapper mapper = new JPASubscriptionMapper(manager);
+ protected SubscriptionMapper createMapper(MailboxSession session) {
+ JPASubscriptionMapper mapper = new JPASubscriptionMapper(factory);
return mapper;
}
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPATransactionalMapper.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPATransactionalMapper.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPATransactionalMapper.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPATransactionalMapper.java
Fri Apr 30 13:36:21 2010
@@ -19,6 +19,7 @@
package org.apache.james.imap.jpa;
import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceException;
@@ -28,17 +29,29 @@ import org.apache.james.imap.mailbox.Sto
import org.apache.james.imap.store.transaction.AbstractTransactionalMapper;
/**
- * JPA implementation of TransactionMapper
+ * JPA implementation of TransactionMapper. This class is not thread-safe!
*
*/
public class JPATransactionalMapper extends AbstractTransactionalMapper {
- protected final EntityManager entityManager;
+ private final EntityManagerFactory factory;
+ private EntityManager entityManager;
- public JPATransactionalMapper(final EntityManager entityManager) {
- this.entityManager = entityManager;
+ public JPATransactionalMapper(final EntityManagerFactory factory) {
+ this.factory = factory;
}
+ /**
+ * Return the currently used {...@link EntityManager}. If the currently
used {...@link EntityManager} is null or is closed a new will get obtained from
the {...@link EntityManagerFactory}
+ *
+ * @return entitymanger
+ */
+ protected EntityManager getManager() {
+ if (entityManager == null || entityManager.isOpen() == false) {
+ entityManager = factory.createEntityManager();
+ }
+ return entityManager;
+ }
/*
* (non-Javadoc)
@@ -46,20 +59,20 @@ public class JPATransactionalMapper exte
*/
protected void begin() throws MailboxException {
try {
- entityManager.getTransaction().begin();
+ getManager().getTransaction().begin();
} catch (PersistenceException e) {
throw new
StorageException(HumanReadableText.START_TRANSACTION_FAILED, e);
}
}
- /*
- * (non-Javadoc)
- * @see
org.apache.james.imap.store.transaction.AbstractTransactionalMapper#commit()
+ /**
+ * Commit the Transaction and close the EntityManager
*/
protected void commit() throws MailboxException {
try {
- entityManager.getTransaction().commit();
+ getManager().getTransaction().commit();
+ getManager().close();
} catch (PersistenceException e) {
throw new
StorageException(HumanReadableText.COMMIT_TRANSACTION_FAILED, e);
}
@@ -73,7 +86,7 @@ public class JPATransactionalMapper exte
EntityTransaction transaction = entityManager.getTransaction();
// check if we have a transaction to rollback
if (transaction.isActive()) {
- entityManager.getTransaction().rollback();
+ getManager().getTransaction().rollback();
}
}
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java
Fri Apr 30 13:36:21 2010
@@ -21,7 +21,7 @@ package org.apache.james.imap.jpa.mail;
import java.util.List;
-import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceException;
@@ -40,8 +40,8 @@ public class JPAMailboxMapper extends JP
private static final char SQL_WILDCARD_CHAR = '%';
- public JPAMailboxMapper(EntityManager entityManager) {
- super(entityManager);
+ public JPAMailboxMapper(EntityManagerFactory factory) {
+ super(factory);
}
/**
@@ -50,7 +50,7 @@ public class JPAMailboxMapper extends JP
public boolean existsMailboxStartingWith(String mailboxName) throws
StorageException {
final String name = mailboxName + SQL_WILDCARD_CHAR;
- final Long numberOfChildMailboxes = (Long)
entityManager.createNamedQuery("countMailboxesWithNameLike").setParameter("nameParam",
name).getSingleResult();
+ final Long numberOfChildMailboxes = (Long)
getManager().createNamedQuery("countMailboxesWithNameLike").setParameter("nameParam",
name).getSingleResult();
return numberOfChildMailboxes != null && numberOfChildMailboxes > 0;
}
@@ -61,7 +61,7 @@ public class JPAMailboxMapper extends JP
*/
public void save(Mailbox<Long> mailbox) throws StorageException {
try {
- entityManager.persist(mailbox);
+ getManager().persist(mailbox);
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.SAVE_FAILED, e);
}
@@ -72,7 +72,7 @@ public class JPAMailboxMapper extends JP
*/
public Mailbox<Long> findMailboxByName(String name) throws
StorageException, MailboxNotFoundException {
try {
- return (JPAMailbox)
entityManager.createNamedQuery("findMailboxByName").setParameter("nameParam",
name).getSingleResult();
+ return (JPAMailbox)
getManager().createNamedQuery("findMailboxByName").setParameter("nameParam",
name).getSingleResult();
} catch (NoResultException e) {
throw new MailboxNotFoundException(name);
@@ -86,7 +86,7 @@ public class JPAMailboxMapper extends JP
*/
public void delete(Mailbox<Long> mailbox) throws StorageException {
try {
- entityManager.remove(mailbox);
+ getManager().remove(mailbox);
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.DELETED_FAILED, e);
}
@@ -98,7 +98,7 @@ public class JPAMailboxMapper extends JP
@SuppressWarnings("unchecked")
public List<Mailbox<Long>> findMailboxWithNameLike(String name) throws
StorageException {
try {
- return
entityManager.createNamedQuery("findMailboxWithNameLike").setParameter("nameParam",
SQL_WILDCARD_CHAR + name + SQL_WILDCARD_CHAR).getResultList();
+ return
getManager().createNamedQuery("findMailboxWithNameLike").setParameter("nameParam",
SQL_WILDCARD_CHAR + name + SQL_WILDCARD_CHAR).getResultList();
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.SEARCH_FAILED, e);
}
@@ -109,7 +109,7 @@ public class JPAMailboxMapper extends JP
*/
public void deleteAll() throws StorageException {
try {
- entityManager.createNamedQuery("deleteAll").executeUpdate();
+ getManager().createNamedQuery("deleteAll").executeUpdate();
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.DELETED_FAILED, e);
}
@@ -120,7 +120,7 @@ public class JPAMailboxMapper extends JP
*/
public long countMailboxesWithName(String name) throws StorageException {
try {
- return (Long)
entityManager.createNamedQuery("countMailboxesWithName").setParameter("nameParam",
name).getSingleResult();
+ return (Long)
getManager().createNamedQuery("countMailboxesWithName").setParameter("nameParam",
name).getSingleResult();
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.COUNT_FAILED, e);
}
@@ -131,7 +131,7 @@ public class JPAMailboxMapper extends JP
*/
public Mailbox<Long> findMailboxById(Long mailboxId) throws
StorageException, MailboxNotFoundException {
try {
- return (JPAMailbox)
entityManager.createNamedQuery("findMailboxById").setParameter("idParam",
mailboxId).getSingleResult();
+ return (JPAMailbox)
getManager().createNamedQuery("findMailboxById").setParameter("idParam",
mailboxId).getSingleResult();
} catch (NoResultException e) {
throw new MailboxNotFoundException(mailboxId);
} catch (PersistenceException e) {
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMessageMapper.java
Fri Apr 30 13:36:21 2010
@@ -20,7 +20,7 @@ package org.apache.james.imap.jpa.mail;
import java.util.List;
-import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
import org.apache.james.imap.api.display.HumanReadableText;
@@ -34,12 +34,17 @@ import org.apache.james.imap.mailbox.Sea
import org.apache.james.imap.store.mail.MessageMapper;
import org.apache.james.imap.store.mail.model.MailboxMembership;
+
+/**
+ * JPA implementation of a {...@link MessageMapper}. This class is not
thread-safe!
+ *
+ */
public class JPAMessageMapper extends JPATransactionalMapper implements
MessageMapper<Long> {
private final long mailboxId;
- public JPAMessageMapper(final EntityManager entityManager, final long
mailboxId) {
- super(entityManager);
+ public JPAMessageMapper(final EntityManagerFactory factory, final long
mailboxId) {
+ super(factory);
this.mailboxId = mailboxId;
}
@@ -75,21 +80,21 @@ public class JPAMessageMapper extends JP
@SuppressWarnings("unchecked")
private List<MailboxMembership<Long>> findMessagesInMailboxAfterUID(long
mailboxId, long uid) {
- return entityManager.createNamedQuery("findMessagesInMailboxAfterUID")
+ return getManager().createNamedQuery("findMessagesInMailboxAfterUID")
.setParameter("idParam", mailboxId)
.setParameter("uidParam", uid).getResultList();
}
@SuppressWarnings("unchecked")
private List<MailboxMembership<Long>> findMessagesInMailboxWithUID(long
mailboxId, long uid) {
- return entityManager.createNamedQuery("findMessagesInMailboxWithUID")
+ return getManager().createNamedQuery("findMessagesInMailboxWithUID")
.setParameter("idParam", mailboxId)
.setParameter("uidParam", uid).getResultList();
}
@SuppressWarnings("unchecked")
private List<MailboxMembership<Long>>
findMessagesInMailboxBetweenUIDs(long mailboxId, long from, long to) {
- return
entityManager.createNamedQuery("findMessagesInMailboxBetweenUIDs")
+ return
getManager().createNamedQuery("findMessagesInMailboxBetweenUIDs")
.setParameter("idParam", mailboxId)
.setParameter("fromParam", from)
.setParameter("toParam", to).getResultList();
@@ -97,7 +102,7 @@ public class JPAMessageMapper extends JP
@SuppressWarnings("unchecked")
private List<MailboxMembership<Long>> findMessagesInMailbox(long
mailboxId) {
- return
entityManager.createNamedQuery("findMessagesInMailbox").setParameter("idParam",
mailboxId).getResultList();
+ return
getManager().createNamedQuery("findMessagesInMailbox").setParameter("idParam",
mailboxId).getResultList();
}
/**
@@ -131,26 +136,26 @@ public class JPAMessageMapper extends JP
@SuppressWarnings("unchecked")
private List<MailboxMembership<Long>> findDeletedMessagesInMailbox(long
mailboxId) {
- return
entityManager.createNamedQuery("findDeletedMessagesInMailbox").setParameter("idParam",
mailboxId).getResultList();
+ return
getManager().createNamedQuery("findDeletedMessagesInMailbox").setParameter("idParam",
mailboxId).getResultList();
}
@SuppressWarnings("unchecked")
private List<MailboxMembership<Long>>
findDeletedMessagesInMailboxAfterUID(long mailboxId, long uid) {
- return
entityManager.createNamedQuery("findDeletedMessagesInMailboxAfterUID")
+ return
getManager().createNamedQuery("findDeletedMessagesInMailboxAfterUID")
.setParameter("idParam", mailboxId)
.setParameter("uidParam", uid).getResultList();
}
@SuppressWarnings("unchecked")
private List<MailboxMembership<Long>>
findDeletedMessagesInMailboxWithUID(long mailboxId, long uid) {
- return
entityManager.createNamedQuery("findDeletedMessagesInMailboxWithUID")
+ return
getManager().createNamedQuery("findDeletedMessagesInMailboxWithUID")
.setParameter("idParam", mailboxId)
.setParameter("uidParam", uid).getResultList();
}
@SuppressWarnings("unchecked")
private List<MailboxMembership<Long>>
findDeletedMessagesInMailboxBetweenUIDs(long mailboxId, long from, long to) {
- return
entityManager.createNamedQuery("findDeletedMessagesInMailboxBetweenUIDs")
+ return
getManager().createNamedQuery("findDeletedMessagesInMailboxBetweenUIDs")
.setParameter("idParam", mailboxId)
.setParameter("fromParam", from)
.setParameter("toParam", to).getResultList();
@@ -161,7 +166,7 @@ public class JPAMessageMapper extends JP
*/
public long countMessagesInMailbox() throws StorageException {
try {
- return (Long)
entityManager.createNamedQuery("countMessagesInMailbox").setParameter("idParam",
mailboxId).getSingleResult();
+ return (Long)
getManager().createNamedQuery("countMessagesInMailbox").setParameter("idParam",
mailboxId).getSingleResult();
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.COUNT_FAILED, e);
}
@@ -172,7 +177,7 @@ public class JPAMessageMapper extends JP
*/
public long countUnseenMessagesInMailbox() throws StorageException {
try {
- return (Long)
entityManager.createNamedQuery("countUnseenMessagesInMailbox").setParameter("idParam",
mailboxId).getSingleResult();
+ return (Long)
getManager().createNamedQuery("countUnseenMessagesInMailbox").setParameter("idParam",
mailboxId).getSingleResult();
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.COUNT_FAILED, e);
}
@@ -185,7 +190,7 @@ public class JPAMessageMapper extends JP
public List<MailboxMembership<Long>> searchMailbox(SearchQuery query)
throws StorageException {
try {
final String jql = formulateJQL(mailboxId, query);
- return entityManager.createQuery(jql).getResultList();
+ return getManager().createQuery(jql).getResultList();
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.SEARCH_FAILED, e);
}
@@ -223,7 +228,7 @@ public class JPAMessageMapper extends JP
*/
public void delete(MailboxMembership<Long> message) throws
StorageException {
try {
- entityManager.remove(message);
+ getManager().remove(message);
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.DELETED_FAILED, e);
}
@@ -236,7 +241,7 @@ public class JPAMessageMapper extends JP
@SuppressWarnings("unchecked")
public List<MailboxMembership<Long>> findUnseenMessagesInMailbox() throws
StorageException {
try {
- return
entityManager.createNamedQuery("findUnseenMessagesInMailboxOrderByUid").setParameter("idParam",
mailboxId).getResultList();
+ return
getManager().createNamedQuery("findUnseenMessagesInMailboxOrderByUid").setParameter("idParam",
mailboxId).getResultList();
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.SEARCH_FAILED, e);
}
@@ -248,7 +253,7 @@ public class JPAMessageMapper extends JP
@SuppressWarnings("unchecked")
public List<MailboxMembership<Long>> findRecentMessagesInMailbox() throws
StorageException {
try {
- return
entityManager.createNamedQuery("findRecentMessagesInMailbox").setParameter("idParam",
mailboxId).getResultList();
+ return
getManager().createNamedQuery("findRecentMessagesInMailbox").setParameter("idParam",
mailboxId).getResultList();
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.SEARCH_FAILED, e);
}
@@ -259,7 +264,7 @@ public class JPAMessageMapper extends JP
*/
public void save(MailboxMembership<Long> message) throws StorageException {
try {
- entityManager.persist(message);
+ getManager().persist(message);
} catch (PersistenceException e) {
throw new StorageException(HumanReadableText.SAVE_FAILED, e);
}
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailbox.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailbox.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailbox.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/model/JPAMailbox.java
Fri Apr 30 13:36:21 2010
@@ -66,7 +66,7 @@ public class JPAMailbox implements Mailb
/** The value for the size field */
@Basic(optional=false) private long size = 0;
-
+
/**
* JPA only
*/
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
Fri Apr 30 13:36:21 2010
@@ -25,10 +25,11 @@ import java.util.Date;
import java.util.List;
import javax.mail.Flags;
-import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.Query;
import org.apache.james.imap.jpa.JPAMailbox;
-import org.apache.james.imap.jpa.MailboxSessionEntityManagerFactory;
import org.apache.james.imap.jpa.mail.JPAMailboxMapper;
import org.apache.james.imap.jpa.mail.model.AbstractJPAMailboxMembership;
import org.apache.james.imap.jpa.mail.model.JPAHeader;
@@ -40,6 +41,8 @@ import org.apache.james.imap.store.mail.
import org.apache.james.imap.store.mail.model.Mailbox;
import org.apache.james.imap.store.mail.model.MailboxMembership;
import org.apache.james.imap.store.mail.model.PropertyBuilder;
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
/**
* OpenJPA implementation of Mailbox
@@ -48,11 +51,11 @@ import org.apache.james.imap.store.mail.
public class OpenJPAMailbox extends JPAMailbox{
private final boolean useStreaming;
- public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long>
mailbox, MailboxSessionEntityManagerFactory entityManagerfactory) {
+ public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long>
mailbox, EntityManagerFactory entityManagerfactory) {
this(dispatcher, mailbox, entityManagerfactory, false);
}
- public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long>
mailbox, MailboxSessionEntityManagerFactory entityManagerfactory, final boolean
useStreaming) {
+ public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long>
mailbox, EntityManagerFactory entityManagerfactory, final boolean useStreaming)
{
super(dispatcher, mailbox, entityManagerfactory);
this.useStreaming = useStreaming;
}
@@ -61,10 +64,8 @@ public class OpenJPAMailbox extends JPAM
* (non-Javadoc)
* @see
org.apache.james.imap.jpa.JPAMailbox#createMailboxMapper(org.apache.james.imap.mailbox.MailboxSession)
*/
- protected JPAMailboxMapper createMailboxMapper(MailboxSession session) {
- EntityManager manager =
entityManagerFactory.getEntityManager(session);
-
- JPAMailboxMapper mapper = new JPAMailboxMapper(manager);
+ protected JPAMailboxMapper createMailboxMapper(MailboxSession session)
{
+ JPAMailboxMapper mapper = new JPAMailboxMapper(entityManagerFactory);
return mapper;
}
@@ -90,5 +91,30 @@ public class OpenJPAMailbox extends JPAM
return super.createMessage(internalDate, uid, size,
bodyStartOctet, document, flags, headers, propertyBuilder);
}
}
+
+ /**
+ * Reserve next Uid in mailbox and return the mailbox. We use a
transaction here to be sure we don't get any duplicates
+ *
+ */
+ protected Mailbox<Long> reserveNextUid(MailboxSession session) throws
MailboxException {
+ OpenJPAEntityManager oem =
OpenJPAPersistence.cast(entityManagerFactory.createEntityManager());
+ boolean optimistic = oem.getOptimistic();
+ try {
+
+ oem.setOptimistic(false);
+ EntityTransaction transaction = oem.getTransaction();
+ transaction.begin();
+ Query query =
oem.createNamedQuery("findMailboxById").setParameter("idParam", getMailboxId());
+ org.apache.james.imap.jpa.mail.model.JPAMailbox mailbox =
(org.apache.james.imap.jpa.mail.model.JPAMailbox) query.getSingleResult();
+ //entityManager.lock(mailbox, LockModeType.READ);
+ mailbox.consumeUid();
+ oem.persist(mailbox);
+ oem.flush();
+ transaction.commit();
+ return mailbox;
+ } finally {
+ oem.setOptimistic(optimistic);
+ }
+ }
}
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java
Fri Apr 30 13:36:21 2010
@@ -19,8 +19,9 @@
package org.apache.james.imap.jpa.openjpa;
+import javax.persistence.EntityManagerFactory;
+
import org.apache.james.imap.jpa.JPAMailboxManager;
-import org.apache.james.imap.jpa.MailboxSessionEntityManagerFactory;
import org.apache.james.imap.mailbox.util.MailboxEventDispatcher;
import org.apache.james.imap.store.Authenticator;
import org.apache.james.imap.store.StoreMailbox;
@@ -35,12 +36,12 @@ public class OpenJPAMailboxManager exten
private boolean useStreaming;
- public OpenJPAMailboxManager(Authenticator authenticator, Subscriber
subscriber, MailboxSessionEntityManagerFactory entityManagerFactory, boolean
useStreaming) {
+ public OpenJPAMailboxManager(Authenticator authenticator, Subscriber
subscriber, EntityManagerFactory entityManagerFactory, boolean useStreaming) {
super(authenticator, subscriber, entityManagerFactory);
this.useStreaming = useStreaming;
}
- public OpenJPAMailboxManager(Authenticator authenticator, Subscriber
subscriber, MailboxSessionEntityManagerFactory entityManagerFactory) {
+ public OpenJPAMailboxManager(Authenticator authenticator, Subscriber
subscriber, EntityManagerFactory entityManagerFactory) {
this(authenticator, subscriber, entityManagerFactory, false);
}
Modified:
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/user/JPASubscriptionMapper.java
URL:
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/user/JPASubscriptionMapper.java?rev=939668&r1=939667&r2=939668&view=diff
==============================================================================
---
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/user/JPASubscriptionMapper.java
(original)
+++
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/user/JPASubscriptionMapper.java
Fri Apr 30 13:36:21 2010
@@ -20,7 +20,7 @@ package org.apache.james.imap.jpa.user;
import java.util.List;
-import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceException;
@@ -31,12 +31,12 @@ import org.apache.james.imap.store.user.
import org.apache.james.imap.store.user.model.Subscription;
/**
- * Maps data access logic to JPA operations.
+ * JPA implementation of a {...@link SubscriptionMapper}. This class is not
thread-safe!
*/
public class JPASubscriptionMapper extends JPATransactionalMapper implements
SubscriptionMapper {
- public JPASubscriptionMapper(final EntityManager entityManager) {
- super(entityManager);
+ public JPASubscriptionMapper(final EntityManagerFactory factory) {
+ super(factory);
}
@@ -46,7 +46,7 @@ public class JPASubscriptionMapper exten
*/
public Subscription findFindMailboxSubscriptionForUser(final String user,
final String mailbox) throws SubscriptionException {
try {
- return (Subscription)
entityManager.createNamedQuery("findFindMailboxSubscriptionForUser")
+ return (Subscription)
getManager().createNamedQuery("findFindMailboxSubscriptionForUser")
.setParameter("userParam", user).setParameter("mailboxParam",
mailbox).getSingleResult();
} catch (NoResultException e) {
return null;
@@ -61,7 +61,7 @@ public class JPASubscriptionMapper exten
*/
public void save(Subscription subscription) throws SubscriptionException {
try {
- entityManager.persist(subscription);
+ getManager().persist(subscription);
} catch (PersistenceException e) {
throw new SubscriptionException(HumanReadableText.SAVE_FAILED, e);
}
@@ -74,7 +74,7 @@ public class JPASubscriptionMapper exten
@SuppressWarnings("unchecked")
public List<Subscription> findSubscriptionsForUser(String user) throws
SubscriptionException {
try {
- return (List<Subscription>)
entityManager.createNamedQuery("findSubscriptionsForUser").setParameter("userParam",
user).getResultList();
+ return (List<Subscription>)
getManager().createNamedQuery("findSubscriptionsForUser").setParameter("userParam",
user).getResultList();
} catch (PersistenceException e) {
throw new SubscriptionException(HumanReadableText.SEARCH_FAILED,
e);
}
@@ -86,7 +86,7 @@ public class JPASubscriptionMapper exten
*/
public void delete(Subscription subscription) throws SubscriptionException
{
try {
- entityManager.remove(subscription);
+ getManager().remove(subscription);
} catch (PersistenceException e) {
throw new SubscriptionException(HumanReadableText.DELETED_FAILED,
e);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]