Wednesday, September 3, 2008

Tutorial: Sample RCP application using Spring, Spring Dynamic Modules for OSGi Service Platforms and AgileRCP (3/3)

In the first two parts of the tutorial you have learned how to use Spring beans as OSGi services (see part 1 and part 2). You have used the ApplicationContextTracker of AgileRCP to access Spring's ApplicationContext. The third part of the tutorial will show you how to use Eclipse RCP Extensions in interaction with Spring beans. AgileRCP offers a convenient way to do this without the hassle of the direct use of the ApplicationContextTracker.
  1. Create a new interface for a user view:
    • New -> Interface
    • Name: IUserView
    • Extended Interfaces: org.agilercp.ui.IView, org.agilercp.ui.view.IWorkbenchPartView

  2. Add a method for setting a list of user names:
        void setUserNames(final List<String> names);
  3. The interface is not compile clean, because some packages are missing. Add the following packages to the list of imported packages (MANIFEST.MF, Dependencies tab):
    • org.agilercp.ui
    • org.agilercp.ui.dialog
    • org.agilercp.ui.view
    • org.agilercp.ui.workbench
    • org.agilercp.util.log

  4. Edit the view of the application (View.java):
    • The view extends DefaultViewParta (from AgileRCP) instead of ViewPart.
    • The view implements the interface IUserView.
    • The table viewer displays a list of user names.
    • This list will be set from outside.
    public class View extends DefaultViewPart implements IUserView {
    public static final String ID = "org.digitalcure.hellospring.app.view";

    private TableViewer tableViewer;

    @Override
    protected void doCreatePartControl(final Composite parent) {
    final Composite composite = new Composite(parent, SWT.NONE);
    composite.setLayout((new GridLayout(1, false)));
    composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    tableViewer = new TableViewer(composite, SWT.FULL_SELECTION | SWT.BORDER);
    tableViewer.getTable().setHeaderVisible(true);
    tableViewer.getTable().setLinesVisible(true);
    tableViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    final TableColumn firstNameColumn = new TableColumn(tableViewer.getTable(), SWT.NONE);
    firstNameColumn.setText("Name");
    firstNameColumn.setWidth(100);

    tableViewer.setContentProvider(new ArrayContentProvider());
    tableViewer.setLabelProvider(new UserTableLabelProvider());
    }

    @Override
    public void setFocus() {
    tableViewer.getTable().setFocus();
    }

    public void setUserNames(final List<String> names) {
    tableViewer.setInput(names);
    }

    private class UserTableLabelProvider extends LabelProvider implements ITableLabelProvider {
    public Image getColumnImage(final Object element, final int columnIndex) {
    return null;
    }

    public String getColumnText(final Object element, final int columnIndex) {
    if (!(element instanceof String)) {
    throw new IllegalArgumentException("The given object must be a string!");
    }

    return (String) element;
    }
    }
    }
  5. Edit the plugin.xml file:
    • Go to the Extensions tab, expand the node "org.eclipse.ui.views" and select "View (view)".
    • Change the class to: org.agilercp.ui.workbench.WorkbenchPartFactory

  6. The WorkbenchPartFactory implementation will create an instance of a Spring bean with the ID of the view (org.digitalcure.hellospring.app.view). The Spring bean has to implement the interface org.agilercp.ui.IPresenter. So now you have to create a new class for the presenter:
    • New -> Class
    • Name: UserPresenter
    • Superclass: org.agilercp.ui.DefaultPresenter

  7. You have to specify the type of the presented view:
    public class UserPresenter extends DefaultPresenter<IUserView> { ... }
  8. Add a member for the user manager to the user presenter class and a constructor that provides both the user manager and the user view:
        private final IUserManager userManager;

    public UserPresenter(final IUserView view, final IUserManager userManager) {
    super(view);
    this.userManager = userManager;
    }
  9. Override the handleViewCreated(...) method and initialize the view with the list of user names:
        @Override
    protected void handleViewCreated(final IUserView view) {
    super.handleViewCreated(view);
    getView().setUserNames(userManager.getUserNames());
    }
  10. Edit the Spring configuration file bundle-context.xml and add a Spring bean for the user presenter:
        <bean name="org.digitalcure.hellospring.app.view" class="org.digitalcure.hellospring.app.UserPresenter">
    <constructor-arg>
    <bean class="org.digitalcure.hellospring.app.View" />
    </constructor-arg>
    <constructor-arg ref="userManagerService" />
    </bean>
  11. The source code modifications are finished, so you have to modify the product configuration file "HelloSpringApp.product". Go to the Configuration tab and press "Add Required Plug-ins".

  12. Open the Run Configuration and press "Add Required Bundles".

  13. Press "Run" to run the application. The list inside the application window should display the user names now.
You may download the source code of the tutorial from here.

Monday, September 1, 2008

Tutorial: Sample RCP application using Spring, Spring Dynamic Modules for OSGi Service Platforms and AgileRCP (2/3)

In this tutorial you will extend the sample application of the first tutorial part. You will add another plug-in that provides a new user manager. You will learn how to declare Spring beans as OSGi services and use them in other plug-ins. This is possible without any modification of the original source code.
  1. Create a new plug-in project for the user manager service:
    • New -> Other... -> Plug-in Development / Plug-in Project
    • Choose a proper project name, e.g. "org.digitalcure.hellospring.service"
    • Generate an activator: yes, This plug-in will make contributions to the UI: no, Would you like to create a rich client application? no
    • Create a plug-in using one of the templates: no

  2. Edit the MANIFEST.MF file and import the package "org.digitalcure.hellospring.common" (Dependencies tab).

  3. Create an implementation of a user manager. Create a new class inside the "org.digitalcure.hellospring.service" package:
    • New -> Class
    • Choose a class name: ExtendedUserManager
    • Interfaces: org.digitalcure.hellospring.common.IUserManager

  4. Implement the getUserNames() method, so that it returns three names, e.g.:
    public List<String> getUserNames() {
    final List<String> list = new ArrayList<String>(3);
    list.add("Charly");
    list.add("Dennis");
    list.add("Ed");
    return list;
    }
  5. Now you are ready to create the Spring configuration files. Create a folder named "spring" inside the META-INF folder.

  6. Create two XML files inside the "spring" folder:
    • bundle-context.xml
    • bundle-context-osgi.xml

  7. bundle-context.xml: Create a Spring bean for the user manager:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="extendedUserManager" class="org.digitalcure.hellospring.service.ExtendedUserManager" />
    </beans>
  8. bundle-context-osgi.xml: Export the user manager bean as OSGi service:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans
    xmlns="http://www.springframework.org/schema/osgi"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/osgi
    http://www.springframework.org/schema/osgi/spring-osgi.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <service id="extendedUserManagerService" ref="extendedUserManager"
    interface="org.digitalcure.hellospring.common.IUserManager" />
    </beans:beans>
  9. Add Spring support to the "service" project: Open the context menu for the project and select "Spring Tools" -> "Add Spring Project Nature". The project itself will be marked with a "S" in the upper right corner of the project icon.

  10. Open the Properties dialog of the project. Go to "Spring" -> "Beans Support" and add the two XML files of the "spring" folder. After closing the dialog, both XML files will be marked with an "S", plus the Java file "ExtendedUserManager.java".

  11. Switch back to the first project (the "app" project). Now you have to configure the first user manager (default user manager) as service. You have to edit the Spring configuration files of the project.

  12. bundle-context-osgi.xml: Export the user manager bean as OSGi service:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans
    xmlns="http://www.springframework.org/schema/osgi"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/osgi
    http://www.springframework.org/schema/osgi/spring-osgi.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <service id="defaultUserManagerService" ref="defaultUserManager"
    interface="org.digitalcure.hellospring.common.IUserManager" />
    </beans:beans>
  13. bundle-context.xml: Import an user manager service:
    <osgi:reference id="userManagerService" interface="org.digitalcure.hellospring.common.IUserManager" />
  14. bundle-context.xml: Use the user manager service for the action:
    <bean id="listUserAction" class="org.digitalcure.hellospring.app.ListUserAction" >
    <property name="userManager" ref="userManagerService" />
    </bean>
  15. Edit the product configuration file "HelloSpringApp.product" and add the "service" plug-in to the list of plug-ins (Configuration tab).

  16. Edit the Run Configuration. Add the "service" plug-in to the list of plug-ins.

  17. Run the application. Take care of the logger messages in the Console view. When the application frame appears, select the menu item "File" -> "List Users". You should see a list of user names in the Console view.

  18. Please note that the user managers of both plug-ins ("app" and "service") are available as OSGi services. You may control the ranking of the services by adding the "ranking" attribute to the service definition.

  19. "app" plug-in, bundle-context-osgi.xml:
    <service id="defaultUserManagerService" ref="defaultUserManager"
    interface="org.digitalcure.hellospring.common.IUserManager" ranking="5" />
  20. "service" plug-in, bundle-context-osgi.xml:
    <service id="extendedUserManagerService" ref="extendedUserManager"
    interface="org.digitalcure.hellospring.common.IUserManager" ranking="7" />
  21. Run the application once again and see what names are printed. You may now modify the ranking of the user manager service of the "service" plug-in to 3 and run the application again. You should see other names printed in the Console view.
You may download the source code of the tutorial from here.