mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
MNT-23411 Option to disable events2 (#1703)
* Added configuration to disable events2 so the behaviours are not bootstrapped. Additionally added options to enable/disable on runtime * Added unit test
This commit is contained in:
@@ -169,6 +169,12 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
/** Unregister a {@link FixedAclUpdaterListener} to be notified when a node is updated by an instance of this class. */
|
||||
public static void unregisterListener(FixedAclUpdaterListener listener)
|
||||
{
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
onInheritPermissionsDisabledDelegate = policyComponent
|
||||
|
@@ -31,8 +31,10 @@ import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.alfresco.repo.domain.node.NodeDAO;
|
||||
@@ -54,8 +56,11 @@ import org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnSetNodeTypePolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy;
|
||||
import org.alfresco.repo.policy.Behaviour;
|
||||
import org.alfresco.repo.policy.BehaviourDefinition;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.ServiceBehaviourBinding;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
@@ -103,10 +108,27 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
private ChildAssociationTypeFilter childAssociationTypeFilter;
|
||||
private EventUserFilter userFilter;
|
||||
protected final EventTransactionListener transactionListener = new EventTransactionListener();
|
||||
protected boolean enabled;
|
||||
private Set<Behaviour> behaviours;
|
||||
|
||||
public void setEnabled(boolean enabled)
|
||||
{
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet()
|
||||
{
|
||||
if (!isEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PropertyCheck.mandatory(this, "policyComponent", policyComponent);
|
||||
PropertyCheck.mandatory(this, "nodeService", nodeService);
|
||||
PropertyCheck.mandatory(this, "namespaceService", namespaceService);
|
||||
@@ -126,28 +148,56 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
|
||||
private void bindBehaviours()
|
||||
{
|
||||
policyComponent.bindClassBehaviour(OnCreateNodePolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onCreateNode"));
|
||||
policyComponent.bindClassBehaviour(BeforeDeleteNodePolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||
policyComponent.bindClassBehaviour(OnUpdatePropertiesPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onUpdateProperties"));
|
||||
policyComponent.bindClassBehaviour(OnSetNodeTypePolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onSetNodeType"));
|
||||
policyComponent.bindClassBehaviour(OnAddAspectPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onAddAspect"));
|
||||
policyComponent.bindClassBehaviour(OnRemoveAspectPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onRemoveAspect"));
|
||||
policyComponent.bindClassBehaviour(OnMoveNodePolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onMoveNode"));
|
||||
policyComponent.bindAssociationBehaviour(OnCreateChildAssociationPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onCreateChildAssociation"));
|
||||
policyComponent.bindAssociationBehaviour(BeforeDeleteChildAssociationPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "beforeDeleteChildAssociation"));
|
||||
policyComponent.bindAssociationBehaviour(OnCreateAssociationPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onCreateAssociation"));
|
||||
policyComponent.bindAssociationBehaviour(BeforeDeleteAssociationPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "beforeDeleteAssociation"));
|
||||
setClassBehaviour(OnCreateNodePolicy.QNAME, "onCreateNode");
|
||||
setClassBehaviour(BeforeDeleteNodePolicy.QNAME, "beforeDeleteNode");
|
||||
setClassBehaviour(OnUpdatePropertiesPolicy.QNAME, "onUpdateProperties");
|
||||
setClassBehaviour(OnSetNodeTypePolicy.QNAME, "onSetNodeType");
|
||||
setClassBehaviour(OnAddAspectPolicy.QNAME, "onAddAspect");
|
||||
setClassBehaviour(OnRemoveAspectPolicy.QNAME, "onRemoveAspect");
|
||||
setClassBehaviour(OnMoveNodePolicy.QNAME, "onMoveNode");
|
||||
setAssociationBehaviour(OnCreateChildAssociationPolicy.QNAME, "onCreateChildAssociation");
|
||||
setAssociationBehaviour(BeforeDeleteChildAssociationPolicy.QNAME, "beforeDeleteChildAssociation");
|
||||
setAssociationBehaviour(OnCreateAssociationPolicy.QNAME, "onCreateAssociation");
|
||||
setAssociationBehaviour(BeforeDeleteAssociationPolicy.QNAME, "beforeDeleteAssociation");
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Events2 generated events
|
||||
*/
|
||||
public void disable()
|
||||
{
|
||||
if (!isEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
setEnabled(false);
|
||||
disableBehaviours();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Events2 generated events
|
||||
*/
|
||||
public void enable()
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setEnabled(true);
|
||||
|
||||
if (behaviours == null)
|
||||
{
|
||||
behaviours = new HashSet<Behaviour>();
|
||||
afterPropertiesSet();
|
||||
bindBehaviours();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
enableBehaviours();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setNodeDAO(NodeDAO nodeDAO)
|
||||
@@ -289,6 +339,62 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
return new PeerAssociationEventConsolidator(peerAssociationRef, nodeResourceHelper);
|
||||
}
|
||||
|
||||
private void setClassBehaviour(QName policyQName, String method)
|
||||
{
|
||||
Behaviour behaviour = bindClassBehaviour(policyQName, method);
|
||||
behaviours.add(behaviour);
|
||||
}
|
||||
|
||||
private void setAssociationBehaviour(QName policyQName, String method)
|
||||
{
|
||||
Behaviour behaviour = bindAssociationBehaviour(policyQName, method);
|
||||
behaviours.add(behaviour);
|
||||
}
|
||||
|
||||
protected Behaviour bindClassBehaviour(QName policyQName, String method)
|
||||
{
|
||||
BehaviourDefinition<ServiceBehaviourBinding> behaviourDef = policyComponent.bindClassBehaviour(policyQName, this,
|
||||
new JavaBehaviour(this, method));
|
||||
return behaviourDef.getBehaviour();
|
||||
}
|
||||
|
||||
protected Behaviour bindAssociationBehaviour(QName policyQName, String method)
|
||||
{
|
||||
BehaviourDefinition<ServiceBehaviourBinding> behaviourDef = policyComponent.bindAssociationBehaviour(policyQName, this,
|
||||
new JavaBehaviour(this, method));
|
||||
return behaviourDef.getBehaviour();
|
||||
}
|
||||
|
||||
private void disableBehaviours()
|
||||
{
|
||||
disableBehaviours(behaviours);
|
||||
}
|
||||
|
||||
protected void disableBehaviours(Set<Behaviour> bindedBehaviours)
|
||||
{
|
||||
if (bindedBehaviours != null)
|
||||
{
|
||||
bindedBehaviours.forEach(behaviour -> {
|
||||
behaviour.disable();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void enableBehaviours()
|
||||
{
|
||||
enableBehaviours(behaviours);
|
||||
}
|
||||
|
||||
protected void enableBehaviours(Set<Behaviour> bindedBehaviours)
|
||||
{
|
||||
if (bindedBehaviours != null)
|
||||
{
|
||||
bindedBehaviours.forEach(behaviour -> {
|
||||
behaviour.enable();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link EventConsolidator} for the supplied {@code nodeRef} from
|
||||
* the current transaction context.
|
||||
@@ -396,6 +502,11 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent applicationEvent)
|
||||
{
|
||||
if (!isEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
behaviours = new HashSet<Behaviour>();
|
||||
bindBehaviours();
|
||||
}
|
||||
|
||||
|
@@ -43,6 +43,9 @@
|
||||
<property name="nodeResourceHelper" ref="nodeResourceHelper"/>
|
||||
<property name="eventGeneratorQueue" ref="eventGeneratorQueue"/>
|
||||
<property name="nodeDAO" ref="nodeDAO"/>
|
||||
<property name="enabled">
|
||||
<value>${repo.event2.enabled}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="baseNodeResourceHelper" abstract="true">
|
||||
|
@@ -1219,6 +1219,7 @@ contentPropertyRestrictions.enabled=true
|
||||
contentPropertyRestrictions.whitelist=
|
||||
|
||||
# Repo events2
|
||||
repo.event2.enabled=true
|
||||
# Type and aspect filters which should be excluded
|
||||
# Note: System folders node types are added by default
|
||||
repo.event2.filter.nodeTypes=sys:*, fm:*, cm:thumbnail, cm:failedThumbnail, cm:rating, rma:rmsite include_subtypes
|
||||
|
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.event.v1.model.RepoEvent;
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.command.ActiveMQTextMessage;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class EventGeneratorDisabledTest extends AbstractContextAwareRepoEvent
|
||||
{
|
||||
private static final String EVENT2_TOPIC_NAME = "alfresco.repo.event2";
|
||||
private static final String BROKER_URL = "tcp://localhost:61616";
|
||||
|
||||
@Autowired @Qualifier("event2ObjectMapper")
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
protected ObjectMapper event2ObjectMapper;
|
||||
|
||||
//private EventGenerator eventGenerator;
|
||||
|
||||
private ActiveMQConnection connection;
|
||||
protected List<RepoEvent<?>> receivedEvents;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception
|
||||
{
|
||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
|
||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createTopic(EVENT2_TOPIC_NAME);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
receivedEvents = Collections.synchronizedList(new LinkedList<>());
|
||||
consumer.setMessageListener(new MessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onMessage(Message message)
|
||||
{
|
||||
String text = getText(message);
|
||||
RepoEvent<?> event = toRepoEvent(text);
|
||||
receivedEvents.add(event);
|
||||
}
|
||||
|
||||
private RepoEvent<?> toRepoEvent(String json)
|
||||
{
|
||||
try
|
||||
{
|
||||
return objectMapper.readValue(json, RepoEvent.class);
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdownTopicListener() throws Exception
|
||||
{
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotReceiveEvent2EventsOnNodeCreation() throws Exception
|
||||
{
|
||||
if (eventGenerator.isEnabled())
|
||||
{
|
||||
eventGenerator.disable();
|
||||
}
|
||||
|
||||
createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
Awaitility.await().pollDelay(6, TimeUnit.SECONDS).until(() -> receivedEvents.size() == 0);
|
||||
|
||||
assertTrue(EVENT_CONTAINER.getEvents().size() == 0);
|
||||
assertTrue(receivedEvents.size() == 0);
|
||||
|
||||
eventGenerator.enable();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReceiveEvent2EventsOnNodeCreation() throws Exception
|
||||
{
|
||||
if (!eventGenerator.isEnabled())
|
||||
{
|
||||
eventGenerator.enable();
|
||||
}
|
||||
|
||||
createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
Awaitility.await().atMost(6, TimeUnit.SECONDS).until(() -> receivedEvents.size() == 1);
|
||||
|
||||
assertTrue(EVENT_CONTAINER.getEvents().size() == 1);
|
||||
assertTrue(receivedEvents.size() == 1);
|
||||
|
||||
RepoEvent<?> sent = getRepoEvent(1);
|
||||
RepoEvent<?> received = receivedEvents.get(0);
|
||||
assertEventsEquals("Events are different!", sent, received);
|
||||
}
|
||||
|
||||
private void assertEventsEquals(String message, RepoEvent<?> expected, RepoEvent<?> current)
|
||||
{
|
||||
assertEquals(message, expected, current);
|
||||
}
|
||||
|
||||
private static String getText(Message message)
|
||||
{
|
||||
try
|
||||
{
|
||||
ActiveMQTextMessage am = (ActiveMQTextMessage) message;
|
||||
return am.getText();
|
||||
} catch (JMSException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -35,7 +35,8 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||
DeleteRepoEventIT.class,
|
||||
ChildAssociationRepoEventIT.class,
|
||||
PeerAssociationRepoEventIT.class,
|
||||
EventGeneratorTest.class
|
||||
EventGeneratorTest.class,
|
||||
EventGeneratorDisabledTest.class
|
||||
})
|
||||
public class RepoEvent2ITSuite
|
||||
{
|
||||
|
Reference in New Issue
Block a user