Architectural Middleware - Center for Software Engineering

Architectural
Middleware
Eric M. Dashofy
CSCI 578 at the University of Southern California
March 24, 2011
Copyright © Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy. All rights reserved.
Software Architecture: Foundations, Theory, and Practice
Review: From Architecture to
Design to Implementation
Problem
Space
Solution
Space
A
D
I
Software Architecture: Foundations, Theory, and Practice
Mapping Architecture to
Implementation


There is a community who advocates Model-Driven
Architecture or Model-Driven Development
Ideal: fully generate implementations
from architectural models


This ideal is rarely feasible
Models are necessarily abstractions
of systems

We can take the modeled
parts and map those,
especially with domain
knowledge
Limit/prevent architectural erosion
A
I
Software Architecture: Foundations, Theory, and Practice
The Gap to Bridge



Architecture Concepts
 Application: Components, connectors, interfaces (at
component level), high-level behaviors
 Style: Connection rules, communication rules,
concurrency rules…
Programming language concepts
 Functions, conditionals, variables, structures,
assignments, classes and objects…
Operating system concepts
 Threads, mutexes, sockets, files and filesystems, IPC
mechanisms…
Software Architecture: Foundations, Theory, and Practice
The Key Question

How do we take architectural concepts and realize them
using the elements that we have in the implementation
world?
Software Architecture: Foundations, Theory, and Practice
A Discussion About Mapping
Architectural Concept
Implementation Concepts
Components
?
Connectors
?
Interfaces
?
Configurations
?
Design Rationale
?
Behavior
?
Concurrency Rules
?
NFPs
?
Software Architecture: Foundations, Theory, and Practice
A Discussion About Mapping
Architectural Concept
Implementation Concepts
Components
Classes, packages, modules, …
Connectors
Software buses, middleware; others?
Interfaces
APIs, protocols
Configurations
Module dependencies, possibly supported by
reflection
Design Rationale
Comments, documentation
Behavior
Translated algorithms
Concurrency Rules
Design patterns using OS-level concurrency
constructs
NFPs
Verified separately through testing, inspections,
etc.
Software Architecture: Foundations, Theory, and Practice
Middleware, Frameworks, and Mappings
(oh my!)


Middleware has a lot of broad definitions
 My definition: any software that sits in between your
application and your Programming Language/OS to
provide services not provided by PL/OS
Architectural frameworks
are a special type
Application
of middleware
“Middleware”
Programming Language &
OS
Software Architecture: Foundations, Theory, and Practice
So what’s the difference?

There’s no clear, bright line

Middleware is designed based on services
 Architectural concerns are secondary

Frameworks are designed based on architectural styles
and patterns
 Services are secondary
Software Architecture: Foundations, Theory, and Practice
Traditional Middleware


Traditional middleware may be based on services, but it
induces an architectural style (Di Nitto and Rosenblum)
Consider CORBA
 Services: Network transparency, language
transparency, OS transparency
 Induced properties: (primarily) synchronous requestresponse point-to-point communication, hiding of
network properties, OO-style topologies
Software Architecture: Foundations, Theory, and Practice
Middleware is Everywhere



Software reuse is alive and well, but perhaps thriving
most at the middleware layer
Software systems today are increasingly built on growing
stacks of underlying middleware – whether we call it
 “Middleware”
 “Frameworks”
 “Component Libraries”
 “Toolkits”
All of it has architectural implications
 Who is really designing your software?
Software Architecture: Foundations, Theory, and Practice
Let’s Discuss some Middleware




“Distributed Systems Middleware”
 DCE, Courier, CORBA, (D)COM(+), RMI, Web Services
Message-Oriented Middleware
 MQ Series, MSMQ, JMS implementations
“Enterprise Service Buses”
Web Application Middleware
 Server-side: JSP, Spring, JSF, Rich Faces, Rails,
Grails, Pylons, TurboGears
 Client-Side: YUI, JQuery, JQuery UI, Dojo, Prototype
Software Architecture: Foundations, Theory, and Practice
Architecture Frameworks


Start from an architectural style (or specific architecture)
 Pipe-and-filter
 Web Services
 C2
 Prism
 Myx
Develop middleware that supports (not necessarily
enforces) the constraints of the style, tailored to support
 Desirable NFPs
 Additional desirable properties/services
Software Architecture: Foundations, Theory, and Practice
A Tale of Four Frameworks




Supporting the evolution of one system (ArchStudio)
over four versions.
Through a fundamental change in architectural style
(C2Myx)
Three research-based (Lightweight C2, Flexible C2, Myx)
One off the shelf (OSGi)
Software Architecture: Foundations, Theory, and Practice
Review: C2 Style
Software Architecture: Foundations, Theory, and Practice
Framework #1: Lightweight C2
Framework




16 classes, 3000
lines of code
Components &
connectors extend
abstract base classes
Concurrency,
queuing handled at
individual
comp/conn level
Messages are
request or
notification objects
16
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
Lightweight C2 Framework


Advantages
 Simple, small
 Control concurrency (or not) at brick level
Disadvantages
 Fixed top, bottom interfaces
 Potential for deadlock
 Single-inheritance limitation of Java
Software Architecture: Foundations, Theory, and Practice
ArchStudio 2
Software Architecture: Foundations, Theory, and Practice
Framework #2: Flexible C2
Framework




73 classes, 8500
lines of code
Uses interfaces
rather than base
classes
Threading policy
for application
is pluggable
Message queuing policy is
also pluggable
19
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
Framework #2: Flexible C2
Framework
20
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
Flexible C2 Framework


Advantages
 Ability to implement and change out message queuing,
threading policies
 …but it turned out not to matter
 However, it did enable the “Steppable Engine”
 Reduced dependency on base classes
 Flexible interfaces permit non-C2-topologies
 Synchronous call support
 Fully serializable control interface
Disadvantages
 Complexity
 Performance
 Certain threading policies (e.g., shepherd threads) difficult to
implement
Software Architecture: Foundations, Theory, and Practice
ArchStudio 3
Software Architecture: Foundations, Theory, and Practice
The Myx Style


Combines useful qualities of C2, Weaves
 (C2) All communication through interfaces
 (C2) No assumption of shared
state
 (C2) Substrate Independence
 Top, bottom interfaces,
enforced layering
 (C2) Asynchronous eventing
 (Weaves) Synchronous
invocations
 (Weaves) Connectors create
threading policy
Relatively hard to deadlock
Software Architecture: Foundations, Theory, and Practice
Myx: Synchronous Patterns
Direct Call
With Proxy
Software Architecture: Foundations, Theory, and Practice
Myx: Asynchronous Patterns
Downward Event
Upward Event
Software Architecture: Foundations, Theory, and Practice
Myx: Nifty Patterns
Software Architecture: Foundations, Theory, and Practice
Framework #3: Myx Framework




62 classes, 2600 lines of code
Minimal required support for brick classes
Pluggable brick loaders
Framework does not get
involved in any
inter-brick
communication
27
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
Myx Framework


Advantages
 Performance: all communication between bricks direct
 Library of reusable connectors
 Pluggable brick loaders permit operation in different contexts
 This becomes important later
 Can support non-Myx topologies
 Fully serializable control interface
 Flexible dynamism
Disadvantages
 Complexity (sorta)
 Monitorability
Software Architecture: Foundations, Theory, and Practice
ArchStudio 4
Software Architecture: Foundations, Theory, and Practice
Worlds are Mixing! OSGi and Myx



Myx was developed as a general-purpose architectural
style
 But was specifically built to support ArchStudio 4
ArchStudio 4 was going to be built in Eclipse
 Considered AS3+Myx but rejected
Eclipse has its own framework (OSGi), inducing a style
Software Architecture: Foundations, Theory, and Practice
Simplified view of OSGi
Bundle
class
Bundle
class
Exposed Pkgs
class
class
class
class
Exposed Pkgs
class
class
Software Architecture: Foundations, Theory, and Practice
Simplified view of OSGi
Bundle
class
Bundle
class
Exposed Pkgs
class
class
class
class
Exposed Pkgs
class
class
Software Architecture: Foundations, Theory, and Practice
Simplified view of OSGi
Bundle
class
Bundle
class
Exposed Pkgs
class
class
class
class
Exposed Pkgs
class
class
Software Architecture: Foundations, Theory, and Practice
Simplified view of OSGi
Bundle
class
Bundle
class
Exposed Pkgs
class
class
class
class
Exposed Pkgs
class
class
Software Architecture: Foundations, Theory, and Practice
OSGi Why?



Provide a system with deployable and undeployable
units
 With well-known, manageable lifecycles
Permit lazy loading of bundles
Permit dynamism
 In a limited way
Software Architecture: Foundations, Theory, and Practice
Integration Attempt #1 (AS4)
Bundle (all exposed)
Software Architecture: Foundations, Theory, and Practice
Handling the Master of the Universe problem
Eclipse framework
Instantiates and controls
ArchEdit
Eclipse
View
Eclipse
Layer
communication
xArchADT
ArchEdit
Myx
Layer
Instantiates and controls
myx.fw architecture implementation framework
Software Architecture: Foundations, Theory, and Practice
Approach #1: Evaluation



(+) “Hatting” solution solves MOU problem
 (-) But it’s a dirty dirty hack
(+) Requires no Eclipse-specific code in Myx framework
(+) Otherwise works OK with Eclipse and permits
deploy/undeploy through the Eclipse Update system
 (-) But the unit of deployment is the whole app!
Software Architecture: Foundations, Theory, and Practice
Integration Attempt #2 (AS5)
“Core” Bundle
“Core” Bundle
class
class
class
“Common”
Bundle
class
class
class
“Common”
Bundle
class
class
Software Architecture: Foundations, Theory, and Practice
Integration Attempt #2 (AS5)
“Core” Bundle
“Core” Bundle
class
class
class
“Common”
Bundle
class
class
class
“Common”
Bundle
class
class
Software Architecture: Foundations, Theory, and Practice
Approach #2: Evaluation



(+) “Hatting” solution still solves MOU problem
 (-) But it’s still a dirty dirty hack
(+) Eclipse-specific code in Myx framework can be
written entirely as extensions in a separate bundle
(+) Deploy/undeploy at the level of an individual
component/connector
Software Architecture: Foundations, Theory, and Practice
Takeaways


Middleware is Everywhere and Everyware
 May have more influence on your architecture than
you do!
 Beware middleware that gives you enticing services,
but does not improve your cognitive control over your
system
Frameworks are tricky to build
 But well-built frameworks can substantially reduce the
burden on app developers
 Concurrency is an area where this can be
especially true
Software Architecture: Foundations, Theory, and Practice
Takeaways (cont.)


Efficient frameworks stay out of the way of intercomponent communication
 Component granularity matters for efficiency
The difficulty in elegantly merging an architecture
framework with existing middleware is very high
 This may be the biggest barrier to the adoption of
strong architectural styles.
Software Architecture: Foundations, Theory, and Practice
BACKUP CHARTS
Software Architecture: Foundations, Theory, and Practice
Implementing Lunar Lander in C2





Framework: Lightweight
C2 framework
Each component has its
own thread of control
Components receive
requests or notifications
and respond with new
ones
Message routing follows
C2 rules
This is a real-time, clock-driven version of Lunar Lander
45
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
Implementing Lunar Lander in C2
(cont’d)



First: Clock component
Sends out a ‘tick’ notification
periodically
Does not respond to any
messages
46
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
import c2.framework.*;
Clock Component
public class Clock extends ComponentThread {
public Clock() {
super.create("clock", FIFOPort.class);
}
public void start() {
super.start();
Thread clockThread = new Thread() {
public void run() {
// Repeat while the application runs
while (true) {
// Wait for five seconds
try {
Thread.sleep(5000);
}
catch (InterruptedException ie) {}
//Send out a tick notification
Notification n = new Notification("clockTick");
send(n);
}
}
};
47
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
import c2.framework.*;
Clock Component
public class Clock extends ComponentThread{
public Clock(){
super.create("clock", FIFOPort.class);
}
public void start(){
clockThread.start();
super.start();
}
Thread clockThread = new Thread(){
void handle (Notification n) {
publicprotected
void run(){
// This
does notruns
handle notifications
//Repeat
whilecomponent
the application
}
while(true){
//Wait for five seconds
protected void handle (Request r) {
try{
// This component does not handle requests
Thread.sleep(5000);
}}
}catch(InterruptedException ie){}
//Send out a tick notification
Notification n = new Notification("clockTick");
send(n);
}
}
};
48
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
Implementing Lunar Lander in C2




Second: GameState
Component
Receives request to update
internal state
Emits notifications of new
game state on request
or when state changes
Does NOT compute new
state
 Just a data store
49
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
GameState Component
import c2.framework.*;
public class GameState extends ComponentThread{
public GameState() {
super.create("gameState", FIFOPort.class);
}
// Internal game state and initial values
int altitude = 1000;
int fuel = 500;
int velocity = 70;
int time = 0;
int burnRate = 0;
boolean landedSafely = false;
50
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
protected void handle (Request r) {
GameState
Component
if (r.name().equals("updateGameState")) {
// Update the internal game state
if (r.hasParameter("altitude")) {
import c2.framework.*;
this.altitude = ((Integer)r.getParameter("altitude")).intValue();
}
public class
GameState extends ComponentThread{
if (r.hasParameter("fuel")) {
this.fuel = ((Integer)r.getParameter("fuel")).intValue();
public GameState(){
}
super.create("gameState",
FIFOPort.class);
if
(r.hasParameter("velocity"))
{
}
this.velocity = ((Integer)r.getParameter("velocity")).intValue();
}
//Internal
game state and initial values
if
(r.hasParameter("time"))
{
int altitude = 1000;
= ((Integer)r.getParameter("time")).intValue();
int fuel this.time
= 500;
}
int velocity
= 70;
if =(r.hasParameter("burnRate"))
{
int time
0;
this.burnRate
= ((Integer)r.getParameter("burnRate")).intValue();
int burnRate
= 0;
boolean} landedSafely = false;
if (r.hasParameter("landedSafely")) {
this.landedSafely = ((Boolean)r.getParameter("landedSafely"))
.booleanValue();
}
// Send out the updated game state
Notification n = createStateNotification();
send(n);
51
}
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
GameState Component
(r.name().equals("getGameState"))
{
protected else
void if
handle(Request
r){
//If a component requests the game state
if(r.name().equals("updateGameState")){
//without
updating
send out the state
//Update
the internal
gameit,
state
if(r.hasParameter("altitude")){
import c2.framework.*;
Notification
n = createStateNotification();
this.altitude
= ((Integer)r.getParameter("altitude")).intValue();
send(n);
}
public class
GameState extends ComponentThread{
}
if(r.hasParameter("fuel")){
}
this.fuel
= ((Integer)r.getParameter("fuel")).intValue();
public GameState(){
}
super.create("gameState",
FIFOPort.class);
protected Notification createStateNotification() {
if(r.hasParameter("velocity")){
}
// Create a =new
notification comprising the
this.velocity
((Integer)r.getParameter("velocity")).intValue();
// current game state
}
//Internal
game state and initial values
if(r.hasParameter("time")){
int altitude
= 1000;
Notification
n = new Notification("gameState");
this.time
= ((Integer)r.getParameter("time")).intValue();
int fuel = 500;
n.addParameter("altitude", altitude);
}
int velocity
= 70;
n.addParameter("fuel",
fuel);
if(r.hasParameter("burnRate")){
int time
= 0;
n.addParameter("velocity",
velocity);
this.burnRate
= ((Integer)r.getParameter("burnRate")).intValue();
int burnRate
= 0;
n.addParameter("time", time);
boolean} landedSafely = false;
n.addParameter("burnRate", burnRate);
if(r.hasParameter("landedSafely")){
n.addParameter("landedSafely",
landedSafely);
this.landedSafely
= ((Boolean)r.getParameter("landedSafely"))
return n;
.booleanValue();
} }
protected
void
handlegame
(Notification
n) {
//Send
out the
updated
state
// This component
does not handle notifications
Notification
n = createStateNotification();
}
send(n);
52
} }
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
Implementing Lunar Lander in C2



Third: GameLogic
Component
Receives notifications of
game state changes
Receives clock ticks
 On clock tick notification,
calculates new state
and sends request up
53
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
GameLogic Component
import c2.framework.*;
public class GameLogic extends ComponentThread {
public GameLogic() {
super.create("gameLogic", FIFOPort.class);
}
// Game constants
final int GRAVITY = 2;
// Internal state values for computation
int altitude = 0;
int fuel = 0;
int velocity = 0;
int time = 0;
int burnRate = 0;
public void start() {
super.start();
Request r = new Request("getGameState");
send(r);
}
54
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
GameLogic
Component
protected void handle
(Notification n) {
if (n.name().equals("gameState")) {
import c2.framework.*;
if (n.hasParameter("altitude")) {
this.altitude =
public class GameLogic
extends ComponentThread{
((Integer)n.getParameter("altitude")).intValue();
public GameLogic(){
}
super.create("gameLogic",
FIFOPort.class);
if (n.hasParameter("fuel"))
{
}
this.fuel =
((Integer)n.getParameter("fuel")).intValue();
//Game constants
}
final int GRAVITY
= 2;
if (n.hasParameter("velocity"))
{
this.velocity =
//Internal state
values for computation
((Integer)n.getParameter("velocity")).intValue();
int altitude
} = 0;
int fuel = if
0; (n.hasParameter("time")) {
int velocity this.time
= 0;
=
int time = 0; ((Integer)n.getParameter("time")).intValue();
int burnRate
} = 0;
if (n.hasParameter("burnRate")) {
public void start(){
this.burnRate =
super.start();
((Integer)n.getParameter("burnRate")).intValue();
Request r} = new Request("getGameState");
send(r);
}
}
55
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
GameLogic
Component
protected void handle(Notification
n){
if(n.name().equals("gameState")){
else
if if(n.hasParameter("altitude")){
(n.name().equals("clockTick")) {
import
c2.framework.*;
// Calculate
new lander
this.altitude
= state values
actualBurnRate
= burnRate;
((Integer)n.getParameter("altitude")).intValue();
public int
class
GameLogic
extends
ComponentThread{
if
(actualBurnRate
>
fuel)
{
}
public GameLogic(){
//Ensure
we don’t burnFIFOPort.class);
more fuel than we have
if(n.hasParameter("fuel")){
super.create("gameLogic",
actualBurnRate
this.fuel == fuel;
}
}
((Integer)n.getParameter("fuel")).intValue();
}
//Game constants
time + =1;2;
if(n.hasParameter("velocity")){
finaltime
int =GRAVITY
altitudethis.velocity
= altitude - =velocity;
velocity
=((Integer)n.getParameter("velocity")).intValue();
((velocity
GRAVITY) * 10 –
//Internal
state
values for+ computation
actualBurnRate
* 2) / 10;
} = 0;
int altitude
fuel ==if(n.hasParameter("time")){
fuel - actualBurnRate;
int fuel
0;
=
int velocity this.time
= 0;
// Determine
if we landed (safely)
int time
= 0; ((Integer)n.getParameter("time")).intValue();
boolean
= false;
} landedSafely
int burnRate
= 0;
if (altitude
<= 0) {
if(n.hasParameter("burnRate")){
= 0;
this.burnRate
=
public altitude
void start(){
if (velocity
<= 5) {
((Integer)n.getParameter("burnRate")).intValue();
super.start();
= true;
RequestlandedSafely
r} = new Request("getGameState");
} }
send(r);
}
}
56
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
GameLogic
Component
protected void handle(Notification
n){
if(n.name().equals("gameState")){
else if(n.name().equals("clockTick")){
if(n.hasParameter("altitude")){
import //Calculate
c2.framework.*;
new lander= state values
this.altitude
int actualBurnRate
= burnRate;
((Integer)n.getParameter("altitude")).intValue();
public if(actualBurnRate
class }GameLogic extends
ComponentThread{
> fuel){
public //Ensure
GameLogic(){
Request
= newburn
Request("updateGameState");
werdon’t
more fuel than we have
if(n.hasParameter("fuel")){
super.create("gameLogic",
FIFOPort.class);
r.addParameter("time",
time);
actualBurnRate
this.fuel == fuel;
}
r.addParameter("altitude",
altitude);
}
((Integer)n.getParameter("fuel")).intValue();
r.addParameter("velocity",
velocity);
}
//Game
constants
r.addParameter("fuel",
fuel);
time =
time + 1;
if(n.hasParameter("velocity")){
finalaltitude
int r.addParameter("landedSafely",
GRAVITY
= 2;
landedSafely);
= altitude
- =velocity;
this.velocity
send(r);
velocity
=((Integer)n.getParameter("velocity")).intValue();
((velocity + GRAVITY) * 10 –
//Internal
state
values
for/ computation
} }
actualBurnRate
* 2)
10;
int altitude
=
0;
}
fuel
=if(n.hasParameter("time")){
fuel - actualBurnRate;
int fuel = 0;this.time =
int velocity
= ((Integer)n.getParameter("time")).intValue();
0;
protected
void
handle
(Request
r) {
//Determine
if we
landed
(safely)
int time
= }0;landedSafely
//This
component does
not handle requests
boolean
= false;
int burnRate
= 0;<= 0){
}
if(altitude
if(n.hasParameter("burnRate")){
} altitude
= 0;
this.burnRate
=
public if(velocity
void start(){
<= 5){
((Integer)n.getParameter("burnRate")).intValue();
super.start();
landedSafely
= true;
}
Request
r
=
new
Request("getGameState");
} }
send(r);
}
}
57
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
Implementing Lunar Lander in C2



Fourth: GUI Component
Reads burn rates from
user and sends them
up as requests
Receives notifications of
game state changes and
formats them to console
58
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
GUI Component
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import c2.framework.*;
public class GUI extends ComponentThread{
public GUI() {
super.create("gui", FIFOPort.class);
}
public void start() {
super.start();
Thread t = new Thread(){
public void run(){
processInput();
}
};
t.start();
}
59
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
public void processInput() {
System.out.println("Welcome to Lunar Lander");
try{
BufferedReader inputReader = new BufferedReader(
new InputStreamReader(System.in));
import java.io.BufferedReader;
import java.io.IOException;
int burnRate = 0;
import java.io.InputStreamReader;
do {
System.out.println("Enter burn rate or <0 to quit:");
import c2.framework.*;
try {
= inputReader.readLine();
public class GUI String
extendsburnRateString
ComponentThread{
public GUI(){ burnRate = Integer.parseInt(burnRateString);
GUI Component
super.create("gui", FIFOPort.class);
Request r = new Request("updateGameState");
}
r.addParameter("burnRate", burnRate);
send(r);
public void start(){
}
super.start();
(NumberFormatException nfe) {
Thread t = catch
new Thread(){
burn rate.");
public voidSystem.out.println("Invalid
run(){
}
processInput();
} while(burnRate >= 0);
}
inputReader.close();
};
}
t.start();
catch (IOException ioe) {
}
ioe.printStackTrace();
}
}
60
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
public void processInput(){
System.out.println("Welcome to Lunar Lander");
try{
protected void handle (Notification n) {
BufferedReader inputReader = new BufferedReader(
if
(n.name().equals("gameState"))
{
import java.io.BufferedReader;
new InputStreamReader(System.in));
importSystem.out.println();
java.io.IOException;
System.out.println("New
game state:");
import java.io.InputStreamReader;
int burnRate = 0;
do{
if
(n.hasParameter("altitude"))
{
import c2.framework.*;
System.out.println("Enter burn rate or <0 to quit:");
System.out.println(" Altitude: " + n.getParameter("altitude"));
try{
}
public class GUI String
extendsburnRateString
ComponentThread{
= inputReader.readLine();
if
(n.hasParameter("fuel"))
{
public GUI(){ burnRate = Integer.parseInt(burnRateString);
System.out.println("
Fuel: " + n.getParameter("fuel"));
super.create("gui",
FIFOPort.class);
}
}
Request r = new Request("updateGameState");
if (n.hasParameter("velocity")) {
r.addParameter("burnRate", burnRate);
System.out.println("
Velocity: " + n.getParameter("velocity"));
public void start(){
send(r);
}
super.start();
}
if
(n.hasParameter("time"))
{
Thread t = catch(NumberFormatException
new Thread(){
nfe){
System.out.println("
Time:
"
+
n.getParameter("time"));
public voidSystem.out.println("Invalid
run(){
burn rate.");
} processInput();
}
if
(n.hasParameter("burnRate"))
{
}
}while(burnRate >= 0);
Burn rate: " + n.getParameter("burnRate"));
}; System.out.println("
inputReader.close();
}
t.start();
}
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
GUI Component
61
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
public void processInput(){
System.out.println("Welcome to Lunar Lander");
try{
protectedifvoid
handle(Notification n){ {
(n.hasParameter("altitude"))
BufferedReader
inputReader = new BufferedReader(
if(n.name().equals("gameState")){
int
altitude
=
import java.io.BufferedReader;
new InputStreamReader(System.in));
System.out.println();
((Integer)n.getParameter("altitude")).intValue();
import java.io.IOException;
System.out.println("New
state:");
if
0)game
{
import java.io.InputStreamReader;
int(altitude
burnRate <=
= 0;
boolean landedSafely =
do{
if(n.hasParameter("altitude")){
((Boolean)n.getParameter("landedSafely"))
import c2.framework.*;
System.out.println("Enter
burn rate or <0 to quit:");
System.out.println("
Altitude: " + n.getParameter("altitude"));
.booleanValue();
try{
}
if String
(landedSafely)
{
public class GUI
extends
ComponentThread{
burnRateString
= inputReader.readLine();
if(n.hasParameter("fuel")){
have landed safely.");
public GUI(){ System.out.println("You
burnRate = Integer.parseInt(burnRateString);
System.out.println("
Fuel:
"
+
n.getParameter("fuel"));
}
super.create("gui",
FIFOPort.class);
}
else
{
}
Request r = new Request("updateGameState");
if(n.hasParameter("velocity")){
System.out.println("You
have
crashed.");
r.addParameter("burnRate",
burnRate);
System.out.println("
Velocity:
"
+
n.getParameter("velocity"));
} send(r);
public void start(){
}
System.exit(0);
super.start();
}
if(n.hasParameter("time")){
}
Thread t = catch(NumberFormatException
new Thread(){
nfe){
System.out.println("
Time:
"
+
n.getParameter("time"));
}
public voidSystem.out.println("Invalid
run(){
burn rate.");
} processInput();
}
}
if(n.hasParameter("burnRate")){
}}
}while(burnRate >= 0);
Burn rate: " + n.getParameter("burnRate"));
}; System.out.println("
inputReader.close();
}protected void handle (Request r) {
t.start();
}
//This
component does
not handle requests
}
catch(IOException
ioe){
}
ioe.printStackTrace();
}
}
}
GUI Component
62
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
Implementing Lunar Lander in C2


Lastly, main program
Instantiates and connects
all elements of the system
63
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
import c2.framework.*;
Main Program
public class LunarLander {
public static void main(String[] args) {
// Create the Lunar Lander architecture
Architecture lunarLander = new
SimpleArchitecture("LunarLander");
// Create
Component
Component
Component
Component
the components
clock = new Clock();
gameState = new GameState();
gameLogic = new GameLogic();
gui = new GUI();
// Create the connectors
Connector bus = new ConnectorThread("bus");
// Add the components and connectors to the architecture
lunarLander.addComponent(clock);
lunarLander.addComponent(gameState);
lunarLander.addComponent(gameLogic);
lunarLander.addComponent(gui);
lunarLander.addConnector(bus);
64
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Software Architecture: Foundations, Theory, and Practice
import c2.framework.*;
Main Program
public class LunarLander{
public static void main(String[] args){
//Create the Lunar Lander architecture
Architecture lunarLander = new
SimpleArchitecture("LunarLander");
// Create the welds (links) between components and
// connectors
//Create
the components
lunarLander.weld(clock,
bus);
Component
clock = new Clock();
lunarLander.weld(gameState,
bus);
Component
gameState = new GameState();
lunarLander.weld(bus,
gameLogic);
Component
gameLogic = new GameLogic();
lunarLander.weld(bus,
gui);
Component gui = new GUI();
//Start the application
//Create
the connectors
lunarLander.start();
Connector
bus = new ConnectorThread("bus");
}
}
//Add the components and connectors to the architecture
lunarLander.addComponent(clock);
lunarLander.addComponent(gameState);
lunarLander.addComponent(gameLogic);
lunarLander.addComponent(gui);
lunarLander.addConnector(bus);
65
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.