diff --git a/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java b/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java index 754f1016fb..1933b0c9d4 100644 --- a/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java +++ b/source/java/org/alfresco/web/bean/dialog/BaseDialogBean.java @@ -40,6 +40,7 @@ import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.transaction.TransactionService; import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; import org.alfresco.web.app.context.UIContextService; @@ -64,6 +65,7 @@ public abstract class BaseDialogBean implements IDialogBean, Serializable protected BrowseBean browseBean; protected NavigationBean navigator; + transient private TransactionService transactionService; transient private NodeService nodeService; transient private FileFolderService fileFolderService; transient private SearchService searchService; @@ -248,6 +250,15 @@ public abstract class BaseDialogBean implements IDialogBean, Serializable this.navigator = navigator; } + protected TransactionService getTransactionService() + { + if (this.transactionService == null) + { + this.transactionService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getTransactionService(); + } + return this.transactionService; + } + /** * @param nodeService The nodeService to set. */ diff --git a/source/java/org/alfresco/web/bean/forums/CreateDiscussionDialog.java b/source/java/org/alfresco/web/bean/forums/CreateDiscussionDialog.java index 0c1b01954f..eb1e39c61e 100644 --- a/source/java/org/alfresco/web/bean/forums/CreateDiscussionDialog.java +++ b/source/java/org/alfresco/web/bean/forums/CreateDiscussionDialog.java @@ -24,26 +24,23 @@ */ package org.alfresco.web.bean.forums; -import java.io.Serializable; import java.text.MessageFormat; -import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.faces.context.FacesContext; -import javax.transaction.UserTransaction; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ApplicationModel; -import org.alfresco.model.ContentModel; import org.alfresco.model.ForumModel; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.ReportedException; import org.alfresco.web.ui.common.Utils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -103,67 +100,142 @@ public class CreateDiscussionDialog extends CreateTopicDialog * * @param id The id of the node to discuss */ - protected void createTopic(String id) + protected void createTopic(final String id) { - FacesContext context = FacesContext.getCurrentInstance(); - UserTransaction tx = null; - NodeRef forumNodeRef = null; + RetryingTransactionCallback createTopicCallback = new RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + NodeRef forumNodeRef = null; + discussingNodeRef = new NodeRef(Repository.getStoreRef(), id); + + if (getNodeService().hasAspect(discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE)) + { + throw new AlfrescoRuntimeException("createDiscussion called for an object that already has a discussion!"); + } + + // Add the discussable aspect + getNodeService().addAspect(discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE, null); + // The discussion aspect create the necessary child + List destChildren = getNodeService().getChildAssocs( + discussingNodeRef, + ForumModel.ASSOC_DISCUSSION, + RegexQNamePattern.MATCH_ALL); + // Take the first one + if (destChildren.size() == 0) + { + // Drop the aspect and recreate it. This should not happen, but just in case ... + getNodeService().removeAspect(discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE); + getNodeService().addAspect(discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE, null); + // The discussion aspect create the necessary child + destChildren = getNodeService().getChildAssocs( + discussingNodeRef, + ForumModel.ASSOC_DISCUSSION, + RegexQNamePattern.MATCH_ALL); + } + if (destChildren.size() == 0) + { + throw new AlfrescoRuntimeException("The discussable aspect behaviour is not creating a topic"); + } + else + { + // We just take the first one + ChildAssociationRef discussionAssoc = destChildren.get(0); + forumNodeRef = discussionAssoc.getChildRef(); + } + + if (logger.isDebugEnabled()) + logger.debug("created forum for content: " + discussingNodeRef.toString()); + + return forumNodeRef; + } + }; + FacesContext context = FacesContext.getCurrentInstance(); + NodeRef forumNodeRef = null; try { - tx = Repository.getUserTransaction(context); - tx.begin(); - - this.discussingNodeRef = new NodeRef(Repository.getStoreRef(), id); - - if (this.getNodeService().hasAspect(this.discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE)) - { - throw new AlfrescoRuntimeException("createDiscussion called for an object that already has a discussion!"); - } - - // add the discussable aspect - this.getNodeService().addAspect(this.discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE, null); - - // create a child forum space using the child association just introduced by - // adding the discussable aspect - String name = (String)this.getNodeService().getProperty(this.discussingNodeRef, - ContentModel.PROP_NAME); - String msg = Application.getMessage(FacesContext.getCurrentInstance(), "discussion_for"); - String forumName = MessageFormat.format(msg, new Object[] {name}); - - Map forumProps = new HashMap(1); - forumProps.put(ContentModel.PROP_NAME, forumName); - ChildAssociationRef childRef = this.getNodeService().createNode(this.discussingNodeRef, - ForumModel.ASSOC_DISCUSSION, - QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "discussion"), - ForumModel.TYPE_FORUM, forumProps); - - forumNodeRef = childRef.getChildRef(); - - // apply the uifacets aspect - Map uiFacetsProps = new HashMap(5); - uiFacetsProps.put(ApplicationModel.PROP_ICON, "forum"); - this.getNodeService().addAspect(forumNodeRef, ApplicationModel.ASPECT_UIFACETS, uiFacetsProps); - - if (logger.isDebugEnabled()) - logger.debug("created forum for content: " + this.discussingNodeRef.toString()); - - // commit the transaction - tx.commit(); + forumNodeRef = getTransactionService().getRetryingTransactionHelper().doInTransaction( + createTopicCallback, false); } catch (Throwable e) { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} Utils.addErrorMessage(MessageFormat.format(Application.getMessage( context, Repository.ERROR_GENERIC), e.getMessage()), e); + ReportedException.throwIfNecessary(e); } - // finally setup the context for the forum we just created if (forumNodeRef != null) { this.browseBean.clickSpace(forumNodeRef); } +// +// try +// { +// tx = Repository.getUserTransaction(context); +// tx.begin(); +// +// this.discussingNodeRef = new NodeRef(Repository.getStoreRef(), id); +// +// if (this.getNodeService().hasAspect(this.discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE)) +// { +// throw new AlfrescoRuntimeException("createDiscussion called for an object that already has a discussion!"); +// } +// +// // Add the discussable aspect +// this.getNodeService().addAspect(this.discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE, null); +// // The discussion aspect create the necessary child +// List destChildren = this.getNodeService().getChildAssocs( +// this.discussingNodeRef, +// ForumModel.ASSOC_DISCUSSION, +// RegexQNamePattern.MATCH_ALL); +// // Take the first one +// if (destChildren.size() == 0) +// { +// // Drop the aspect and recreate it. This should not happen, but just in case ... +// this.getNodeService().removeAspect(this.discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE); +// } +// else +// { +// ChildAssociationRef discussionAssoc = destChildren.get(0); +// forumNodeRef = discussionAssoc.getChildRef(); +// } +// +//// // create a child forum space using the child association just introduced by +//// // adding the discussable aspect +//// String name = (String)this.getNodeService().getProperty(this.discussingNodeRef, +//// ContentModel.PROP_NAME); +//// String msg = Application.getMessage(FacesContext.getCurrentInstance(), "discussion_for"); +//// String forumName = MessageFormat.format(msg, new Object[] {name}); +//// +//// Map forumProps = new HashMap(1); +//// forumProps.put(ContentModel.PROP_NAME, forumName); +//// ChildAssociationRef childRef = this.getNodeService().createNode(this.discussingNodeRef, +//// ForumModel.ASSOC_DISCUSSION, +//// QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "discussion"), +//// ForumModel.TYPE_FORUM, forumProps); +//// +//// forumNodeRef = childRef.getChildRef(); +//// +// // apply the uifacets aspect +// Map uiFacetsProps = new HashMap(5); +// uiFacetsProps.put(ApplicationModel.PROP_ICON, "forum"); +// this.getNodeService().addAspect(forumNodeRef, ApplicationModel.ASPECT_UIFACETS, uiFacetsProps); +// +// if (logger.isDebugEnabled()) +// logger.debug("created forum for content: " + this.discussingNodeRef.toString()); +// +// // commit the transaction +// tx.commit(); +// } +// catch (Throwable e) +// { +// // rollback the transaction +// try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} +// Utils.addErrorMessage(MessageFormat.format(Application.getMessage( +// context, Repository.ERROR_GENERIC), e.getMessage()), e); +// } +// } /** @@ -171,35 +243,32 @@ public class CreateDiscussionDialog extends CreateTopicDialog */ protected void deleteTopic() { + RetryingTransactionCallback deleteTopicCallback = new RetryingTransactionCallback() + { + public Object execute() throws Throwable + { + // remove this node from the breadcrumb if required + Node forumNode = navigator.getCurrentNode(); + browseBean.removeSpaceFromBreadcrumb(forumNode); + + // remove the discussable aspect from the node we were going to discuss! + // AWC-1519: removing the aspect that defines the child association now does the + // cascade delete so we no longer have to delete the child explicitly + getNodeService().removeAspect(discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE); + // Done + return null; + } + }; FacesContext context = FacesContext.getCurrentInstance(); - UserTransaction tx = null; - try { - tx = Repository.getUserTransaction(context); - tx.begin(); - - // remove this node from the breadcrumb if required - Node forumNode = this.navigator.getCurrentNode(); - this.browseBean.removeSpaceFromBreadcrumb(forumNode); - - // remove the discussable aspect from the node we were going to discuss! - // AWC-1519: removing the aspect that defines the child association now does the - // cascade delete so we no longer have to delete the child explicitly - this.getNodeService().removeAspect(this.discussingNodeRef, ForumModel.ASPECT_DISCUSSABLE); - - // commit the transaction - tx.commit(); - - // clear action context - this.browseBean.setActionSpace(null); + getTransactionService().getRetryingTransactionHelper().doInTransaction(deleteTopicCallback, false); } catch (Throwable e) { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} Utils.addErrorMessage(MessageFormat.format(Application.getMessage( context, Repository.ERROR_GENERIC), e.getMessage()), e); + ReportedException.throwIfNecessary(e); } } }