diff --git a/src/main/java/org/olat/core/commons/services/pdf/dispatcher/PdfDeliveryDispatcher.java b/src/main/java/org/olat/core/commons/services/pdf/dispatcher/PdfDeliveryDispatcher.java
index 0664b12053fa78c0de7c0696ecab9c2ef6ad6267..8301ddfd6a3a01e7059f9f4f0304830809071538 100644
--- a/src/main/java/org/olat/core/commons/services/pdf/dispatcher/PdfDeliveryDispatcher.java
+++ b/src/main/java/org/olat/core/commons/services/pdf/dispatcher/PdfDeliveryDispatcher.java
@@ -28,6 +28,7 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.commons.services.pdf.PdfModule;
 import org.olat.core.commons.services.pdf.PdfService;
 import org.olat.core.commons.services.pdf.model.PdfDelivery;
@@ -39,7 +40,6 @@ import org.olat.core.gui.components.Window;
 import org.olat.core.gui.control.creator.ControllerCreator;
 import org.olat.core.gui.control.generic.popup.PopupBrowserWindow;
 import org.olat.core.id.Roles;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.FileUtils;
 import org.olat.core.util.UserSession;
@@ -77,32 +77,38 @@ public class PdfDeliveryDispatcher implements Dispatcher {
 			response.sendError(HttpServletResponse.SC_FORBIDDEN);
 			return;
 		}
-		
-		String uriPrefix = DispatcherModule.getLegacyUriPrefix(request);
-		final String origUri = request.getRequestURI();
-		String uuid = origUri.substring(uriPrefix.length());
-		int indexSuffix = uuid.indexOf('/');
-		
-		String key = null;
-		String filename = null;
-		if(indexSuffix > 0) {
-			key = uuid.substring(0, indexSuffix);
-			filename = uuid.substring(indexSuffix + 1);
-		}
-		
-		PdfDelivery delivery = cache.get(key);
-		if(delivery == null) {
-			response.sendError(HttpServletResponse.SC_NOT_FOUND);
-		} else if(delivery.getDirectory() != null) {
-			renderFile(delivery, filename, response);
-		} else if(delivery.getControllerCreator() != null) {
-			renderController(delivery, request, response);
-		} else {
-			response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+
+		try {
+			String uriPrefix = DispatcherModule.getLegacyUriPrefix(request);
+			final String origUri = request.getRequestURI();
+			String uuid = origUri.substring(uriPrefix.length());
+			int indexSuffix = uuid.indexOf('/');
+			
+			String key = null;
+			String filename = null;
+			if(indexSuffix > 0) {
+				key = uuid.substring(0, indexSuffix);
+				filename = uuid.substring(indexSuffix + 1);
+			}
+
+			PdfDelivery delivery = cache.get(key);
+			if(delivery == null) {
+				response.sendError(HttpServletResponse.SC_NOT_FOUND);
+			} else if(origUri.contains("close-window")) {
+				response.setStatus(HttpServletResponse.SC_OK);
+			} else if(delivery.getDirectory() != null) {
+				renderFile(delivery, filename, response);
+			} else if(delivery.getControllerCreator() != null) {
+				renderController(delivery, request, response);
+			} else {
+				response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+			}
+		} catch (IOException e) {
+			log.error("", e);
 		}
 	}
 	
-	private void renderController(PdfDelivery delivery, HttpServletRequest request, HttpServletResponse response) {
+	private synchronized void renderController(PdfDelivery delivery, HttpServletRequest request, HttpServletResponse response) {
 		ControllerCreator creator = delivery.getControllerCreator();
 		UserRequest ureq = new UserRequestImpl("pdfd", request, response);
 		UserSession usess = ureq.getUserSession();
@@ -113,9 +119,16 @@ public class PdfDeliveryDispatcher implements Dispatcher {
 			usess.setRoles(Roles.userRoles());
 		}
 		
-		PopupBrowserWindow pbw = delivery.getWindowControl().getWindowBackOffice()
-				.getWindowManager().createNewPopupBrowserWindowFor(ureq, creator);
-		Window window = pbw.getPopupWindowControl().getWindowBackOffice().getWindow();
+		Window window;
+		if(delivery.getWindow() == null) {
+			PopupBrowserWindow pbw = delivery.getWindowControl().getWindowBackOffice()
+					.getWindowManager().createNewPopupBrowserWindowFor(ureq, creator);
+			window = pbw.getPopupWindowControl().getWindowBackOffice().getWindow();
+			delivery.setWindow(window);
+			delivery.setBrowserWindow(pbw);
+		} else {
+			window = delivery.getWindow();
+		}
 		window.dispatchRequest(ureq, true);
 	}
 	
diff --git a/src/main/java/org/olat/core/commons/services/pdf/manager/AthenaPdfSPI.java b/src/main/java/org/olat/core/commons/services/pdf/manager/AthenaPdfSPI.java
index 24b2fd50293ef37bd61a57a624f1794a262c2c88..909b1e20ff1db4bdb64897e77a709f32cd69c8e1 100644
--- a/src/main/java/org/olat/core/commons/services/pdf/manager/AthenaPdfSPI.java
+++ b/src/main/java/org/olat/core/commons/services/pdf/manager/AthenaPdfSPI.java
@@ -41,6 +41,7 @@ import org.olat.core.commons.services.pdf.ui.AthenaPdfSettingsController;
 import org.olat.core.configuration.AbstractSpringModule;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Disposable;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.creator.ControllerCreator;
 import org.olat.core.helpers.Settings;
@@ -143,6 +144,9 @@ public class AthenaPdfSPI extends AbstractSpringModule implements PdfSPI {
 		cache.put(key, delivery);
 		render(key, "index.html", out);
 		cache.remove(key);
+		if(delivery.getBrowserWindow() instanceof Disposable) {
+			((Disposable)delivery.getBrowserWindow()).dispose();
+		}
 	}
 
 	private void render(String key, String rootFilename, OutputStream out) {
@@ -184,7 +188,7 @@ public class AthenaPdfSPI extends AbstractSpringModule implements PdfSPI {
 			if(response.getStatusLine().getStatusCode() == 200) {
 				copyResponse(response, out);
 			} else {
-				log.error("Cannot renderer PDF: " + response.getStatusLine().getStatusCode());
+				log.error("Cannot renderer PDF: {}", response.getStatusLine().getStatusCode());
 				EntityUtils.consume(response.getEntity());
 			}
 		} catch(IOException e) {
diff --git a/src/main/java/org/olat/core/commons/services/pdf/model/PdfDelivery.java b/src/main/java/org/olat/core/commons/services/pdf/model/PdfDelivery.java
index 6b028050d49b7b896e1a315f43407e86c884326c..3f002124733e6747730dff8f25842f658f07590e 100644
--- a/src/main/java/org/olat/core/commons/services/pdf/model/PdfDelivery.java
+++ b/src/main/java/org/olat/core/commons/services/pdf/model/PdfDelivery.java
@@ -21,8 +21,10 @@ package org.olat.core.commons.services.pdf.model;
 
 import java.io.Serializable;
 
+import org.olat.core.gui.components.Window;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.creator.ControllerCreator;
+import org.olat.core.gui.control.generic.popup.PopupBrowserWindow;
 import org.olat.core.id.Identity;
 
 /**
@@ -37,8 +39,11 @@ public class PdfDelivery implements Serializable {
 	private final String key;
 	private String directory;
 	private Identity identity;
-	private ControllerCreator controllerCreator;
+	
+	private Window window;
 	private WindowControl windowControl;
+	private PopupBrowserWindow browserWindow;
+	private ControllerCreator controllerCreator;
 	
 	public PdfDelivery(String key) {
 		this.key = key;
@@ -64,6 +69,14 @@ public class PdfDelivery implements Serializable {
 		this.identity = identity;
 	}
 
+	public Window getWindow() {
+		return window;
+	}
+
+	public void setWindow(Window window) {
+		this.window = window;
+	}
+
 	public WindowControl getWindowControl() {
 		return windowControl;
 	}
@@ -80,6 +93,14 @@ public class PdfDelivery implements Serializable {
 		this.controllerCreator = controllerCreator;
 	}
 
+	public PopupBrowserWindow getBrowserWindow() {
+		return browserWindow;
+	}
+
+	public void setBrowserWindow(PopupBrowserWindow browserWindow) {
+		this.browserWindow = browserWindow;
+	}
+
 	@Override
 	public int hashCode() {
 		return key.hashCode();
diff --git a/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java b/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java
index 257560519ef8717672f950506d70f07f1c12f3a6..42d888faf5893f7973c2aa78b8686cb6cfa8569c 100644
--- a/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java
+++ b/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java
@@ -180,6 +180,8 @@ public class ImageRunController extends BasicController implements PageRunElemen
 
 	@Override
 	protected void doDispose() {
-		//
+		if(imageCmp != null) {
+			imageCmp.dispose();
+		}
 	}
 }
diff --git a/src/main/java/org/olat/modules/ceditor/ui/PageController.java b/src/main/java/org/olat/modules/ceditor/ui/PageController.java
index 15d202253bc1c7b510f2770ad0823f022887d168..065c30919e6c6f94e343c132206315e0ea69c1b5 100644
--- a/src/main/java/org/olat/modules/ceditor/ui/PageController.java
+++ b/src/main/java/org/olat/modules/ceditor/ui/PageController.java
@@ -72,7 +72,7 @@ public class PageController extends BasicController {
 
 	@Override
 	protected void doDispose() {
-		//
+		fragmentsCmp.dispose();
 	}
 	
 	public boolean validateElements(UserRequest ureq, List<ValidationMessage> messages) {
diff --git a/src/main/java/org/olat/modules/ceditor/ui/PageRunControllerElement.java b/src/main/java/org/olat/modules/ceditor/ui/PageRunControllerElement.java
index 227c4cb5223e689bb8cf81e8626392dbffaf80ab..5f712b52c107c1b8455e30f16e43cd596578909d 100644
--- a/src/main/java/org/olat/modules/ceditor/ui/PageRunControllerElement.java
+++ b/src/main/java/org/olat/modules/ceditor/ui/PageRunControllerElement.java
@@ -24,6 +24,7 @@ import java.util.List;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Disposable;
 import org.olat.modules.ceditor.PageRunElement;
 import org.olat.modules.ceditor.ValidatingController;
 
@@ -33,13 +34,20 @@ import org.olat.modules.ceditor.ValidatingController;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-public class PageRunControllerElement implements PageRunElement {
+public class PageRunControllerElement implements PageRunElement, Disposable {
 	
 	private Controller controller;
 	
 	public PageRunControllerElement(Controller controller) {
 		this.controller = controller;
 	}
+	
+	@Override
+	public void dispose() {
+		if(controller != null) {
+			controller.dispose();
+		}
+	}
 
 	@Override
 	public Component getComponent() {
diff --git a/src/main/java/org/olat/modules/ceditor/ui/component/PageFragmentsComponent.java b/src/main/java/org/olat/modules/ceditor/ui/component/PageFragmentsComponent.java
index 820099af2dd87dc66612f0946737ad0737994f58..0521cb6d5c72cb7041ba19a169cbacfb6bf19d56 100644
--- a/src/main/java/org/olat/modules/ceditor/ui/component/PageFragmentsComponent.java
+++ b/src/main/java/org/olat/modules/ceditor/ui/component/PageFragmentsComponent.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.components.AbstractComponent;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.ComponentCollection;
 import org.olat.core.gui.components.ComponentRenderer;
+import org.olat.core.gui.control.Disposable;
 import org.olat.modules.ceditor.ui.ValidationMessage;
 import org.olat.modules.ceditor.ui.model.PageFragment;
 
@@ -36,7 +37,7 @@ import org.olat.modules.ceditor.ui.model.PageFragment;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-public class PageFragmentsComponent extends AbstractComponent implements ComponentCollection  {
+public class PageFragmentsComponent extends AbstractComponent implements ComponentCollection, Disposable  {
 	
 	private static final PageFragmentsComponentRenderer RENDERER = new PageFragmentsComponentRenderer();
 	
@@ -79,6 +80,19 @@ public class PageFragmentsComponent extends AbstractComponent implements Compone
 		return components;
 	}
 	
+	@Override
+	public void dispose() {
+		List<PageFragment> fragmentList = getFragments();
+		for(PageFragment fragment:fragmentList) {
+			if(fragment.getPageRunElement() instanceof Disposable) {
+				((Disposable)fragment.getPageRunElement()).dispose();
+			}
+			if(fragment.getPageElement() instanceof Disposable) {
+				((Disposable)fragment.getPageElement()).dispose();
+			}
+		}
+	}
+
 	public boolean validateElements(UserRequest ureq, List<ValidationMessage> messages) {
 		boolean allOk = true;
 		List<PageFragment> fragmentList = getFragments();
diff --git a/src/main/java/org/olat/modules/portfolio/ui/media/VideoMediaController.java b/src/main/java/org/olat/modules/portfolio/ui/media/VideoMediaController.java
index a11031dab8cd74389ad80784967c772efba0ebbe..e5a67901f90ffbb75f2af5ec37def263da64d3f2 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/media/VideoMediaController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/media/VideoMediaController.java
@@ -42,6 +42,8 @@ import org.olat.modules.portfolio.ui.MediaMetadataController;
  */
 public class VideoMediaController extends BasicController {
 	
+	private final ImageComponent videoCmp;
+	
 	public VideoMediaController(UserRequest ureq, WindowControl wControl, Media media, MediaRenderingHints hints) {
 		super(ureq, wControl);
 		
@@ -49,7 +51,7 @@ public class VideoMediaController extends BasicController {
 
 		File mediaDir = new File(FolderConfig.getCanonicalRoot(), media.getStoragePath());
 		File mediaFile = new File(mediaDir, media.getRootFilename());
-		ImageComponent videoCmp = new ImageComponent(ureq.getUserSession(), "image");
+		videoCmp = new ImageComponent(ureq.getUserSession(), "image");
 		videoCmp.setMedia(mediaFile);
 		mainVC.put("video", videoCmp);
 		mainVC.contextPut("pdf", hints.isToPdf());
@@ -77,6 +79,6 @@ public class VideoMediaController extends BasicController {
 
 	@Override
 	protected void doDispose() {
-		//
+		videoCmp.dispose();
 	}
 }