|
|
# Implementing an own Architecture
|
|
|
The implementation of an Architecture is divided into its configuration and its execution.
|
|
|
|
|
|
## Configuring the Architecture
|
|
|
When writing an own Architecture, i.e., a set of connected stages, you should inherit from `Configuration` to save you some work.
|
|
|
A configuration creates and connects the stages you want to execute.
|
|
|
|
|
|
Consider the following example configuration `RecordReaderConfiguration`. It represents a configuration for an analysis that reads monitoring records from a directory and collects them in a list.
|
|
|
The invoked `buildProducerPipeline()` creates three stages, namely an instance of `InitialElementProducer`, `Dir2RecordsFilter` and `CollectorSink`.
|
|
|
|
|
|
We then uses the method `connectPorts` to connect the stages' ports with each other.
|
|
|
|
|
|
```java
|
|
|
public class RecordReaderConfiguration extends Configuration {
|
|
|
|
|
|
private final List<IMonitoringRecord> elementCollection = new LinkedList<IMonitoringRecord>();
|
|
|
|
|
|
public RecordReaderConfiguration() {
|
|
|
this.buildProducerPipeline();
|
|
|
}
|
|
|
|
|
|
private void buildProducerPipeline() {
|
|
|
ClassNameRegistryRepository classNameRegistryRepository = new ClassNameRegistryRepository();
|
|
|
File logDir = new File("src/test/data/bookstore-logs");
|
|
|
// create stages
|
|
|
InitialElementProducer<File> initialElementProducer = new InitialElementProducer<File>(logDir);
|
|
|
Dir2RecordsFilter dir2RecordsFilter = new Dir2RecordsFilter(classNameRegistryRepository);
|
|
|
CollectorSink<IMonitoringRecord> collector = new CollectorSink<IMonitoringRecord>(this.elementCollection);
|
|
|
|
|
|
// connect stages
|
|
|
connectPorts(initialElementProducer.getOutputPort(), dir2RecordsFilter.getInputPort());
|
|
|
connectPorts(dir2RecordsFilter.getOutputPort(), collector.getInputPort());
|
|
|
|
|
|
}
|
|
|
|
|
|
public List<IMonitoringRecord> getElementCollection() {
|
|
|
return this.elementCollection;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Executing an Analysis
|
|
|
The following snippet shows the default code for creating and executing an own analysis:
|
|
|
|
|
|
```java
|
|
|
Configuration configuration = ... // e.g., new RecordReaderConfiguration();
|
|
|
|
|
|
final Analysis analysis = new Analysis(configuration);
|
|
|
try {
|
|
|
analysis.executeBlocking();
|
|
|
} catch(AnalysisException e) {
|
|
|
// Collection<Pair<Thread, Throwable>> exceptions = e.getThrownExceptions()
|
|
|
}
|
|
|
```
|
|
|
|
|
|
The `executeBlocking` method of an `Analysis` starts the analysis and waits for it to finish successfully. Otherwise the method throws an exception containing a non-empty list. This list in turn contains the thrown exception of each thread that leads to the prematured termination. |
|
|
\ No newline at end of file |