Projet

Général

Profil

SpeADL Minus Tutorial » Historique » Version 5

Anonyme, 06/10/2014 15:53

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
A Java *main()* will be created to show how to execute the composition once.
15
A very simple GUI will be used to illustrate a self-contained component acting as an application.
16
17
h2. Installing Eclipse and MAY
18
19
This procedure is described on [[SpeADL MAY Project SetUp|this page]].
20
21
h2. Creating a New Project
22
23
First, we must create a project to work.
24
25
In Eclipse, go to the menus : *File / New / Java Project*.
26
27
Enter _Tutorial 1_ as the project name, verify that the *execution environment JRE* is 1.5 or above.
28
29
As a start, create a package in the *src* folder called _tutorial1_.
30
31
h2. The Server Component
32
33 3 Anonyme
h3. Organisation
34
35 1 Anonyme
Create the following hierarchy of packages (See [[SpeADL Best Practices#Project Organisation|this best practice]] for details on the matter):
36
* _tutorial1.server_
37
** _impl_
38
** _interfaces_
39
40 3 Anonyme
h3. Defining the Component
41
42 2 Anonyme
Create a SpeADL file:
43
* Right-click on tutorial1.server and select *New / File*.
44
* Enter _server.speadl_ as the file name.
45 1 Anonyme
46
Define the namespace we are going to work in as well as the _Server_ component:
47
<pre>
48
namespace tutorial1.server {
49
	component ServerComponentType {
50
		
51 3 Anonyme
	}
52
}
53
</pre>
54
55
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_.
56
57
h3. Defining a Port and its Interface
58
59
The _Server_ component will provide a port whose interface contains one method to give the contrary of a boolean.
60
61
Add it to the component declaration:
62
<pre>
63
namespace tutorial1.server {
64
	component ServerComponentType {
65
		provides service: NotSoNiceServiceType
66
	}
67
}
68
</pre>
69
70
Because the _NotSoNiceServiceType_ interface does not yet exist, there is an error in the SpeADL editor.
71
We will store the interface in the _tutorial1.server.interfaces_ package.
72
73
Either create it by hand or use the Quick Fix proposed by SpeADL editor by hovering on the error.
74
<pre>
75
package tutorial1.server.interfaces;
76
77
public interface NotSoNiceServiceType {
78
79
	public boolean contrary(boolean b);
80
}
81
</pre>
82
83
Save, and go back to the SpeADL editor for _server.speadl_.
84
Call the automatic import organiser with *Ctrl+Shift+O*.
85
Confirm that an import was added on top of the SpeADL file and save.
86
87
h3. Implementing the Component
88
89
Create a new Java class in _tutorial1.server.impl_ named ServerImpl, and edit it so that it extends ServerComponentType:
90
<pre>
91 5 Anonyme
public class ServerImpl extends ServerComponentType {
92 3 Anonyme
93
}
94
</pre>
95
96
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.
97
98
Because there is abstract method to implement in _ServerComponentType_, there is errors in the Java editor.
99
Use the Quick Fix *Add unimplemented methods* by hovering on the error on the class name _ServerImpl_:
100
<pre>
101
public class ServerImpl extends ServerComponentType {
102
103
	@Override
104
	protected NotSoNiceServiceType make_service() {
105
		// TODO Auto-generated method stub
106
		return null;
107
	}
108
109
}
110
</pre>
111
112
Remove the *TODO* line and replace _null_ with _new NotSoNiceServiceType_, call completion (*Ctrl+Space*) and choose *NotSoNiceServiceType() Anonymous Inner Type*:
113
<pre>
114
public class ServerImpl extends ServerComponentType {
115
116
	@Override
117
	protected NotSoNiceServiceType make_service() {
118
		return new NotSoNiceServiceType() {
119
			
120
			@Override
121
			public boolean contrary(boolean b) {
122
				// TODO Auto-generated method stub
123
				return false;
124 1 Anonyme
			}
125
		};
126 4 Anonyme
	}
127
}
128
</pre>
129
130
Remove the *TODO* line and replace _return false;_ by _return !b;_:
131
<pre>
132
package tutorial1.server.impl;
133
134
import tutorial1.server.ServerComponentType;
135
import tutorial1.server.interfaces.NotSoNiceServiceType;
136
137
public class ServerImpl extends ServerComponentType {
138
139
	@Override
140
	protected NotSoNiceServiceType make_service() {
141
		return new NotSoNiceServiceType() {
142
			
143
			@Override
144
			public boolean contrary(boolean b) {
145
				return !b;
146
			}
147
		};
148
	}
149
150
}
151
</pre>
152
153 1 Anonyme
h2. The Client Component
154 4 Anonyme
155
h3. Organisation
156
157 5 Anonyme
Create the following hierarchy of packages:
158 4 Anonyme
* _tutorial1.client_
159
** _impl_
160
** _interfaces_
161
** _datatypes_
162
163
h3. Defining the Component
164
165
Create a SpeADL file in _tutorial1.client_ named _client.speadl_.
166
167
Define the namespace we are going to work in as well as the _Client_ component:
168
<pre>
169
namespace tutorial1.client {
170
	component ClientComponentType {
171
		
172
	}
173
}
174
</pre>
175
176
Save and confirm that the *speadl-gen* folder contains a Java class generated in the package _tutorial1.client_ named _ClientComponentType_.
177
178
h3. Defining the Ports, their Interfaces and Datatypes
179
180
The Client component will provides a port computing a request and will need the _NotSoNiceServiceType_ to do its job:
181
<pre>
182
import tutorial1.server.interfaces.NotSoNiceServiceType
183
184
namespace tutorial1.client {
185
	
186
	component ClientComponentType {
187
		provides service: ASupeNiceService
188
		requires helper: NotSoNiceServiceType
189
	}
190
	
191
}
192
</pre>
193
194
Don't hesitate to exploit completion (*Ctrl+Space*) and automatic import organiser (*Ctrl+Shift+O*) to type the interfaces names.
195
196
As before, an error appears in the editor because _ASupeNiceService_ does not exists, create it in _tutorial1.client.interfaces_:
197
<pre>
198
package tutorial1.client.interfaces;
199
200
public interface ASupeNiceService {
201
202 1 Anonyme
	public Request compute(Request r);
203
	
204 4 Anonyme
}
205
</pre>
206
207 5 Anonyme
As we can see, we rely on a type named _Request_.
208
Create it in _tutorial1.client.datatypes_:
209 4 Anonyme
<pre>
210
package tutorial1.client.datatypes;
211
212
public class Request {
213
214
	public final boolean b;
215 1 Anonyme
216
	public Request(boolean b) {
217
		this.b = b;
218
	}
219
}
220
</pre>
221 5 Anonyme
222
h3. Implementing the Component
223
224
Create a new Java class in tutorial1.client.impl named ClientImpl.
225
Edit it so that it extends _ClientComponentType_ and resolve all the errors to generate its complete skeleton:
226
<pre>
227
package tutorial1.client.impl;
228
229
import tutorial1.client.ClientComponentType;
230
import tutorial1.client.datatypes.Request;
231
import tutorial1.client.interfaces.ASupeNiceService;
232
233
public class ClientImpl extends ClientComponentType {
234
235
	@Override
236
	protected ASupeNiceService make_service() {
237
		return new ASupeNiceService() {
238
			
239
			@Override
240
			public Request compute(Request r) {
241
				// TODO Auto-generated method stub
242
				return null;
243
			}
244
		};
245
	}
246
247
}
248
</pre>
249
250
Implement the _compute()_ method to call the required port _helper_ to actually do the computation and to return a new _Request_:
251
<pre>
252
public class ClientImpl extends ClientComponentType {
253
254
	@Override
255
	protected ASupeNiceService make_service() {
256
		return new ASupeNiceService() {
257
			@Override
258
			public Request compute(Request r) {
259
				final boolean contrary = requires().helper().contrary(r.b);
260
				return new Request(contrary);
261
			}
262
		};
263
	}
264
}
265
</pre>
266
267
h2. The Composite Component
268
269
In order to use the Client and the Server components together, we need to build a composite component connecting them together.
270
271
h3. Defining the Component
272
273
Create a SpeADL file in _tutorial1_ named _application.speadl_.
274
275
Define the namespace we are going to work in as well as the _Application_ component:
276
<pre>
277
namespace tutorial1 {
278
	component Application {
279
		
280
	}
281
}
282
</pre>
283
284
Save.
285
286
h3. Defining the Composition
287
288
In Application, there will be one Server and one Client for now.
289
Declare them as parts in the Application component:
290
<pre>
291
import tutorial1.client.ClientComponentType
292
import tutorial1.server.ServerComponentType
293
294
namespace tutorial1 {
295
	component Application {
296
		part server: ServerComponentType {
297
			
298
		}
299
		
300
		part client: ClientComponentType {
301
			
302
		}
303
	}
304
}
305
</pre>
306
307
An error is present in the editor on the _client_ name to express that some required ports of client are not bound.
308
Using the *bind ... to ...* keyword by it:
309
<pre>
310
namespace tutorial1 {
311
	component Application {
312
		part server: ServerComponentType {
313
			
314
		}
315
		
316
		part client: ClientComponentType {
317
			bind helper to server.service
318
		}
319
	}
320
}
321
</pre>
322
323
Save.
324
325
h3. Implementing the Component