diff --git a/src/main/java/org/olat/core/logging/activity/CourseLoggingAction.java b/src/main/java/org/olat/core/logging/activity/CourseLoggingAction.java index 36d874cd8d83e2c7a4f5ab3541bbaf04d70d86fa..c6f625a2784cc7228693a020126489ee691620c7 100644 --- a/src/main/java/org/olat/core/logging/activity/CourseLoggingAction.java +++ b/src/main/java/org/olat/core/logging/activity/CourseLoggingAction.java @@ -59,10 +59,6 @@ public class CourseLoggingAction extends BaseLoggingAction { public static final ILoggingAction ST_GOTO_NODE = new CourseLoggingAction(ActionType.statistic, CrudAction.retrieve, ActionVerb.open, ActionObject.gotonode).setTypeList( new ResourceableTypeList().addMandatory(OlatResourceableType.course, OlatResourceableType.node, StringResourceableType.nodeId). - // the following has been seen here: - /* - * 2010-02-26 00:03:36,515 [TP-Processor754] WARN UserActivityLoggerImpl - OLAT::WARN ^%^ N2-W40796 ^%^ org.olat.core.logging.activity ^%^ vjetel ^%^ 85.2.180.155 ^%^ https://www.olat.uzh.ch/olat/auth/1%3A1%3A0%3A0%3A0/ ^%^ Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6.4) ^%^ LoggingAction reported an inconsistency: action=org.olat.core.logging.activity.CourseLoggingAction@79888465, fieldId=null, expected: [Mandatory are course,node,nodeId. ], actual: [LoggingResourceables: 5, LoggingResourceInfo[type=CourseModule,rtype=genRepoEntry,id=80997996474040,name=Krier: Einführung in die Literaturwissenschaft FS 2010], LoggingResourceInfo[type=st,rtype=node,id=81053185492848,name=Sitzung II], LoggingResourceInfo[type=BusinessGroup,rtype=businessGroup,id=1975255068,name=Krier Einführungsseminar Lit.wiss.], LoggingResourceInfo[type=CourseModule,rtype=course,id=80997996474040,name=Krier: Einführung in die Literaturwissenschaft FS 2010], LoggingResourceInfo[type=nodeId,rtype=nodeId,id=81053185557462,name=//Lotman_Zeichen.pdf]] ^%^ >>>stack of 1.cause::java.lang.Exception: OLAT-4653 -> at org.olat.core.logging.activity.UserActivityLoggerImpl.log(UserActivityLoggerImpl.java:578) at org.olat.core.logging.activity.ThreadLocalUserActivityLogger.log(ThreadLocalUserActivityLogger.java:137) at org.olat.course.nodes.st.STCourseNodeRunController.event(STCourseNodeRunController.java:192) at org.olat.core.gui.control.DefaultController$1.run(DefaultController.java:247) at org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller.runWithUserActivityLogger(ThreadLocalUserActivityLoggerInstaller.java:84) at org.olat.core.gui.control.DefaultController.dispatchEvent(DefaultController.java:244) at org.olat.core.gui.control.DefaultController.fireEvent(DefaultController.java:182) at org.olat.course.nodes.st.PeekViewWrapperController.event(PeekViewWrapperController.java:115) at org.olat.core.gui.control.DefaultController$1.run(DefaultController.java:247) at org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller.runWithUserActivityLogger(ThreadLocalUserActivityLoggerInstaller.java:84) at org.olat.core.gui.control.DefaultController.dispatchEvent(DefaultController.java:244) - */ or().addMandatory(OlatResourceableType.genRepoEntry,OlatResourceableType.node,OlatResourceableType.businessGroup,OlatResourceableType.course,StringResourceableType.nodeId)); public static final ILoggingAction FILE_UPLOADED = diff --git a/src/main/java/org/olat/portfolio/manager/EPXStreamHandler.java b/src/main/java/org/olat/portfolio/manager/EPXStreamHandler.java index 4d143c40f12fe5fd007bcb246823c2218660a395..7a0c4647cd9fe1e1decb6ec02eec3358d9e3099e 100644 --- a/src/main/java/org/olat/portfolio/manager/EPXStreamHandler.java +++ b/src/main/java/org/olat/portfolio/manager/EPXStreamHandler.java @@ -54,6 +54,7 @@ import org.olat.portfolio.model.structel.EPStructureToStructureLink; import org.olat.portfolio.model.structel.EPStructuredMap; import org.olat.portfolio.model.structel.EPStructuredMapTemplate; import org.olat.portfolio.model.structel.PortfolioStructure; +import org.olat.resource.OLATResourceImpl; import com.thoughtworks.xstream.XStream; @@ -79,6 +80,8 @@ public class EPXStreamHandler { myStream.alias("structureToArtefact", EPStructureToArtefactLink.class); myStream.alias("structureToStructure", EPStructureToStructureLink.class); myStream.alias("collectionRestriction", CollectRestriction.class); + myStream.alias("olatResource", OLATResourceImpl.class); + myStream.alias("OLATResource", OLATResourceImpl.class); myStream.omitField(EPAbstractMap.class, "ownerGroup"); // see also OLAT-6344 myStream.omitField(EPAbstractMap.class, "groups"); // see also OLAT-6344 diff --git a/src/test/java/org/olat/core/util/mail/manager/MailManagerTest.java b/src/test/java/org/olat/core/util/mail/manager/MailManagerTest.java index 3b7a94aaf85b83ed6db11bea4bd33b453259fff8..3ec0bd08079d91bfd65e723d7b09761d7e4867ab 100644 --- a/src/test/java/org/olat/core/util/mail/manager/MailManagerTest.java +++ b/src/test/java/org/olat/core/util/mail/manager/MailManagerTest.java @@ -19,15 +19,24 @@ */ package org.olat.core.util.mail.manager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; -import org.junit.Assert; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.MailBoxExtension; import org.olat.core.util.mail.MailBundle; @@ -46,6 +55,7 @@ import org.springframework.beans.factory.annotation.Autowired; * */ public class MailManagerTest extends OlatTestCase { + private static final OLog log = Tracing.createLoggerFor(MailManagerTest.class); @Autowired private MailManager mailManager; @@ -326,5 +336,78 @@ public class MailManagerTest extends OlatTestCase { Assert.assertTrue(deletedMails.isEmpty()); } - + @Test + public void testParalellSubscribers() { + final int NUM_OF_THREADS = 10; + final int NUM_OF_USERS = 10; + final int NUM_OF_REDONDANCY = 50; + + List<Identity> identities = new ArrayList<>(); + for(int i=0; i<NUM_OF_USERS; i++) { + Identity id = JunitTestHelper.createAndPersistIdentityAsUser("fci-" + i + "-" + UUID.randomUUID()); + for(int j=0; j<NUM_OF_REDONDANCY; j++) { + identities.add(id); + } + } + + final CountDownLatch finishCount = new CountDownLatch(NUM_OF_THREADS); + List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1)); + List<Boolean> statusList = Collections.synchronizedList(new ArrayList<Boolean>(1)); + List<SubscribeThread> threads = new ArrayList<SubscribeThread>(); + for(int i=0; i<NUM_OF_THREADS; i++) { + List<Identity> ids = new ArrayList<>(identities); + SubscribeThread thread = new SubscribeThread(ids, exceptionHolder, statusList, finishCount); + threads.add(thread); + } + + for(SubscribeThread thread:threads) { + thread.start(); + } + + // sleep until threads should have terminated/excepted + try { + finishCount.await(120, TimeUnit.SECONDS); + } catch (InterruptedException e) { + log.error("", e); + Assert.fail(); + } + + assertTrue("It throws an exception in test", exceptionHolder.isEmpty()); + assertEquals("Thread(s) did not finish", NUM_OF_THREADS, statusList.size()); + } + + private class SubscribeThread extends Thread { + + private final List<Identity> ids; + private final List<Exception> exceptionHolder; + private final List<Boolean> statusList; + private final CountDownLatch countDown; + + public SubscribeThread(List<Identity> ids, List<Exception> exceptionHolder, List<Boolean> statusList, CountDownLatch countDown) { + this.ids = ids; + this.exceptionHolder = exceptionHolder; + this.statusList = statusList; + this.countDown = countDown; + } + + @Override + public void run() { + try { + Thread.sleep(10); + for(int i=5; i-->0; ) { + for(Identity id:ids) { + mailManager.subscribe(id); + } + } + statusList.add(Boolean.TRUE); + } catch (Exception ex) { + ex.printStackTrace(); + log.error("", ex); + exceptionHolder.add(ex);// no exception should happen + } finally { + countDown.countDown(); + dbInstance.closeSession(); + } + } + } }