Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,16 @@ PAMELA approach has been tested and validated on some java-based industrial proj
- Dynamic code weaving at runtime (aspect programming without compilation)

Official website, documentation and installation available here : [https://www.openflexo.org/pamela](https://www.openflexo.org/pamela)

## Lunch Sync Feature

Build the projet with gradle:

```bash
.\gradlew.bat clean :pamela-core:build :book:classes -x test --console=plain
```
Then run the Book example with the following command:

```bash
.\gradlew.bat :book:runDemo --console=plain
```
Binary file added book/.DS_Store
Binary file not shown.
157 changes: 157 additions & 0 deletions book/SYNC_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# PAMELA Distributed Synchronization Demo

Ce dossier contient un exemple de synchronisation distribuée d'instances PAMELA
utilisant RabbitMQ comme broker de messages.

## Architecture

```
┌─────────────────┐ RabbitMQ ┌─────────────────┐
│ ReplicaA │◄──────────────────►│ ReplicaB │
│ (Terminal 1) │ fanout exchange │ (Terminal 2) │
│ │ pamela-library- │ │
│ ┌───────────┐ │ sync │ ┌───────────┐ │
│ │ Library │ │ │ │ Library │ │
│ │ ┌─────┐ │ │ │ │ ┌─────┐ │ │
│ │ │Book1│ │ │ ◄── ADD Book ──► │ │ │Book1│ │ │
│ │ │Book2│ │ │ ◄── SET prop ──► │ │ │Book2│ │ │
│ │ └─────┘ │ │ ◄── REMOVE ────► │ │ └─────┘ │ │
│ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘
```

## Prérequis

1. **Java 17+** installé
2. **Docker** installé et lancé
3. **Gradle** (ou utiliser le wrapper `gradlew`)

## Étapes de Test

### 1. Démarrer RabbitMQ (Docker)

```bash
docker run -d --name rabbitmq \
-p 5672:5672 \
-p 15672:15672 \
rabbitmq:3-management
```

Accéder à l'interface d'administration : http://localhost:15672
Identifiants par défaut : `guest` / `guest`

### 2. Compiler le projet

```bash
cd book
.\gradlew build
```

### 3. Terminal 1 - Lancer ReplicaA

```bash
.\gradlew run -PmainClass=org.openflexo.testPamela.ReplicaA
```

Ou avec Java directement :
```bash
java -cp build/libs/book.jar:../pamela-core/build/libs/* org.openflexo.testPamela.ReplicaA
```

Notez l'**ID de la Library** affiché (ex: `a3b4c5d6-...`)

### 4. Terminal 2 - Lancer ReplicaB

```bash
.\gradlew run -PmainClass=org.openflexo.testPamela.ReplicaB
```

Quand demandé, entrez l'ID de la Library affiché par ReplicaA.

### 5. Tester la synchronisation

**Dans Terminal 1 (ReplicaA) :**
```
[A] > add Harry Potter
[A] ✓ Added: Book(title=Harry Potter)
```

**Dans Terminal 2 (ReplicaB) :** (mise à jour automatique)
```
[B] 📥 Received: ADD on books = Book(title=Harry Potter)
```

**Dans Terminal 2 (ReplicaB) :**
```
[B] > add Le Seigneur des Anneaux
```

**Dans Terminal 1 (ReplicaA) :** (mise à jour automatique)
```
[A] 📥 Received: ADD on books = ...
```

## Commandes disponibles

| Commande | Description |
|----------|-------------|
| `add <titre>` | Ajoute un livre à la bibliothèque |
| `remove <titre>` | Supprime un livre par son titre |
| `list` | Affiche tous les livres |
| `quit` | Quitte l'application |

## Structure des fichiers

```
book/
├── build.gradle # Dépendances (RabbitMQ, Jackson)
├── SYNC_README.md # Ce fichier
└── src/main/java/org/openflexo/testPamela/
├── model/
│ ├── Book.java # Modèle PAMELA d'un livre
│ ├── Library.java # Modèle PAMELA d'une bibliothèque
│ ├── Novel.java # Sous-type de Book
│ └── Journal.java # Sous-type de Book
├── App.java # Exemple original simple
├── ReplicaA.java # Première instance collaborative
└── ReplicaB.java # Seconde instance collaborative
```

## Comment ça marche ?

1. **SyncEditingContext** : Contexte d'édition étendu qui intercepte les modifications
2. **RabbitMQSyncManager** : Gère la connexion à RabbitMQ et la diffusion des messages
3. **ObjectIdentityManager** : Associe chaque objet PAMELA à un UUID unique
4. **SyncOperation** : Représente une opération (CREATE, SET, ADD, REMOVE, DELETE)
5. **VectorClock** : Horloge vectorielle pour l'ordre causal des opérations

Quand vous faites `library.addToBooks(book)` :
1. Le `ProxyMethodHandler` détecte l'appel au setter
2. Il broadcast une `SyncOperation` via `SyncEditingContext`
3. Le `RabbitMQSyncManager` publie le message JSON sur l'exchange
4. Toutes les réplicas reçoivent le message et appliquent l'opération

## Dépannage

### RabbitMQ ne démarre pas
```bash
docker logs rabbitmq
```

### Erreur de connexion
Vérifiez que le port 5672 est accessible :
```bash
docker ps | findstr rabbitmq
```

### Les messages ne se synchronisent pas
1. Vérifiez que les deux réplicas utilisent le même Library ID
2. Consultez les messages dans RabbitMQ Management UI (http://localhost:15672)
3. Vérifiez l'exchange "pamela-library-sync"

## Arrêter RabbitMQ

```bash
docker stop rabbitmq
docker rm rabbitmq
```
79 changes: 79 additions & 0 deletions book/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java project to get you started.
* For more details take a look at the Java Quickstart chapter in the Gradle
* User Manual available at https://docs.gradle.org/6.6.1/userguide/tutorial_java_projects.html
*/

plugins {
// Apply the java plugin to add support for Java
id 'java'

// Apply the application plugin to add support for building a CLI application.
id 'application'
}

repositories {
maven {
url "https://maven.openflexo.org/artifactory/openflexo-deps/"
}
mavenCentral()
// jcenter()
}

dependencies {
// Use local pamela-core project (includes the sync package)
implementation project(':pamela-core')

// RabbitMQ for collaborative synchronization
implementation 'com.rabbitmq:amqp-client:5.20.0'

// Jackson for JSON serialization
implementation 'com.fasterxml.jackson.core:jackson-databind:2.16.0'

// Use JUnit test framework
testImplementation 'junit:junit:4.13'
}

application {
// Define the main class for the application.
// Can be overridden with: gradlew run -PmainClass=org.openflexo.testPamela.ReplicaA
mainClassName = project.hasProperty('mainClass') ? project.property('mainClass') : 'org.openflexo.testPamela.App'
}

// Task to run ReplicaA
task runReplicaA(type: JavaExec) {
group = 'application'
description = 'Run the first collaborative replica (ReplicaA)'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.openflexo.testPamela.ReplicaA'
standardInput = System.in
}

// Task to run ReplicaB
task runReplicaB(type: JavaExec) {
group = 'application'
description = 'Run the second collaborative replica (ReplicaB)'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.openflexo.testPamela.ReplicaB'
standardInput = System.in
}

// Task to run ReplicaC
task runReplicaC(type: JavaExec) {
group = 'application'
description = 'Run the third collaborative replica (ReplicaC)'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.openflexo.testPamela.ReplicaC'
standardInput = System.in
}

// Task to run the Distributed Feature Demo
task runDemo(type: JavaExec) {
group = 'application'
description = 'Run the distributed features demonstration'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.openflexo.testPamela.DistributedFeatureDemo'
standardInput = System.in
}
Binary file added book/gradle/.DS_Store
Binary file not shown.
Binary file added book/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 5 additions & 0 deletions book/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading