This tutorial will show you how to create a SMAGs project and how to define platform independent types, ports, component types. Furthermore it will show how to extend those platform independent types to platform specific artifacts and how the code generation works.
In this example we create a simple news feed aggregator, allowing us the show news from several sources. Our solution will contain 2 components (a news provider and a news display). The news display will collect news from several sources and display them (in our case, on the console).
1. Setup
Install the latest version of the SMAGs Tools and launch Eclipse. Check out the latest version of the SMAGs Runtime Environment (SmagRE) and import it in your workspace. Create a new SMAGs project, using the SMAGs project wizard.
When you create a new SMAGs project you can setup the project name, the default namespace (for the generated code) and the application name. The application name is the identifier of your application within the SMAGs runtime system. Furthermore you can decide which modeling artifacts are created. By default all three relevant types of artifacts are created:
- Meta Architecture (.madl): Definition of platform independent modeling elements
- Application (.app): Definition of platform specific modeling elements
- Adaptation (.sal): Definition of situation detection, inference and adaptation rules
In our example we call our project “FirstExample” and keep all default settings. Afterwards the project is created and preconfigured. Furthermore, the three modeling files and a main class is generated. The project itself is a standard Java-Project with a dependency to the SmagRE (Runtime Environment) project.
2. Defining the Meta Architecture
The Meta Architecture is a platform independent definition of types, components and their interfaces. SMAGs differentiates between normal components and sensor components (delivering data for adaptation) and differentiates between normal ports and event ports. A normal port is a collection of methods, parameters and dependencies to other ports. Components can provide ports and can requires them (with different cardinalities). Event ports encapsulate the firing of events, from components offering an event port. Those component who require an event port, get notified when a certain event occurs. SMAGs provides tools for editing the necessary artifacts. The generated firstExample.madl file contains predefined sections for the required modeling elements (e.g., sensor units, type libraries etc.).
In our news aggregator we want to visualize news. Because news are complex types (title, body, source, author etc.) we need to define custom types. Open the firstExample.madl file and create a new type library called NewsTypes. Define an enum NewsCategory and a complex type News with the corresponding properties (id, title, message etc.).
Now we need to define the interfaces of the components. In our example we simply need one interface for getting news. In this case we need a normal port with the name INewsProvider, containing one method getNews.
The next step is to define the platform independent definition of components. In our example we define two component types a NewsRepository component offering the INewsProvider port and NewsDisplay requiring this port.
3. Defining the Application
A SMAGs Application implements one or several Meta Architectures by providing platform specific implementation for the platform independent types, defined in the Meta Architecture. In our example we must simply provide the implementations for the defined component types.
Open the firstExample.app file and create the two components JDummyNewsRepository (implementing the NewsRepository component type) and a JConsoleNewsDisplay (implementing the NewsDisplay component type).
Next, we need to define an initialization script, which gets executed on startup of the application. In our case we want to instantiate both components and connect the corresponding port-type offers/requirements. Therefore, we create a new instance of the component JDummyNewsRepository called repo and a new instance of the component JConsoleNewsDisplay called display. Afterwards we connect the required port-type INewsProvider of the component instance display to the offer of this port type of the component instance repo.
4. Generating Code
For this simple example we have created all necessary modeling elements. Now we can generate the code stubs. Therefore, right-click on the firstExample.app file and select the option “Generate SMAGs Code”.
In the wizard select those files, whose content should be generated. Because in the standard generated files, several libary files were imported, the popup shows them as generation sources. Only check those files that you created, because the SMAGs Runtime Environment already contains the generated code for the other artifacts. In our case it is the FirstExample (app file) and the FirstExampleMetaArchitecture. Click Finish to generate the code.
Now, several Java classes are generated. All files in the src-gen folder should not be touched, since they get overwritten every time you generate code. All edits must be made to the classes in the src folder. The types package contains all user defined types and the components package the stubs for our components.
For every component several stubs are generated. Each component implements a setup and a destroy method, which get executed when a component instance is integrated in the application or removed from the application. Furthermore, for every required port-type an event handler is generated for the notification, when a port-type is bound or unbound. Components may contain parameter which may be changed externally during runtime. Therefore, an event handler method can be used to handle parameter changes. For every provided port the stubs for the corresponding methods are generated.
5. Implementing the business functionality
Now we want to implement the real business functionality. We start with the implementation of the JConsoleNewsDisplay component. In our example we want to display the news, when the component gets imported in our application. Therefore, we put the display logic inside the setup method. In the abstract base class (AbstractNewsDisplay – representing the information of the component type NewsDisplay) a getter for the required INewsRepository port-type was generated. We can call the getINewsProvider() method to get all connected INewsProvider components. We iterate over all news provider, fetch all news and print the news on the console.
Next, we need to implement the JDummyNewsProvider component. In our example this component will always return a static list of news. Of course, we sources etc. could be called here.
6. Starting the Application
The project template already generated a class with a main method called firstExample.Starter. You have to uncomment the line:
In the next tutorial you will learn how to use ports to adjust the default behavior of components.
Download Source