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 |