SpeADL Minus Tutorial » Historique » Révision 14
« Précédent |
Révision 14/20
(diff)
| Suivant »
Anonyme, 15/10/2014 10:31
SpeADL⁻ Tutorial¶
- Contenu
- SpeADL⁻ Tutorial
- Wiki Page Resources
This is a tutorial for SpeADL⁻: creating a project, defining simple and composite components, implementing components.
An Eclipse project with the code is provided at the end of this page.
Objectives¶
The objective of this tutorial is to understand the basic workflow to follow when developing component-oriented applications with SpeADL in Eclipse/MAY.
We will create a simple composition of two components connected together following a typical client-server configuration.
The server will provide a service that will be used by the client.
They will be composed together in a big component.
An Java Application will be created to show how to execute the composition from Java.
A very simple GUI will be used to illustrate a self-contained component acting as an application.
Installing Eclipse and MAY¶
This procedure is described on this page.
Creating a New Project¶
First, we must create a project to work.
In Eclipse, go to the menus : File / New / Java Project.
Enter Tutorial 1 as the project name, verify that the execution environment JRE is 1.5 or above.
As a start, create a package in the src folder called tutorial1.
The Server Component¶
Organisation¶
Create the following hierarchy of packages (See this best practice for details on the matter):- tutorial1.server
- impl
- interfaces
Defining the Component¶
Create a SpeADL file:- Right-click on tutorial1.server and select New / File.
- Enter server.speadl as the file name.
Define the namespace we are going to work in as well as the Server component:
namespace tutorial1.server {
component ServerComponentType {
}
}
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.
Defining a Port and its Interface¶
The Server component will provide a port whose interface contains one method to give the contrary of a boolean.
Add it to the component declaration:
namespace tutorial1.server {
component ServerComponentType {
provides service: NotSoNiceServiceType
}
}
Because the NotSoNiceServiceType interface does not yet exist, there is an error in the SpeADL editor.
We will store the interface in the tutorial1.server.interfaces package.
Either create it by hand or use the Quick Fix proposed by SpeADL editor by hovering on the error.
package tutorial1.server.interfaces;
public interface NotSoNiceServiceType {
public boolean contrary(boolean b);
}
Save, and go back to the SpeADL editor for server.speadl.
Call the automatic import organiser with Ctrl+Shift+O.
Confirm that an import was added on top of the SpeADL file and save.
Implementing the Component¶
Create a new Java class in tutorial1.server.impl named ServerImpl, and edit it so that it extends ServerComponentType:
public class ServerImpl extends ServerComponentType {
}
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.
Because there is abstract method to implement in ServerComponentType, there is errors in the Java editor.
Use the Quick Fix Add unimplemented methods by hovering on the error on the class name ServerImpl:
public class ServerImpl extends ServerComponentType {
@Override
protected NotSoNiceServiceType make_service() {
// TODO Auto-generated method stub
return null;
}
}
Remove the TODO line and replace null with new NotSoNiceServiceType, call completion (Ctrl+Space) and choose NotSoNiceServiceType() Anonymous Inner Type:
public class ServerImpl extends ServerComponentType {
@Override
protected NotSoNiceServiceType make_service() {
return new NotSoNiceServiceType() {
@Override
public boolean contrary(boolean b) {
// TODO Auto-generated method stub
return false;
}
};
}
}
Remove the TODO line and replace return false; by return !b;:
package tutorial1.server.impl;
import tutorial1.server.ServerComponentType;
import tutorial1.server.interfaces.NotSoNiceServiceType;
public class ServerImpl extends ServerComponentType {
@Override
protected NotSoNiceServiceType make_service() {
return new NotSoNiceServiceType() {
@Override
public boolean contrary(boolean b) {
return !b;
}
};
}
}
The Client Component¶
Organisation¶
Create the following hierarchy of packages:- tutorial1.client
- impl
- interfaces
- datatypes
Defining the Component¶
Create a SpeADL file in tutorial1.client named client.speadl.
Define the namespace we are going to work in as well as the Client component:
namespace tutorial1.client {
component ClientComponentType {
}
}
Save and confirm that the speadl-gen folder contains a Java class generated in the package tutorial1.client named ClientComponentType.
Defining the Ports, their Interfaces and Datatypes¶
The Client component will provides a port computing a request and will need the NotSoNiceServiceType to do its job:
import tutorial1.server.interfaces.NotSoNiceServiceType
namespace tutorial1.client {
component ClientComponentType {
provides service: ASupeNiceService
requires helper: NotSoNiceServiceType
}
}
Don't hesitate to exploit completion (Ctrl+Space) and automatic import organiser (Ctrl+Shift+O) to type the interfaces names.
As before, an error appears in the editor because ASupeNiceService does not exists, create it in tutorial1.client.interfaces:
package tutorial1.client.interfaces;
public interface ASupeNiceService {
public Request compute(Request r);
}
As we can see, we rely on a type named Request.
Create it in tutorial1.client.datatypes:
package tutorial1.client.datatypes;
public class Request {
public final boolean b;
public Request(boolean b) {
this.b = b;
}
}
Implementing the Component¶
Create a new Java class in tutorial1.client.impl named ClientImpl.
Edit it so that it extends ClientComponentType and resolve all the errors to generate its complete skeleton:
package tutorial1.client.impl;
import tutorial1.client.ClientComponentType;
import tutorial1.client.datatypes.Request;
import tutorial1.client.interfaces.ASupeNiceService;
public class ClientImpl extends ClientComponentType {
@Override
protected ASupeNiceService make_service() {
return new ASupeNiceService() {
@Override
public Request compute(Request r) {
// TODO Auto-generated method stub
return null;
}
};
}
}
Implement the compute() method to call the required port helper to actually do the computation and to return a new Request:
public class ClientImpl extends ClientComponentType {
@Override
protected ASupeNiceService make_service() {
return new ASupeNiceService() {
@Override
public Request compute(Request r) {
final boolean contrary = requires().helper().contrary(r.b);
return new Request(contrary);
}
};
}
}
The Composite Component¶
In order to use the Client and the Server components together, we need to build a composite component connecting them together.
Defining the Component¶
Create a SpeADL file in tutorial1.composite named composite.speadl.
Define the namespace we are going to work in as well as the CompositeComponent component:
namespace tutorial1.composite {
component CompositeComponent {
}
}
Save.
Defining the Composition¶
In CompositeComponent, there will be one server and one client for now.
Declare them as parts in the composite component:
import tutorial1.client.ClientComponentType
import tutorial1.server.ServerComponentType
namespace tutorial1.composite {
component CompositeComponent {
part server: ServerComponentType {
}
part client: ClientComponentType {
}
}
}
An error is present in the editor on the client name to express that some required ports of client are not bound.
Using the bind ... to ... keyword by it:
namespace tutorial1.composite {
component CompositeComponent {
part server: ServerComponentType {
}
part client: ClientComponentType {
bind helper to server.service
}
}
}
Save.
Implementing the Component¶
Create a new Java class in tutorial1.composite.impl named CompositeImpl.
Edit it so that it extends CompositeComponent and resolve all the errors to generate its complete skeleton:
package tutorial1.composite.impl;
import tutorial1.CompositeComponent;
import tutorial1.client.ClientComponentType;
import tutorial1.server.ServerComponentType;
public class CompositeImpl extends CompositeComponent {
@Override
protected ServerComponentType make_server() {
// TODO Auto-generated method stub
return null;
}
@Override
protected ClientComponentType make_client() {
// TODO Auto-generated method stub
return null;
}
}
For the server part, return a new instance of the implementation ServerImpl , and the same for the client part with ClientImpl:
public class CompositeImpl extends CompositeComponent {
@Override
protected ServerComponentType make_server() {
return new ServerImpl();
}
@Override
protected ClientComponentType make_client() {
return new ClientImpl();
}
}
Creating an Application¶
We can now instantiate this composition in an application.
Create a Java class named Application in tutorial1 with a static void main() method.
Create an instance of the composite component in it:
package tutorial1;
import tutorial1.composite.CompositeComponent;
import tutorial1.composite.impl.CompositeImpl;
public class Application {
public static void main(String[] args) {
CompositeComponent.Component component = new CompositeImpl().newComponent();
}
}
Unfortunately, we forgot to provide a port on this component: it is thus impossible for us to access to the client component inside.
Adding a Delegating Port¶
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.
Edit the SpeADL file composite.speadl to add such a delegation:
import tutorial1.client.ClientComponentType
import tutorial1.client.interfaces.ASupeNiceService
import tutorial1.server.ServerComponentType
namespace tutorial1.composite {
component CompositeComponent {
provides service: ASupeNiceService = client.service
part server: ServerComponentType {
}
part client: ClientComponentType {
bind helper to server.service
}
}
}
This is all that is needed for it to work.
Running the Application¶
Edit the Application class to call the newly added port:
package tutorial1;
import tutorial1.client.datatypes.Request;
import tutorial1.composite.CompositeComponent;
import tutorial1.composite.impl.CompositeImpl;
public class Application {
public static void main(String[] args) {
CompositeComponent.Component component = new CompositeImpl().newComponent();
Request input = new Request(true);
Request output = component.service().compute(input);
System.out.println(output.b);
}
}
Right-click on the main() method and select Run As / Java Application.
Confirm that false is printed in the console as expected.
A Self-Contained Application¶
It can be desired that a composition of component is considered a self-contained application, for example with a GUI to execute the client.
We will use that example to illustrate the use of the start() method.
A GUI Component¶
First, let's create a GUI component: create a file gui.speadl in the package tutorial1.gui containing the definition of our component:
import tutorial1.client.interfaces.ASupeNiceService
namespace tutorial1.gui {
component GUIComponent {
requires service: ASupeNiceService
}
}
Component Implementation¶
Then the implementation GUIImpl in Java in the package tutorial1.gui.impl exploiting the required port:
package tutorial1.gui.impl;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import tutorial1.client.datatypes.Request;
import tutorial1.gui.GUIComponent;
public class GUIIMpl extends GUIComponent {
@Override
protected void start() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final JFrame f = new JFrame();
final JPanel pnl = new JPanel(new GridLayout(3,2));
pnl.add(new JLabel("Input True? "));
final JCheckBox tf = new JCheckBox();
pnl.add(tf);
pnl.add(new JLabel("Output: "));
final JTextField tf2 = new JTextField(5);
tf2.setEditable(false);
pnl.add(tf2);
final JButton bt = new JButton("Compute!");
bt.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Request res = requires().service().compute(new Request(tf.isSelected()));
tf2.setText(""+res.b);
}
});
pnl.add(bt);
f.getContentPane().add(BorderLayout.NORTH, pnl);
f.pack();
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}
Composite Implementation¶
We will now create a component named CompositeGUIComponent similar to CompositeComponent to use this new component.
import tutorial1.client.ClientComponentType
import tutorial1.gui.GUIComponent
import tutorial1.server.ServerComponentType
namespace tutorial1.compositegui {
component CompositeGUIComponent {
part server: ServerComponentType
part client: ClientComponentType {
bind helper to server.service
}
part gui: GUIComponent {
bind service to client.service
}
}
}
Create an implementation CompositeGUIImpl:
package tutorial1.compositegui.impl;
import tutorial1.client.ClientComponentType;
import tutorial1.client.impl.ClientImpl;
import tutorial1.compositegui.CompositeGUIComponent;
import tutorial1.gui.GUIComponent;
import tutorial1.gui.impl.GUIIMpl;
import tutorial1.server.ServerComponentType;
import tutorial1.server.impl.ServerImpl;
public class CompositeGUIImpl extends CompositeGUIComponent {
@Override
protected ServerComponentType make_server() {
return new ServerImpl();
}
@Override
protected ClientComponentType make_client() {
return new ClientImpl();
}
@Override
protected GUIComponent make_gui() {
return new GUIIMpl();
}
}
And the Application2 class:
package tutorial1;
import tutorial1.compositegui.impl.CompositeGUIImpl;
public class Application2 {
public static void main(String[] args) {
new CompositeGUIImpl().newComponent();
}
}
And finally run it to test the GUI.
Confirm that when the chekbox is checked, compute fill the the output field with false, and the inverse.
Conclusion¶
The tutorial for SpeADL⁻ finishes here.
Wiki Page Resources¶
Mis à jour par Anonyme il y a plus de 11 ans · 20 révisions