Changes

Jump to: navigation, search

OSGi : Lab Example

12,066 bytes added, 14:56, 5 October 2011
Voting System (Example for the OSGi Lab)
[[Category:OSGi]]{{Ecl_menu}}__NOTOC__
== Voting System (Example of for the OSGi service system Lab) ==
Let us suppose that you were asked to implement a '''voting system as an OSGi service system'''.
The system should be generic enough so that it could be used for any election. Therefore you will not be using specific candidate names, as they can change for different elections.
As a proof of concept, you will be given three candidates and as the election takes place you have to print the number of votes for each candidate.The code for the entire project could be found at:the code from https://guest:1673852@zenit.senecac.on.ca/svn/ecl500/Lectures/trunk/LAB_OSGi_Example/
== Design and implementation ==
<h4> 1. Define the Bundle Service Interface</h4>
Create the bundle ''cs.ecl.osgi.voting_1.0.1.qualifier''
</source>
<h6> 1.2 Define the MANIFEST.MF for the bundle interface service </h6>
<source lang="xml">
Note: The bundle does not need an activator.
 
--------
 
<h4> 2. Define the Service Provider</h4>
Create the bundle ''cs.ecl.osgi.votingsystem.provider_1.0.0.qualifier''
 
<h6> 2.1 Create the VotingActivator.java </h6>
<source lang="java">
package cs.ecl.osgi.votingsystem.provider;
 
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
 
import cs.ecl.osgi.voting.VotingSystem;
import cs.ecl.osgi.votingsystem.provider.internals.SimpleVotingSystem;
 
public class VotingActivator implements BundleActivator {
 
private static BundleContext context;
 
static BundleContext getContext() {
return context;
}
public void start(BundleContext bundleContext) throws Exception {
VotingActivator.context = bundleContext;
VotingSystem vs = new SimpleVotingSystem();
context.registerService(VotingSystem.class.getName(), vs, null);
System.out.println("Voting System Registered !");
}
 
public void stop(BundleContext bundleContext) throws Exception {
VotingActivator.context = null;
System.out.println("Voting System Stopped !");
}
}
</source>
 
<h6> 2.2 Create the SimpleVotingSystem.java </h6>
 
This is the internal implementation of the service and should be done in a packet that will not be exported.
<source lang="java">
package cs.ecl.osgi.votingsystem.provider.internals;
 
import cs.ecl.osgi.voting.VotingSystem;
 
public class SimpleVotingSystem implements VotingSystem {
 
public static int[] votes = { 0, 0, 0, 0 }; // the test for 3 candidates +
// the invalid vote
 
public int[] countVotesFor(String code) {
 
// simple and trivial implementation of a voting system
String[] votCodes = { "default", "yesno", "yeahnah", "ync" };
for (int i = 0; i < votes.length; i++) {
if (code.equals(votCodes[i]))
++votes[i];
}
return votes;
}
 
}
</source>
 
<h6> 2.3 Define the MANIFEST.MF for the service provider</h6>
 
<source lang="xml">
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Voting System Provider
Bundle-SymbolicName: cs.ecl.osgi.votingsystem.provider
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: cs.ecl.osgi.votingsystem.provider.VotingActivator
Bundle-Vendor: Seneca College - Eclipse Course
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: cs.ecl.osgi.voting,
org.osgi.framework;version="1.3.0"
</source>
 
-----
 
<h4> 3. Define the Service Consumer (the voter)</h4>
 
Create the bundle ''cs.ecl.osgi.votingsystem.client_1.0.0.qualifier''. This bundle will have a GUI for letting the voter to exercise his/her public duties.
 
<h6> 3.1 Create the ClientActivator.java </h6>
<source lang="java">
package cs.ecl.osgi.votingsystem.client;
 
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
 
import cs.ecl.osgi.voting.VotingSystem;
 
public class ClientActivator implements BundleActivator {
 
private static BundleContext context;
private VotingSystem vs;
 
static BundleContext getContext() {
return context;
}
 
public void start(BundleContext bundleContext) throws Exception {
ClientActivator.context = bundleContext;
 
ServiceReference reference = context
.getServiceReference(VotingSystem.class.getName());
if (reference != null) {
vs = (VotingSystem) context.getService(reference);
 
if (vs != null) {
// invoke GUI
VoteDialog.runDialog(vs);
context.ungetService(reference);
} else
System.err.println("the Voting Sytem cannot be used !!!");
} else
System.err.println("the Voting Sytem cannot be found !!!");
 
}
 
public void stop(BundleContext bundleContext) throws Exception {
ClientActivator.context = null;
}
}
</source>
 
If the VotingSystem object is retrieved from the OSGi system, then a dialog box is created and the object is sent to GUI.
 
<h6> 3.2 Create the VoteDialog.java </h6>
<source lang="java">
package cs.ecl.osgi.votingsystem.client;
 
import javax.swing.*;
 
import java.awt.*;
import java.awt.event.*;
import cs.ecl.osgi.voting.VotingSystem;
 
public class VoteDialog extends JPanel {
 
JLabel label;
JFrame frame;
String simpleDialogDesc = "The candidates";
static VotingSystem vs;
static int[] votesSoFar = new int[4];
 
public VoteDialog(JFrame frame) {
super(new BorderLayout());
 
this.frame = frame;
JLabel title;
 
// Create the components.
JPanel choicePanel = createSimpleDialogBox();
 
System.out.println("passed createSimpleDialogBox");
 
title = new JLabel("Click the \"Vote\" button"
+ " once you have selected a candidate.", JLabel.CENTER);
 
label = new JLabel("Vote now!", JLabel.CENTER);
label.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
choicePanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 5, 20));
 
// Lay out the main panel.
add(title, BorderLayout.NORTH);
add(label, BorderLayout.SOUTH);
add(choicePanel, BorderLayout.CENTER);
}
 
void setLabel(String newText) {
label.setText(newText);
}
 
private JPanel createSimpleDialogBox() {
final int numButtons = 4;
JRadioButton[] radioButtons = new JRadioButton[numButtons];
 
final ButtonGroup group = new ButtonGroup();
 
JButton voteButton = null;
 
final String defaultMessageCommand = "default";
final String yesNoCommand = "yesno";
final String yeahNahCommand = "yeahnah";
final String yncCommand = "ync";
 
radioButtons[0] = new JRadioButton(
"<html>Candidate 1: <font color=red>Sparky the Dog</font></html>");
radioButtons[0].setActionCommand(defaultMessageCommand);
 
radioButtons[1] = new JRadioButton(
"<html>Candidate 2: <font color=green>Shady Sadie</font></html>");
radioButtons[1].setActionCommand(yesNoCommand);
 
radioButtons[2] = new JRadioButton(
"<html>Candidate 3: <font color=blue>R.I.P. McDaniels</font></html>");
radioButtons[2].setActionCommand(yeahNahCommand);
 
radioButtons[3] = new JRadioButton(
"<html>Candidate 4: <font color=maroon>Duke the Java<font size=-2></font size> Platform Mascot</font></html>");
radioButtons[3].setActionCommand(yncCommand);
 
for (int i = 0; i < numButtons; i++) {
group.add(radioButtons[i]);
}
 
// Select the first button by default.
radioButtons[0].setSelected(true);
 
voteButton = new JButton("Vote");
 
voteButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String command = group.getSelection().getActionCommand();
 
System.out.println("SELECTION " + command);
 
// ok dialog
if (command == defaultMessageCommand) {
JOptionPane.showMessageDialog(frame,
"This candidate is a dog. Invalid vote.");
votesSoFar = vs.countVotesFor(defaultMessageCommand);
printVotes(votesSoFar);
// yes/no dialog
} else if (command == yesNoCommand) {
int n = JOptionPane
.showConfirmDialog(
frame,
"This candidate is a convicted felon. \nDo you still want to vote for her?",
"A Follow-up Question",
JOptionPane.YES_NO_OPTION);
if (n == JOptionPane.YES_OPTION) {
setLabel("OK. Keep an eye on your wallet.");
printVotes(vs.countVotesFor(yesNoCommand));
} else if (n == JOptionPane.NO_OPTION) {
setLabel("Whew! Good choice.");
} else {
setLabel("It is your civic duty to cast your vote.");
}
 
// yes/no (with customized wording)
} else if (command == yeahNahCommand) {
Object[] options = { "Yes, please", "No, thanks" };
int n = JOptionPane
.showOptionDialog(
frame,
"This candidate is deceased. \nDo you still want to vote for him?",
"A Follow-up Question",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null,
options, options[0]);
if (n == JOptionPane.YES_OPTION) {
setLabel("I hope you don't expect much from your candidate.");
printVotes(vs.countVotesFor(yeahNahCommand));
 
} else if (n == JOptionPane.NO_OPTION) {
setLabel("Whew! Good choice.");
} else {
setLabel("It is your civic duty to cast your vote.");
}
 
// yes/no/cancel (with customized wording)
} else if (command == yncCommand) {
Object[] options = { "Yes!", "No, I'll pass",
"Well, if I must" };
int n = JOptionPane.showOptionDialog(frame,
"Duke is a cartoon mascot. \nDo you "
+ "still want to cast your vote?",
"A Follow-up Question",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options,
options[2]);
if (n == JOptionPane.YES_OPTION) {
setLabel("Excellent choice.");
printVotes(vs.countVotesFor(yncCommand));
 
} else if (n == JOptionPane.NO_OPTION) {
setLabel("Whatever you say. It's your vote.");
} else if (n == JOptionPane.CANCEL_OPTION) {
setLabel("Well, I'm certainly not going to make you vote.");
} else {
setLabel("It is your civic duty to cast your vote.");
}
}
return;
}
 
private void printVotes(int[] votesSoFar) {
for (int i = 0; i < votesSoFar.length; i++)
System.out.println(" Candidate = " + (i + 1) + " has "
+ votesSoFar[i]);
 
}
});
System.out.println("calling createPane");
return createPane(simpleDialogDesc + ":", radioButtons, voteButton);
}
 
private JPanel createPane(String description, JRadioButton[] radioButtons,
JButton showButton) {
int numChoices = radioButtons.length;
JPanel box = new JPanel();
JLabel label = new JLabel(description);
 
box.setLayout(new BoxLayout(box, BoxLayout.PAGE_AXIS));
box.add(label);
 
for (int i = 0; i < numChoices; i++) {
box.add(radioButtons[i]);
}
 
JPanel pane = new JPanel(new BorderLayout());
pane.add(box, BorderLayout.NORTH);
pane.add(showButton, BorderLayout.SOUTH);
System.out.println("returning pane");
return pane;
}
 
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
private static void createAndShowGUI(VotingSystem vs) {
 
// Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
 
// Create and set up the window.
JFrame frame = new JFrame("VoteDialog");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
// Set up the content pane.
Container contentPane = frame.getContentPane();
contentPane.setLayout(new GridLayout(1, 1));
contentPane.add(new VoteDialog(frame));
VoteDialog.vs = vs;
// Display the window.
frame.pack();
frame.setVisible(true);
}
 
public static void runDialog(final VotingSystem vs) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI(vs);
}
});
}
 
}
</source>
 
<h6> 3.3 Define the MANIFEST.MF for the service consumer</h6>
 
<source lang="xml">
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Voting System Client
Bundle-SymbolicName: cs.ecl.osgi.votingsystem.client
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: cs.ecl.osgi.votingsystem.client.ClientActivator
Bundle-Vendor: Seneca College - Eclipse Course
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: cs.ecl.osgi.voting,
org.osgi.framework;version="1.3.0"
</source>
 
-----
 
<h4> 4. Run the Voting System (OSGi Implementation) </h4>
 
In Eclipse define the configuration for the Client bundle and run it.
 
Important Note: While there are some issues ([https://bugs.eclipse.org/bugs/show_bug.cgi?id=212617 a bug in Eclipse]) with multithreaded Java Swing on Mac OX and Unix, we can run the OSGi system, if you remove the „-ws ${target.ws}“ from the launch configuration. Just delete what is highlighted below and the window should start up instantly.
[[File:fixOSGi-swing-Mac.png]]
 
== Results ==
[[Image:Lab-osgi-1.png|300px| ]]
 
The cs.ecl.osgi.votingsystem.client bundle running should display the Voting dialog:
 
[[Image:Lab-osgi-2.png]]

Navigation menu