Projet

Général

Profil

SpeADL Dynamic Tutorial » Historique » Version 8

Anonyme, 14/10/2014 16:21

1 3 Anonyme
h1. SpeADL for Dynamic Architectures Tutorial
2 2 Anonyme
3 7 Anonyme
{{>toc}}
4
5 1 Anonyme
This is a tutorial for SpeADL: understanding ecosystems and species, defining a simple ecosystem, composing species together with uses.
6 3 Anonyme
7
h2. Objectives
8
9
The objective of this tutorial to understand the abstractions of species and uses.
10
11
We will create a Logging ecosystem that contains Logger species.
12
Then we will create a Banking ecosystem that contains Account species that need to log what happens.
13
Finally we will create a Bank ecosystem that compose Account species with Logger species thanks to the use abstraction.
14
15
h2. Prerequisites
16
17
It is needed to understand the content of the [[SpeADL Minus Tutorial|SpeADL⁻ tutorial]] before doing this one.
18
19
h2. Creating a New Project and Organisation
20
21
Create a Java project.
22
We will use again an organisation of the package and namespaces as explained in [[MAY Best Practices#Project Organisation|this best practice]].
23
24
h2. The Logging Ecosystem
25
26
Logging will be an ecosystem, and its particularity is that it will be able to create Loggers: while logging is the subsystem responsible of all logging, each logger will be responsible of logging one particular aspect of the system identified by a _name_.
27
We will have multiple implementation for the Logging ecosystem:
28
* One with only one file where to log with each line prepended with the name.
29
* One with one file per Logger all in the same directory.
30
31
h3. Defining the Ecosystem and the Species
32 1 Anonyme
33 8 Anonyme
Create a SpeADL file named _logging.speadl_ in the package _tutorial2.logging_.
34 3 Anonyme
35
Define in it the ecosystem and the species in the right namespace as well as the needed interface:
36
<pre>
37 8 Anonyme
import tutorial2.logging.interfaces.ILog
38 3 Anonyme
39 8 Anonyme
namespace tutorial2.logging {
40 3 Anonyme
	
41 1 Anonyme
	ecosystem Logging {
42 3 Anonyme
		species Logger(name: String) {
43
			provides log: ILog
44
		}
45
	}
46
	
47
}
48
</pre>
49
50
<pre>
51 8 Anonyme
package tutorial2.logging.interfaces;
52 3 Anonyme
53
public interface ILog {
54
55
	public void addLine(String line);
56
}
57
</pre>
58
59
h3. Implementing the Ecosystem and the Species, First One
60
61 4 Anonyme
Create a new Java class in _tutorial2.logging.impl_ named _LoggingImplOne_ that extends _Logging_, that takes the a _File_ as a parameter to the constructor to store the logs, and resolve the error with the Quick Fixes of Eclipse:
62 3 Anonyme
<pre>
63
package tutorial2.logging.impl;
64
65
import java.io.File;
66
import java.io.FileNotFoundException;
67 5 Anonyme
import java.io.FileWriter;
68 3 Anonyme
import java.io.IOException;
69
import java.io.PrintWriter;
70
71
import tutorial2.logging.Logging;
72
73
public class LoggingImplOne extends Logging {
74
75
	private PrintWriter logWriter;
76
	
77
	public LoggingImplOne(File logFile) {
78
		// if an exception happens, nothing can be done about it
79
		// we just let logStream be null and
80
		// the operations of logging won't be done
81
		try {
82 5 Anonyme
			this.logWriter = new PrintWriter(new FileWriter(logFile), true);
83 3 Anonyme
		} catch (FileNotFoundException e) {
84 5 Anonyme
			System.err.println("An error happened with the file, nothing will be logged.");
85 1 Anonyme
			this.logWriter = null;
86 3 Anonyme
		} catch (IOException e) {
87 5 Anonyme
			System.err.println("An error happened with the file, nothing will be logged.");
88 3 Anonyme
			this.logWriter = null;
89
		}
90
	}
91
	
92
	@Override
93
	protected Logger make_Logger(String name) {
94
		// TODO Auto-generated method stub
95
		return null;
96
	}
97
}
98
</pre>
99
100
As we can see, the species we defined needs to be implemented and this implementation needs to be returned by the method _Logger make_Logger(String name)_.
101
102 4 Anonyme
Let's define an inner class inside _LoggingImplOne_ to do that, it will take as a parameter to the constructor the _name_ of the Logger and that will exploit the _logWriter_ to do the actual logging.
103 3 Anonyme
<pre>
104
public class LoggingImplOne extends Logging {
105
106
	private PrintWriter logWriter;
107
	
108
	// ...
109
	
110
	@Override
111
	protected Logger make_Logger(String name) {
112
		return new LoggerImpl(name);
113
	}
114
	
115
	private class LoggerImpl extends Logger implements ILog {
116
117
		private final String name;
118
		
119
		public LoggerImpl(String name) {
120
			this.name = name;
121
		}
122
		
123
		@Override
124
		protected ILog make_log() {
125
			return this;
126
		}
127 1 Anonyme
128
		@Override
129
		public void addLine(String line) {
130 5 Anonyme
			if (logWriter != null) {
131
				logWriter.println("["+name+"] "+ line);
132
			}
133 1 Anonyme
		}
134
	}
135
}
136 5 Anonyme
</pre>
137
138
We now have a complete implementation for the Logging ecosystem.
139
Let's test it with a very simple program, for that we will subclass _LoggingImplOne_ in _tutorial2.logging.tests_, create some Logger in its *start()* method and instantiate it:
140
<pre>
141
package tutorial2.logging.tests;
142
143
import java.io.File;
144
145
import tutorial2.logging.impl.LoggingImplOne;
146
147
public class LoggingImplOneTest extends LoggingImplOne {
148
149
	public LoggingImplOneTest(File logFile) {
150
		super(logFile);
151
	}
152
153
	@Override
154
	protected void start() {
155
		// create new Loggers
156
		Logger.Component l1 = newLogger("a");
157
		Logger.Component l2 = newLogger("b");
158
		Logger.Component l3 = newLogger("c");
159
		// log things to them
160
		l1.log().addLine("1 a says hi");
161
		l1.log().addLine("2 test test");
162
		l2.log().addLine("3 b says hoy");
163
		l1.log().addLine("4 blabla");
164
		l3.log().addLine("5 hop");
165
	}
166
	
167
	public static void main(String[] args) {
168
		new LoggingImplOneTest(new File("/tmp/tutorial2-logging-test.txt")).newComponent();
169
		
170
	}
171
}
172
</pre>
173
174 6 Anonyme
Execute it and confirm that the file _/tmp/tutorial2-logging-test.txt_ contains the following:
175 5 Anonyme
<pre>
176
[a] 1 a says hi
177
[a] 2 test test
178
[b] 3 b says hoy
179
[a] 4 blabla
180
[c] 5 hop
181 3 Anonyme
</pre>
182
183 1 Anonyme
h3. Implementing the Ecosystem and the Species, Second One
184 6 Anonyme
185
We can now define a second implementation that stores the logs of each Logger in its own file:
186
<pre>
187
package tutorial2.logging.impl;
188
189
import java.io.File;
190
import java.io.FileNotFoundException;
191
import java.io.FileWriter;
192
import java.io.IOException;
193
import java.io.PrintWriter;
194
195
import tutorial2.logging.Logging;
196
import tutorial2.logging.interfaces.ILog;
197
198
public class LoggingImplTwo extends Logging {
199
200
	private final File logDir;
201
202
	public LoggingImplTwo(File logDir) {
203
		this.logDir = logDir;
204
		this.logDir.mkdirs();
205
	}
206
	
207
	@Override
208
	protected Logger make_Logger(String name) {
209
		return new LoggerImpl(new File(logDir, name+".txt"));
210
	}
211
	
212
	private class LoggerImpl extends Logger implements ILog {
213
214
		private PrintWriter logWriter;
215
		
216
		public LoggerImpl(File logFile) {
217
			// if an exception happens, nothing can be done about it
218
			// we just let logStream be null and
219
			// the operations of logging won't be done
220
			try {
221
				this.logWriter = new PrintWriter(new FileWriter(logFile), true);
222
			} catch (FileNotFoundException e) {
223
				System.err.println("An error happened with the file, nothing will be logged.");
224
				this.logWriter = null;
225
			} catch (IOException e) {
226
				System.err.println("An error happened with the file, nothing will be logged.");
227
				this.logWriter = null;
228
			}
229
		}
230
		
231
		@Override
232
		protected ILog make_log() {
233
			return this;
234
		}
235
236
		@Override
237
		public void addLine(String line) {
238
			if (logWriter != null) {
239
				logWriter.println(line);
240
			}
241
		}
242
	}
243
}
244
</pre>
245
246
That can be tested with the following subclass:
247
<pre>
248
package tutorial2.logging.tests;
249
250
import java.io.File;
251
252
import tutorial2.logging.impl.LoggingImplTwo;
253
254
public class LoggingImplTwoTest extends LoggingImplTwo {
255
256
	public LoggingImplTwoTest(File logDir) {
257
		super(logDir);
258
	}
259
	
260
	@Override
261
	protected void start() {
262
		// create new Loggers
263
		Logger.Component l1 = newLogger("a");
264
		Logger.Component l2 = newLogger("b");
265
		Logger.Component l3 = newLogger("c");
266
		// log things to them
267
		l1.log().addLine("1 a says hi");
268
		l1.log().addLine("2 test test");
269
		l2.log().addLine("3 b says hoy");
270 1 Anonyme
		l1.log().addLine("4 blabla");
271
		l3.log().addLine("5 hop");
272
	}
273
	
274
	public static void main(String[] args) {
275
		new LoggingImplTwoTest(new File("/tmp/tutorial2-logging2-test/")).newComponent();
276
	}
277 6 Anonyme
}
278
</pre>
279
280
Execute it and confirm that the _/tmp/tutorial2-logging2-test/_ directory contains one file per Logger with the correct content.
281 8 Anonyme
282
h2. The Banking Ecosystem 
283
284
Banking will also be an ecosystem, it will contain Account that are species with a particularity: they have required ports!
285
Because of that, they can't simply be created but must be composed with other components or species to be usable.
286
287
h3. Defining the Ecosystem and the Species