Projet

Général

Profil

SpeADL Minus Tutorial » Historique » Version 6

Anonyme, 06/10/2014 16:13

1 1 Anonyme
h1. SpeADL Minus Tutorial
2
3 4 Anonyme
{{>toc}}
4
5 1 Anonyme
This is a tutorial for [[SpeADL Minus Reference|SpeADL⁻]]: creating a project, defining simple and composite components, implementing components.
6
7
h2. Objectives
8
9
The objective of this tutorial is to understand the basic workflow to follow when developing component-oriented applications with SpeADL in Eclipse/MAY.
10
11
We will create a simple composition of two components connected together following a typical client-server configuration.
12
The server will provide a service that will be used by the client.
13
They will be composed together in a big component.
14 6 Anonyme
A Java *main()* will be created to show how to execute the composition from Java.
15 1 Anonyme
16
h2. Installing Eclipse and MAY
17
18
This procedure is described on [[SpeADL MAY Project SetUp|this page]].
19
20
h2. Creating a New Project
21
22
First, we must create a project to work.
23
24
In Eclipse, go to the menus : *File / New / Java Project*.
25
26
Enter _Tutorial 1_ as the project name, verify that the *execution environment JRE* is 1.5 or above.
27
28
As a start, create a package in the *src* folder called _tutorial1_.
29
30
h2. The Server Component
31
32 3 Anonyme
h3. Organisation
33
34 1 Anonyme
Create the following hierarchy of packages (See [[SpeADL Best Practices#Project Organisation|this best practice]] for details on the matter):
35
* _tutorial1.server_
36
** _impl_
37
** _interfaces_
38
39 3 Anonyme
h3. Defining the Component
40
41 2 Anonyme
Create a SpeADL file:
42
* Right-click on tutorial1.server and select *New / File*.
43
* Enter _server.speadl_ as the file name.
44 1 Anonyme
45
Define the namespace we are going to work in as well as the _Server_ component:
46
<pre>
47
namespace tutorial1.server {
48
	component ServerComponentType {
49
		
50 3 Anonyme
	}
51
}
52
</pre>
53
54
Save and confirm that the *speadl-gen* folder was automatically added to the project source folders and that it contains a Java class generated in the package _tutorial1.server_ named _ServerComponentType_.
55
56
h3. Defining a Port and its Interface
57
58
The _Server_ component will provide a port whose interface contains one method to give the contrary of a boolean.
59
60
Add it to the component declaration:
61
<pre>
62
namespace tutorial1.server {
63
	component ServerComponentType {
64
		provides service: NotSoNiceServiceType
65
	}
66
}
67
</pre>
68
69
Because the _NotSoNiceServiceType_ interface does not yet exist, there is an error in the SpeADL editor.
70
We will store the interface in the _tutorial1.server.interfaces_ package.
71
72
Either create it by hand or use the Quick Fix proposed by SpeADL editor by hovering on the error.
73
<pre>
74
package tutorial1.server.interfaces;
75
76
public interface NotSoNiceServiceType {
77
78
	public boolean contrary(boolean b);
79
}
80
</pre>
81
82
Save, and go back to the SpeADL editor for _server.speadl_.
83
Call the automatic import organiser with *Ctrl+Shift+O*.
84
Confirm that an import was added on top of the SpeADL file and save.
85
86
h3. Implementing the Component
87
88
Create a new Java class in _tutorial1.server.impl_ named ServerImpl, and edit it so that it extends ServerComponentType:
89
<pre>
90 5 Anonyme
public class ServerImpl extends ServerComponentType {
91 3 Anonyme
92
}
93
</pre>
94
95
Notice that completion can be exploited as _ServerComponentType_ is an actual Java type, but that calling *F3* on it redirects directly to the SpeADL file.
96
97
Because there is abstract method to implement in _ServerComponentType_, there is errors in the Java editor.
98
Use the Quick Fix *Add unimplemented methods* by hovering on the error on the class name _ServerImpl_:
99
<pre>
100
public class ServerImpl extends ServerComponentType {
101
102
	@Override
103
	protected NotSoNiceServiceType make_service() {
104
		// TODO Auto-generated method stub
105
		return null;
106
	}
107
108
}
109
</pre>
110
111
Remove the *TODO* line and replace _null_ with _new NotSoNiceServiceType_, call completion (*Ctrl+Space*) and choose *NotSoNiceServiceType() Anonymous Inner Type*:
112
<pre>
113
public class ServerImpl extends ServerComponentType {
114
115
	@Override
116
	protected NotSoNiceServiceType make_service() {
117
		return new NotSoNiceServiceType() {
118
			
119
			@Override
120
			public boolean contrary(boolean b) {
121
				// TODO Auto-generated method stub
122
				return false;
123 1 Anonyme
			}
124
		};
125 4 Anonyme
	}
126
}
127
</pre>
128
129
Remove the *TODO* line and replace _return false;_ by _return !b;_:
130
<pre>
131
package tutorial1.server.impl;
132
133
import tutorial1.server.ServerComponentType;
134
import tutorial1.server.interfaces.NotSoNiceServiceType;
135
136
public class ServerImpl extends ServerComponentType {
137
138
	@Override
139
	protected NotSoNiceServiceType make_service() {
140
		return new NotSoNiceServiceType() {
141
			
142
			@Override
143
			public boolean contrary(boolean b) {
144
				return !b;
145
			}
146
		};
147
	}
148
149
}
150
</pre>
151
152 1 Anonyme
h2. The Client Component
153 4 Anonyme
154
h3. Organisation
155
156 5 Anonyme
Create the following hierarchy of packages:
157 4 Anonyme
* _tutorial1.client_
158
** _impl_
159
** _interfaces_
160
** _datatypes_
161
162
h3. Defining the Component
163
164
Create a SpeADL file in _tutorial1.client_ named _client.speadl_.
165
166
Define the namespace we are going to work in as well as the _Client_ component:
167
<pre>
168
namespace tutorial1.client {
169
	component ClientComponentType {
170
		
171
	}
172
}
173
</pre>
174
175
Save and confirm that the *speadl-gen* folder contains a Java class generated in the package _tutorial1.client_ named _ClientComponentType_.
176
177
h3. Defining the Ports, their Interfaces and Datatypes
178
179
The Client component will provides a port computing a request and will need the _NotSoNiceServiceType_ to do its job:
180
<pre>
181
import tutorial1.server.interfaces.NotSoNiceServiceType
182
183
namespace tutorial1.client {
184
	
185
	component ClientComponentType {
186
		provides service: ASupeNiceService
187
		requires helper: NotSoNiceServiceType
188
	}
189
	
190
}
191
</pre>
192
193
Don't hesitate to exploit completion (*Ctrl+Space*) and automatic import organiser (*Ctrl+Shift+O*) to type the interfaces names.
194
195
As before, an error appears in the editor because _ASupeNiceService_ does not exists, create it in _tutorial1.client.interfaces_:
196
<pre>
197
package tutorial1.client.interfaces;
198
199
public interface ASupeNiceService {
200
201 1 Anonyme
	public Request compute(Request r);
202
	
203 4 Anonyme
}
204
</pre>
205
206 5 Anonyme
As we can see, we rely on a type named _Request_.
207
Create it in _tutorial1.client.datatypes_:
208 4 Anonyme
<pre>
209
package tutorial1.client.datatypes;
210
211
public class Request {
212
213
	public final boolean b;
214 1 Anonyme
215
	public Request(boolean b) {
216
		this.b = b;
217
	}
218
}
219
</pre>
220 5 Anonyme
221
h3. Implementing the Component
222
223
Create a new Java class in tutorial1.client.impl named ClientImpl.
224
Edit it so that it extends _ClientComponentType_ and resolve all the errors to generate its complete skeleton:
225
<pre>
226
package tutorial1.client.impl;
227
228
import tutorial1.client.ClientComponentType;
229
import tutorial1.client.datatypes.Request;
230
import tutorial1.client.interfaces.ASupeNiceService;
231
232
public class ClientImpl extends ClientComponentType {
233
234
	@Override
235
	protected ASupeNiceService make_service() {
236
		return new ASupeNiceService() {
237
			
238
			@Override
239
			public Request compute(Request r) {
240
				// TODO Auto-generated method stub
241
				return null;
242
			}
243
		};
244
	}
245
246
}
247
</pre>
248
249
Implement the _compute()_ method to call the required port _helper_ to actually do the computation and to return a new _Request_:
250
<pre>
251
public class ClientImpl extends ClientComponentType {
252
253
	@Override
254
	protected ASupeNiceService make_service() {
255
		return new ASupeNiceService() {
256
			@Override
257
			public Request compute(Request r) {
258
				final boolean contrary = requires().helper().contrary(r.b);
259
				return new Request(contrary);
260
			}
261
		};
262
	}
263
}
264
</pre>
265
266
h2. The Composite Component
267
268
In order to use the Client and the Server components together, we need to build a composite component connecting them together.
269
270 1 Anonyme
h3. Defining the Component
271
272 6 Anonyme
Create a SpeADL file in _tutorial1.composite_ named _composite.speadl_.
273 5 Anonyme
274 6 Anonyme
Define the namespace we are going to work in as well as the _CompositeComponentType_ component:
275 5 Anonyme
<pre>
276 6 Anonyme
namespace tutorial1.composite {
277
	component CompositeComponentType {
278 5 Anonyme
		
279
	}
280
}
281 1 Anonyme
</pre>
282 5 Anonyme
283
Save.
284
285 1 Anonyme
h3. Defining the Composition
286 5 Anonyme
287 6 Anonyme
In CompositeComponentType, there will be one server and one client for now.
288
Declare them as parts in the composite component:
289 5 Anonyme
<pre>
290
import tutorial1.client.ClientComponentType
291
import tutorial1.server.ServerComponentType
292
293 6 Anonyme
namespace tutorial1.composite {
294
	component CompositeComponentType {
295 5 Anonyme
		part server: ServerComponentType {
296
			
297
		}
298
		
299 1 Anonyme
		part client: ClientComponentType {
300 5 Anonyme
			
301
		}
302
	}
303
}
304
</pre>
305
306
An error is present in the editor on the _client_ name to express that some required ports of client are not bound.
307
Using the *bind ... to ...* keyword by it:
308
<pre>
309 6 Anonyme
namespace tutorial1.composite {
310
	component CompositeComponentType {
311 5 Anonyme
		part server: ServerComponentType {
312
			
313 1 Anonyme
		}
314
		
315
		part client: ClientComponentType {
316
			bind helper to server.service
317
		}
318
	}
319
}
320
</pre>
321
322
Save.
323
324
h3. Implementing the Component
325 6 Anonyme
326
Create a new Java class in tutorial1.composite.impl named CompositeImpl.
327
Edit it so that it extends _CompositeComponentType_ and resolve all the errors to generate its complete skeleton:
328
<pre>
329
package tutorial1.composite.impl;
330
331
import tutorial1.CompositeComponentType;
332
import tutorial1.client.ClientComponentType;
333
import tutorial1.server.ServerComponentType;
334
335
public class CompositeImpl extends CompositeComponentType {
336
337
	@Override
338
	protected ServerComponentType make_server() {
339
		// TODO Auto-generated method stub
340
		return null;
341
	}
342
343
	@Override
344
	protected ClientComponentType make_client() {
345
		// TODO Auto-generated method stub
346
		return null;
347
	}
348
}
349
</pre>
350
351
For the _server_ part, return a new instance of the implementation _ServerImpl_ , and the same for the _client_ part with _ClientImpl_:
352
<pre>
353
public class CompositeImpl extends CompositeComponentType {
354
355
	@Override
356
	protected ServerComponentType make_server() {
357
		return new ServerImpl();
358
	}
359
360
	@Override
361
	protected ClientComponentType make_client() {
362
		return new ClientImpl();
363
	}
364
}
365
</pre>
366
367
h3. Creating an Application
368
369
We can now instantiate this composition in an application.
370
Create a Java class named _Application_ in _tutorial1_ with a *static void main()* method.
371
372
Create an instance of the composite component in it:
373
<pre>
374
package tutorial1;
375
376
import tutorial1.composite.CompositeComponentType;
377
import tutorial1.composite.impl.CompositeImpl;
378
379
public class Application {
380
381
	public static void main(String[] args) {
382
		CompositeComponentType.Component component = new CompositeImpl().newComponent();
383
	}
384
385
}
386
</pre>
387
388
Unfortunately, we forgot to provide a port on this component: it is thus impossible for us to access to the client component inside.
389
390
h3. Adding a Delegating Port 
391
392
In order to be able to use the composite component from Java, we thus need a provided port, and it will delegate to the provided port of the client component.
393
Edit the SpeADL file _composite.speadl_ to add such a delegation:
394
<pre>
395
import tutorial1.client.ClientComponentType
396
import tutorial1.client.interfaces.ASupeNiceService
397
import tutorial1.server.ServerComponentType
398
399
namespace tutorial1.composite {
400
	
401
	component CompositeComponentType {
402
		
403
		provides service: ASupeNiceService = client.service
404
		
405
		part server: ServerComponentType {
406
			
407
		}
408
		
409
		part client: ClientComponentType {
410
			bind helper to server.service
411
		}
412
	}
413
}
414
</pre>
415
416
This is all that is needed for it to work.
417
418
h3. Running the Application
419
420
Edit the Application class to call the newly added port:
421
<pre>
422
package tutorial1;
423
424
import tutorial1.client.datatypes.Request;
425
import tutorial1.composite.CompositeComponentType;
426
import tutorial1.composite.impl.CompositeImpl;
427
428
public class Application {
429
430
	public static void main(String[] args) {
431
		CompositeComponentType.Component component = new CompositeImpl().newComponent();
432
		Request input = new Request(true);
433
		Request output = component.service().compute(input);
434
		System.out.println(output.b);
435
	}
436
437
}
438
</pre>
439
440
Right-click on the *main()* method and select *Run As / Java Application*.
441
442
Confirm that *false* is printed in the console as expected.