Teams Winter 2011/team9/Lab2

From CDOT Wiki
Jump to: navigation, search

Overview

For our OSGi tutorial we will be creating a simple task manager that will allow you to add and delete new tasks in a small java interface.

Creating the Service Interface

The first step in our OSGi tutorial will be creating our TaskManager interface. Create a new plug-in project by right-clicking the Package Explorer and selecting New -> Project... -> Plug-in Project, then name it cs.ecl.osgi.taskmanager and make sure that you select the OSGi Equinox as your platform then press Next.

Taskmanager 00.png


Since we will not be needing an activator for the service interface, make sure to uncheck the Generate an activator... option.

Taskmanager 01.png


Now, right-click your cs.ecl.osgi.taskmanager package and create a new interface called TaskManager. Then enter the following:

package cs.ecl.osgi.taskmanager;

public interface TaskManager {
    boolean addTask(String name);
    String removeTask(int index);
}

Before going on to our next step we must define our MANIFEST.MF file to export the package we just created. To do this, double-click the MANIFEST.MF file and select the Runtime tab. From here, you just select Add... and then find our package cs.ecl.osgi.taskmanager.

Taskmanager 02.png


Implementing the Service Provider

Now we will be creating another project but this time the project will be used as the service provider. Like our example above, create a new plug-in project and name it cs.ecl.osgi.tasksystem. This time make sure that you check the Generate an activator... option on the second step of the create project screen.


Tasksystem 00.png

We will now be using the service interface we created above, so double-click the MANIFEST.MF file and go to the Dependencies tab. Now add the following dependencies as shown below. Use the Add... options and filter to search for the package.


Tasksystem 01.png


We will now create a class to act as the system for adding and removing tasks. Essentially, this will be the core of our service. In our example, we decided to keep this class in a separate package so, let's do this by right-clicking on the cs.ecl.osgi.tasksystem package and selecting New -> Package; name this new package cs.ecl.osgi.tasksystem.internals.

Now within the new package, create a new class called SimpleTaskSystem that implements the service interface, TaskManager, that we created before. The class should look like this:

package cs.ecl.osgi.tasksystem.internals;

import java.util.ArrayList;
import java.util.List;

import cs.ecl.osgi.taskmanager.TaskManager;

public class SimpleTaskSystem implements TaskManager {
   
    public static List<String> tasks = new ArrayList<String>();
    public static List<Boolean> complete = new ArrayList<Boolean>();
   
    @Override
    public boolean addTask(String name) {
        boolean success = false;
        if(tasks.add(name)) {
            complete.add(false);
            success = true;
        }
        return success;
    }
    @Override
    public String removeTask(int index) {
        String taskName = "";
        taskName = tasks.remove(index);
        if( taskName != "") {
            complete.remove(index);
        }
        return taskName;
    }
}

Using the Package Explorer find the Activator.java class and open it by double-clicking. Now we will implement the service provider (TaskManagerSystem) we just created. The code should look like this:

package cs.ecl.osgi.tasksystem;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import cs.ecl.osgi.taskmanager.TaskManager;
import cs.ecl.osgi.tasksystem.internals.SimpleTaskSystem;

public class Activator implements BundleActivator {

    private static BundleContext context;

    static BundleContext getContext() {
        return context;
    }

    /*
     * (non-Javadoc)
     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
     */
    public void start(BundleContext bundleContext) throws Exception {
        Activator.context = bundleContext;
       
        TaskManager tm = new SimpleTaskSystem();
        context.registerService(TaskManager.class.getName(), tm, null);
        System.out.println("Task Manager registered!");
    }

    /*
     * (non-Javadoc)
     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
     */
    public void stop(BundleContext bundleContext) throws Exception {
        Activator.context = null;
        System.out.println("Task Manager stopped!");
    }

}

Creating the Service Consumer

Now that we have the service finished, we need to create a user interface that will act as the service consumer. This basically refers to something that will be using our service, task system. To start, let's create another Plug-in Project as we've done before and name it cs.ecl.osgi.tasksystem.client. Once again, make sure that we generate an activator for this new project.

Now we will be adding the dependencies again. As shown in the previous step, make sure that the following plug-ins are required.

Tasksystemclient 00.png


Let's create the graphical user interface (GUI) for the project. Create a new class that looks like the following:

package cs.ecl.osgi.tasksystem.client;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import cs.ecl.osgi.taskmanager.TaskManager;

public class TaskDialog extends JPanel {
   
    JLabel label;
    JFrame frame;
    DefaultListModel taskListModel;
    JList taskList;
    String addTaskString = "Add Task";
    String deleteTaskString = "Delete Task";
    String instructions = "<html><B>Add New Task:</B> Type a task in the textbox below and press the \"Add Task\" button. <P>" +
                          "<B>Delete Task:</B> Select a task and press the \"Delete Task\" button.<P><P></html>";
    JTextField taskName;
    JButton deleteTaskButton;
    JButton addTaskButton;
   
    static TaskManager tm;
   
    public TaskDialog(JFrame frame) {
        super(new BorderLayout());
        this.frame = frame;
       
        JPanel taskPanel = createTaskPanel();
        taskPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 5, 20));
       
        JPanel taskAddPanel = createTaskAddPanel();
        JPanel headerPanel = getHeaderPanel();
       
        // GUI Layout
       
        add(headerPanel, BorderLayout.NORTH);
        add(taskPanel, BorderLayout.CENTER);       
        add(taskAddPanel,BorderLayout.PAGE_END);
    }
    private JPanel getHeaderPanel() {
        JPanel headerPanel = new JPanel();
        headerPanel.setLayout(new BoxLayout(headerPanel, BoxLayout.Y_AXIS));
       
       
        JLabel instructionsLabel = new JLabel(instructions, JLabel.CENTER);
        Font font = new Font("Serif", Font.PLAIN, 24);
        instructionsLabel.setFont(font);
       
        label = new JLabel("<html><FONT COLOR=GREEN>Start adding Tasks...</FONT></html>", JLabel.CENTER);
       
        headerPanel.add(instructionsLabel);
        headerPanel.add(label);
       
        return headerPanel;
    }
   
    private JPanel createTaskPanel() {
        JPanel taskPanel = new JPanel();
        taskPanel.setLayout(new BoxLayout(taskPanel, BoxLayout.LINE_AXIS));
       
        taskListModel = new DefaultListModel();
       
        // create JList then add it to scroll pane
        taskList = new JList(taskListModel);
        taskList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        taskList.setSelectedIndex(0);
        taskList.setVisibleRowCount(50);
        JScrollPane taskListScrollPane = new JScrollPane(taskList);
       
        taskPanel.add(taskListScrollPane);
       
        return taskPanel;
    }
   
    private JPanel createTaskAddPanel() {
        JPanel taskAddPanel = new JPanel();
        taskAddPanel.setLayout(new BoxLayout(taskAddPanel, BoxLayout.LINE_AXIS));
       
        taskName = new JTextField(100);
       
        addTaskButton = new JButton(addTaskString);
        addTaskButton.setActionCommand(addTaskString);
        addTaskButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String task = taskName.getText();
                if(tm.addTask(task)) {
                    taskListModel.addElement(task);
                    taskName.setText("");
                    label.setText("<html><FONT COLOR=GREEN>\"" + task + "\"" + " has been added to your to do list.</FONT></html>");
                }
            }
        });     
       
        deleteTaskButton = new JButton(deleteTaskString);
        deleteTaskButton.setActionCommand(deleteTaskString);
        deleteTaskButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(taskList.getSelectedIndex() != -1) {
                    // ******  uncomment this line to handle multiple indicies  ******
                    //int [] arr = taskList.getSelectedIndices();
                    //for(int i=0; i< arr.length; i++) {
                    //    tm.removeTask(arr[i]);
                    //    taskListModel.removeElementAt(arr[i]);
                    //    label.setText("\"" + task + "\"" + " has been added to your to do list.");
                    //}
                    // ****** comment the following lines to handle single item selects  ********
                    int selectedIndex = taskList.getSelectedIndex();
                    String taskName = tm.removeTask(selectedIndex);
                    taskListModel.removeElementAt(selectedIndex);
                    label.setText("<html><FONT COLOR=RED>\"" + taskName + "\"" + " has been removed from your to do list.</FONT></html>");
                   
                }
            }
        });
              
        taskAddPanel.add(deleteTaskButton);
        taskAddPanel.add(Box.createHorizontalStrut(5));
       
        taskAddPanel.add(Box.createHorizontalStrut(5));
        taskAddPanel.add(taskName);
        taskAddPanel.add(addTaskButton);
        taskAddPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
       
        return taskAddPanel;
    }
   
    /**
     * Create the GUI and show it. For thread safety, this method should be
     * invoked from the event-dispatching thread.
     */
    private static void createAndShowGUI(TaskManager tm) {
 
        // Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);
        JDialog.setDefaultLookAndFeelDecorated(true);
 
        // Create and set up the window.
        JFrame frame = new JFrame("To Do List");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        // Set up the content pane.
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new GridLayout(1, 1));
        contentPane.add(new TaskDialog(frame));
        TaskDialog.tm = tm;
        // Display the window.
        frame.pack();
        frame.setVisible(true);
    }
 
    public static void runDialog(final TaskManager tm) {
        // 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(tm);
            }
        });
    }

}

Once again, we will need to edit the activator for this new project to make use of the GUI we created for our project. To do this, find the Activator.java class for our new project (cs.ecl.osgi.tasksystem.client) and add the following:

package cs.ecl.osgi.tasksystem.client;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import cs.ecl.osgi.taskmanager.TaskManager;

public class Activator implements BundleActivator {

    private static BundleContext context;
    private TaskManager tm;

    static BundleContext getContext() {
        return context;
    }

    /*
     * (non-Javadoc)
     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
     */
    public void start(BundleContext bundleContext) throws Exception {
        Activator.context = bundleContext;
       
        ServiceReference reference = context.getServiceReference(TaskManager.class.getName());
        if(reference != null) {
            tm = (TaskManager) context.getService(reference);
           
            if(tm != null) {
                // start GUI
                TaskDialog.runDialog(tm);
                context.ungetService(reference);
            } else {
                System.err.println("Task Manager could not be used!");
            }
        } else {
            System.err.println("The Task Manager System could not be found!");
        }
    }

    /*
     * (non-Javadoc)
     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
     */
    public void stop(BundleContext bundleContext) throws Exception {
        Activator.context = null;
    }

}

We are now finished. To run our application, right-click the MANIFEST.MF file and select the Run As... -> Run Configurations. Now make sure that all the required bundles in our workspace are selected and that the Validate bundles automatically prior to launching is checked.

Tasksystemclient 01.png

If everything was done correctly, you should be able to run the project and see our new application.


Tasksystemclient 02.png