Skip to content

Commit c5a4422

Browse files
jlosornogilMiguel Ángel Martín
and
Miguel Ángel Martín
authored
REPO-5404 Alfresco Java Event API (#2)
* [#REPO-5404] Initial import * [REPO-5404] Move acs-event-model as submodule Move the project https://github.com/Alfresco/acs-event-model as a submodule of the Alfresco Java Event API project. * [REPO-5404] Rename alfresco-java-event-api-acs-event-model Rename the module alfresco-java-event-api-acs-event-model to alfresco-java-event-api-model * [REPO-5404] Rename org.alfresco.repo.event package Rename the package to align to the ones in the sdk (org.alfresco.event.sdk) * [REPO-5404] Cleanup model module * [REPO-5404] Add Spring Integration sample project Add first version of the Spring Integration sample project to use the Alfresco Java Events API. * [REPO-5404] Add plain handlers sample project Add first version of the plain handlers sample project to use the Alfresco Java Events API. * [REPO-5404] Add README to event API root project * [REPO-5404] Add README files for the sample projects * [REPO-5404] Add custom runtime exception Add EventHandlingException as custom RuntimeException and throw it if there is any problem parsing the JSON of the event in the generic transformer. * Update alfresco-java-event-api/alfresco-java-event-api-handling/src/test/java/org/alfresco/event/sdk/handling/SimpleEventHandlingExecutorTest.java Co-authored-by: Miguel Ángel Martín <[email protected]> * Update alfresco-java-event-api/alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/EventHandlingRegistry.java Co-authored-by: Miguel Ángel Martín <[email protected]> * Update alfresco-java-event-api/alfresco-java-event-api-model/src/main/java/org/alfresco/event/sdk/model/v1/model/PeerAssocInfo.java Co-authored-by: Miguel Ángel Martín <[email protected]> * Remove unnecessary line * [REPO-5404] Remove all references to enterprise Remove all the references to the enterprise event model in the SDK for now. * [REPO-5404] Change MimeType filter to multi-value Change the mime-type filter to accept a set of possible mime-type's. * [REPO-5404] Reorganize projects hierarchy Reorganize the hierarchy of the projects after the addition of the parent pom. * [REPO-5404] Remove unnecessary configuration * [REPO-5404] Remove unnecessary configuration Co-authored-by: Miguel Ángel Martín <[email protected]>
1 parent 715450c commit c5a4422

File tree

130 files changed

+9247
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+9247
-2
lines changed

alfresco-java-event-api/README.md

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# Alfresco Java Event API
2+
3+
Alfresco Java Event API is a part of the Alfresco Java SDK that enables an Alfresco integrator to work with the new Alfresco Event API, reacting to the events
4+
produced by the Alfresco platform.
5+
6+
## Components
7+
8+
The Alfresco Java Event API offering is composed by four main components: the event model, the event handling library, the [Spring Integration](https://spring.io/projects/spring-integration)
9+
tooling library and the [Spring Boot](https://spring.io/projects/spring-boot) custom [starter](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-developing-auto-configuration).
10+
11+
### Event Model
12+
13+
The event model is a component that offers a custom model definition to clearly specify the way the event's data is organised.
14+
15+
This component is declared in the module [alfresco-java-event-api-model](./alfresco-java-event-api-model) and it is explained in detail in its
16+
[README file](./alfresco-java-event-api-model/README.md).
17+
18+
### Event Handling Library
19+
20+
The event handling library is a core component of the Java Event API that offers a set of pre-defined event handling interfaces and the classes required to
21+
properly work with them. The idea of this library is to ease the implementation of behaviours that must be triggered as a response to an event.
22+
23+
This component is defined in the module [alfresco-java-event-api-handling](./alfresco-java-event-api-handling). The classes and interfaces of this library
24+
where designed to be as Java technology agnostic as possible. They offer the plain event handling functionality doing no assumptions about the technology used
25+
to make them work together. They're mostly plain Java classes, so the integrator can use them in a Spring project, a Dagger project or any other technology.
26+
27+
The main four items in this library are explained in the next sections.
28+
29+
#### Event Handler
30+
31+
[```EventHandler```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/handler/EventHandler.java) interface defines the
32+
contract of each implementation of a behaviour to be triggered as a reaction to an event.
33+
34+
This contract has been reduced to a minimum, which is:
35+
* The type of event the handler will tackle.
36+
* Other conditions the event must match to be handled (defaulted to none). See [Event Filter](#event-filter).
37+
* The code to execute as a reaction to the event.
38+
39+
A hierarchy of interfaces that extend [```EventHandler```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/handler/EventHandler.java)
40+
has been already defined to cover the different types of events that can be currently triggered by the API (i.e.
41+
[```OnNodeDeletedEventHandler```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/handler/OnNodeDeletedEventHandler.java)).
42+
43+
#### Event Handling Registry
44+
45+
[```EventHandlingRegistry```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/EventHandlingRegistry.java) is a class that
46+
registers the [```EventHandler```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/handler/EventHandler.java)'s that must be
47+
executed in response to each event type.
48+
49+
#### Event Handling Executor
50+
51+
[```EventHandlingExecutor```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/EventHandlingExecutor.java) is an interface
52+
that defines the process to execute the event handlers when events are received.
53+
54+
Currently, there is only one implementation ([```SimpleEventHandlingExecutor```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/SimpleEventHandlingExecutor.java))
55+
of this interface that simply uses the [```EventHandlingRegistry```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/EventHandlingRegistry.java)
56+
to get the list of [```EventHandler```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/handler/EventHandler.java)'s to execute
57+
when a specific event is triggered and executes them synchronously one by one.
58+
59+
#### Event Filter
60+
61+
[```EventFilter```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/filter/EventFilter.java) is an interface that defines the
62+
contract that must be fulfilled by an event. It is basically a predicate interface that allows the integrator to easily define conditions that must match an
63+
event.
64+
65+
The SDK offers a basic set of implementations of the [```EventFilter```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/filter/EventFilter.java)
66+
covering the most common use cases that can be tackled by a handler (i.e. [```PropertyChangedFilter```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/filter/PropertyChangedFilter.java)
67+
or [```ContentAddedFilter```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/filter/ContentAddedFilter.java)).
68+
69+
The integrator can create new custom event filters, as complex as required, and can use the logical operation of the [```EventFilter```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/filter/EventFilter.java)
70+
interface to combine several simpler filters in any way.
71+
72+
For instance, you can create a filter to react to an event related to the modification of the title of a content of type ```cm:content``` with a mime-type of
73+
```text/html``` this way:
74+
75+
```
76+
PropertyChangedFilter.of("cm:title")
77+
.and(NodeTypeFilter.of("cm:content"))
78+
.and(MimeTypeFilter.of("text/html"))
79+
```
80+
81+
### Spring Integration Tooling Library
82+
83+
The Spring Integration tooling library component offers some utility classes that ease the handling of Alfresco events in the context of a Spring Integration
84+
application.
85+
86+
This component is defined in the module [alfresco-java-event-api-integration](./alfresco-java-event-api-integration).
87+
88+
It makes use of the event handling library and the event model to offer integration features making the assumption that the integrator is working on the context
89+
of a Spring Integration project.
90+
91+
The way the events are consumed from the ActiveMQ topic where the Events API is currently publishing them is not specified at this level of integration, and it
92+
is intentionally left open to the integrator's choice. For a more opinionated integration level please take a look to the
93+
[Spring Boot custom starter section](#spring-boot-custom-starter).
94+
95+
Once the JSON events are ingested in a Spring Integration channel, this library offers a transformer to translate from the JSON schema defined by the Event Model
96+
to the Java POJO classes defined in it (i.e. ```RepoEvent```).
97+
98+
Apart from that, this module offers a wrapper of the [```EventFilter```](./alfresco-java-event-api-handling/src/main/java/org/alfresco/event/sdk/handling/filter/EventFilter.java)
99+
interface as a Spring Integration filter (```GenericSelector```) to be able to use all the filter offering of the handling library in a Spring Integration
100+
context easily.
101+
102+
### Spring Boot Custom Starter
103+
104+
The Spring Boot custom starter component defines a personalized Spring Boot starter to automatically configure all the beans and properties defaults to
105+
implement a client of the Alfresco Java Event API easily. As should be expected, the use of this component makes the assumption of creating an integration in
106+
the context of a Spring Boot application.
107+
108+
This component is defined in the modules [alfresco-java-event-api-spring-boot-autoconfigure](./alfresco-java-event-api-spring-boot-autoconfigure) and
109+
[alfresco-java-event-api-spring-boot-starter](./alfresco-java-event-api-spring-boot-starter).
110+
111+
The core class of this module is [```AlfrescoEventsAutoConfiguration```](./alfresco-java-event-api-spring-boot-autoconfigure/src/main/java/org/alfresco/event/sdk/autoconfigure/AlfrescoEventsAutoConfiguration.java).
112+
It is a Spring configuration class that automatically define the beans required to do the next actions:
113+
* Define a Spring Integration flow to read the event messages from the ActiveMQ topic using a JMS channel adapter.
114+
* Transform the message payload from JSON to a ```RepoEvent``` object.
115+
* Route the corresponding event messages to up to 2 other channels:
116+
+ A channel to use pure Spring Integration handling if the property ```alfresco.events.enableSpringIntegration``` is enabled.
117+
+ A channel to use event handling (from the event handling library) if the property ```alfresco.events.enableHandlers``` is enabled.
118+
119+
All this auto-configuration will be enabled as soon as the dependency ```org.alfresco:alfresco-java-event-api-spring-boot-starter``` is added to a Spring Boot
120+
project.
121+
122+
## How To Integrate
123+
124+
### Option 1: Use Spring Boot Starter
125+
126+
The steps to integrate with the Alfresco Java Event API using the Spring Boot starter are:
127+
128+
* In you ```pom.xml``` file, add the dependency of the custom starter:
129+
130+
```
131+
<dependency>
132+
<groupId>org.alfresco</groupId>
133+
<artifactId>alfresco-java-event-api-spring-boot-starter</artifactId>
134+
<version>5.0.0-SNAPSHOT</version>
135+
</dependency>
136+
```
137+
138+
* In your ```application.properties``` file define the properties required to properly connect to the ActiveMQ broker:
139+
140+
```
141+
spring.activemq.brokerUrl=tcp://activemq-host:61616
142+
# This property is required if you want Spring Boot to auto-define the ActiveMQConnectionFactory, otherwise you can define that bean in Spring config
143+
spring.jms.cache.enabled=false
144+
```
145+
146+
* In your ```application.properties``` file define the properties to set the type of integration you want to use (spring integration and/or plain Java
147+
handlers):
148+
149+
```
150+
alfresco.events.enableSpringIntegration=false
151+
alfresco.events.enableHandlers=true
152+
```
153+
154+
From this point you can start defining Spring Integration flows and/or event handlers depending on the integration method selected.
155+
156+
For more detail about how to write the handlers, please take a look to the [samples](../samples) section of this project:
157+
* Spring Integration -> [```event-api-spring-integration```](../samples/event-api-spring-integration)
158+
* Plain Java handlers -> [```event-api-handlers```](../samples/event-api-handlers)
159+
160+
### Option 2: Use Spring Integration Tooling
161+
162+
If you're working on a Spring Integration application, but you don't want to use Spring Boot, then you can make use of the tooling classes explained in the
163+
[section above](#spring-integration-tooling-library).
164+
165+
In order to use them, you only need to add the corresponding dependency to your ```pom.xml``` file:
166+
167+
```
168+
<dependency>
169+
<groupId>org.alfresco</groupId>
170+
<artifactId>alfresco-java-event-api-integration</artifactId>
171+
<version>5.0.0-SNAPSHOT</version>
172+
</dependency>
173+
```
174+
175+
In this case, you can choose the way the events are consumed from the ActiveMQ topic and ingested into Spring Integration.
176+
177+
### Option 3: Use Event Handling Library
178+
179+
If you're not interested in working with Spring Integration or even with the Spring Framework, then you can make use of the interfaces and classes offered by
180+
the event handling library explained in the [section above](#event-handling-library).
181+
182+
In order to use them, you only need to add the corresponding dependency to your ```pom.xml``` file:
183+
184+
```
185+
<dependency>
186+
<groupId>org.alfresco</groupId>
187+
<artifactId>alfresco-java-event-api-handling</artifactId>
188+
<version>5.0.0-SNAPSHOT</version>
189+
</dependency>
190+
```
191+
192+
In this case, you can choose the way the events are consumed from the ActiveMQ topic and the way the event handling components are initialised and wired up to
193+
be able to react to each specific event (i.e. you can use [Dagger](https://dagger.dev/) as dependency injection engine with no problem).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>org.alfresco</groupId>
9+
<artifactId>alfresco-java-event-api</artifactId>
10+
<version>5.0.0-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>alfresco-java-event-api-handling</artifactId>
14+
<name>Alfresco Java Event API :: Event Handling</name>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>org.alfresco</groupId>
19+
<artifactId>alfresco-java-event-api-model</artifactId>
20+
</dependency>
21+
<dependency>
22+
<groupId>org.slf4j</groupId>
23+
<artifactId>slf4j-api</artifactId>
24+
</dependency>
25+
26+
<dependency>
27+
<groupId>junit</groupId>
28+
<artifactId>junit</artifactId>
29+
<scope>test</scope>
30+
</dependency>
31+
<dependency>
32+
<groupId>org.assertj</groupId>
33+
<artifactId>assertj-core</artifactId>
34+
<scope>test</scope>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.mockito</groupId>
38+
<artifactId>mockito-core</artifactId>
39+
<scope>test</scope>
40+
</dependency>
41+
</dependencies>
42+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2010-2021 Alfresco Software, Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.alfresco.event.sdk.handling;
18+
19+
/**
20+
* {@link RuntimeException} that reflects a problem handling an event.
21+
*/
22+
public class EventHandlingException extends RuntimeException {
23+
24+
/**
25+
* Construct a new event handling exception with the specified message and cause.
26+
*
27+
* @param message given message to add to the exception
28+
* @param cause given {@link Throwable} that caused this exception
29+
*/
30+
public EventHandlingException(final String message, final Throwable cause) {
31+
super(message, cause);
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2010-2021 Alfresco Software, Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.alfresco.event.sdk.handling;
18+
19+
import org.alfresco.event.sdk.model.v1.model.DataAttributes;
20+
import org.alfresco.event.sdk.model.v1.model.RepoEvent;
21+
import org.alfresco.event.sdk.model.v1.model.Resource;
22+
23+
/**
24+
* Definition of the operations related to the execution of the handling of the repository events.
25+
*/
26+
@FunctionalInterface
27+
public interface EventHandlingExecutor {
28+
29+
/**
30+
* Execute the event handlers that correspond to a specific {@link RepoEvent}.
31+
*
32+
* @param repoEvent given {@link RepoEvent} to be handled
33+
*/
34+
void executeEventHandlers(final RepoEvent<DataAttributes<Resource>> repoEvent);
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2010-2021 Alfresco Software, Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.alfresco.event.sdk.handling;
18+
19+
import java.util.ArrayList;
20+
import java.util.Collections;
21+
import java.util.HashMap;
22+
import java.util.List;
23+
import java.util.Map;
24+
import org.alfresco.event.sdk.handling.handler.EventHandler;
25+
import org.alfresco.event.sdk.model.v1.model.EventType;
26+
import org.alfresco.event.sdk.model.v1.model.RepoEvent;
27+
import org.slf4j.Logger;
28+
import org.slf4j.LoggerFactory;
29+
30+
/**
31+
* Register for {@link EventHandler} instances. The event handlers are internally stored in a {@link Map} which key is an event type and its value a list of the
32+
* event handlers registered for that type.
33+
*/
34+
public class EventHandlingRegistry {
35+
36+
private static final Logger LOGGER = LoggerFactory.getLogger(EventHandlingRegistry.class);
37+
38+
private final Map<String, List<EventHandler>> eventHandlers = new HashMap<>();
39+
40+
/**
41+
* Constructor.
42+
*
43+
* @param eventHandlers given list of event handlers to add to the registry
44+
*/
45+
public EventHandlingRegistry(final List<EventHandler> eventHandlers) {
46+
eventHandlers.forEach(this::registerHandler);
47+
}
48+
49+
/**
50+
* Get the list of event handlers that correspond to a specific {@link RepoEvent}. The event type determines the list of handlers to provide.
51+
*
52+
* @param repoEvent given {@link RepoEvent} to get its handlers
53+
* @return the {@link List} of {@link EventHandler}s registered for the corresponding event type
54+
*/
55+
public List<EventHandler> getEventHandlers(final RepoEvent repoEvent) {
56+
return eventHandlers.getOrDefault(repoEvent.getType(), Collections.emptyList());
57+
}
58+
59+
private void registerHandler(final EventHandler eventHandler) {
60+
LOGGER.debug("Registering event handler {}", eventHandler);
61+
final EventType handledEventType = eventHandler.getHandledEventType();
62+
if (handledEventType != null) {
63+
final List<EventHandler> typedEventHandlers = eventHandlers.getOrDefault(handledEventType.getType(), new ArrayList<>());
64+
typedEventHandlers.add(eventHandler);
65+
eventHandlers.put(handledEventType.getType(), typedEventHandlers);
66+
} else {
67+
LOGGER.warn("Skipping registry of event handler {} because the event type handled is null", eventHandler);
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)