Technical Blog

2 Posts authored by: Ivan Jensen

As you may know, Eclipse RCP (which the CM Client is implemented on) is itself built upon the OSGI and runs in the Equinox OSGI container. That means there's the full power of the OSGI framework at your disposal.

 

One of the interesting features that Equinox provides is a console that allows you to poke around at the insides of a running OSGI application.

 

To see the console simply add the command line flag -console when launching an Eclipse application. The following is an example of accessing the console running Eclipse itself on my Mac, but you could do exactly the same when running the Commerce Manager.exe on Windows.

 

 

ep-wl-0594:eclipse35 ivanjensen$ ./eclipse/Eclipse.app/Contents/MacOS/eclipse -console

 

osgi>

 

 

You can see the osgi> prompt just there. There's lots of options in there that can be very useful in debugging issues. You can see all the available options by simply typing help at the osgi prompt:

 

 

osgi> help

---Controlling the OSGi framework---

        launch - start the OSGi Framework

        shutdown - shutdown the OSGi Framework

        close - shutdown and exit

        exit - exit immediately (System.exit)

        init - uninstall all bundles

        setprop <key>=<value> - set the OSGi property

---Controlling Bundles---

        install - install and optionally start bundle from the given URL

        uninstall - uninstall the specified bundle(s)

        start - start the specified bundle(s)

        stop - stop the specified bundle(s)

        refresh - refresh the packages of the specified bundles

        update - update the specified bundle(s)

---Displaying Status---

        status [-s [<comma separated list of bundle states>]  [<segment of bsn>]] - display installed bundles and registered services

        ss [-s [<comma separated list of bundle states>]  [<segment of bsn>]] - display installed bundles (short status)

        services [filter] - display registered service details

        packages [<pkgname>|<id>|<location>] - display imported/exported package details

        bundles [-s [<comma separated list of bundle states>]  [<segment of bsn>]] - display details for all installed bundles

        bundle (<id>|<location>) - display details for the specified bundle(s)

        headers (<id>|<location>) - print bundle headers

        log (<id>|<location>) - display log entries

---Extras---

        exec <command> - execute a command in a separate process and wait

        fork <command> - execute a command in a separate process

        gc - perform a garbage collection

        getprop  [ name ] - displays the system properties with the given name, or all of them.

 

...output abbreviated...

 

osgi>

 

 

The command I use most frequently to get a general overview of which bundles are available and their status is ss:

 

 

osgi> ss     

 

Framework is launched.

 

id      State       Bundle

0       ACTIVE      org.eclipse.osgi_3.5.0.v20090520

1       ACTIVE      org.eclipse.equinox.simpleconfigurator_1.0.100.v20090520-1905

2       <<LAZY>>    com.ibm.icu_4.0.1.v20090415

3       RESOLVED    com.jcraft.jsch_0.1.41.v200903070017

4       <<LAZY>>    com.sun.jna_3.1.0

5       RESOLVED    java_cup.runtime_0.10.0.v200803061811

6       RESOLVED    javax.activation_1.1.0.v200905021805

7       RESOLVED    javax.mail_1.4.0.v200905040518

8       RESOLVED    javax.servlet_2.5.0.v200806031605

9       RESOLVED    javax.servlet.jsp_2.0.0.v200806031607

 

...output abbreviated...

 

osgi>

 

 

Here you can see some of the bundles that run in my installation of eclipse. Each bundle is given a unique number that can be used with some of the other console commands. You can also see the bundle's state and the bundle's symbolic name. For more information on the bundle states check out this Wikipedia article.

 

There's plenty more good stuff down in the console, including being able to start, stop and update bundles in a running system.

 

So why not take some time and get to know your OSGI console and add another string to your RCP bow?

0 Comments Permalink

This post walks through adding filtering to the System Configuration page in the CM Client helping you track down a setting as quickly as possible.

 

We added the Settings Framework in Elastic Path Commerce 6.1 and it's proved incredibly useful in centralizing configuration and easing customization versus the previous XML based approach.  The number of settings out-of-the-box continues to grow plus any additional ones that customers are free to add.  So this tip will show you how to reign in that growing number of settings.

 

Here's a screenshot of what we'll be producing, if you've spent any time in the System Configuration (like our trusty QA guys) this will be a real time saver.

 

settings-filter.png

 

Changing the layout

I had to refresh my SWT widget layout knowledge a little and found this great page: http://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html.  With that excellent refresher I decided I would need a three column GridLayout: a column each for the Edit button, filter label and the filter text widget.  The table would then span all three columns.

 

settings-filter-layout.png

First, simply change the number of columns on the SettingDefinitionComposite:

 

private void setupLayout() {
     final int columns = 3;
     this.setLayout(new GridLayout(columns, false));
}

 

Then add in a horizontal span to the table's LayoutData - this makes it span the three columns we just created.

final int horizontalSpan = 3;
table.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, horizontalSpan, 1));

Note: the final variables are to keep Checkstyle quiet about magic numbers.

 

Adding the new widgets

The code below adds the label and the filter Text widget.  Take a close look at the style we are using to create the Text widget with: SWT.SEARCH | SWT.CANCEL.  The SWT.SEARCH style gives us the rounded edges (at least on my Mac) which makes it look like a regular search/filter widget.  The SWT.CANCEL style adds the small cross to the widget.  When clicked it removes the currently entered text.

Label label = formToolkit.createLabel(this, AdminConfigurationMessages.filterLabel + ":"); //$NON-NLS-1$
GridData gridData = new GridData(SWT.END, SWT.CENTER, false, false);
label.setLayoutData(gridData);
Text settingNameFilter = formToolkit.createText(this, "", SWT.SEARCH | SWT.CANCEL); //$NON-NLS-1$
gridData = new GridData(SWT.FILL, SWT.CENTER, false, false);
final int verticalIndent = 10;
gridData.verticalIndent = verticalIndent;
settingNameFilter.setLayoutData(gridData);

 

We want this new addition to be localizable so we need to add AdminConfigurationMessages.filterLabel

public static String filterLabel;

 

And then we provide the English version of that in AdminConfigurationPluginResources.properties

 

filterLabel=Filter

 

Filtering

Now we'll take a look at how we will actually filter down the table's contents.  The code's pretty simple:

/**
 * Filter setting definitions against a specified string.
 */
private class SettingPathFilter extends ViewerFilter {
     private final String filterText;
     public SettingPathFilter(final String filterText) {
          this.filterText = filterText;
     }
     @Override
     public boolean select(final Viewer viewer, final Object parent, final Object element) {
          SettingDefinition definition = (SettingDefinition) element;
          return StringUtils.containsIgnoreCase(definition.getPath(), filterText);
     }
}

We've simply extended the JFace ViewerFilter class and implemented the select method with a case-insensitive check against the setting definition's path.  In the next step we'll create an instance of this class and pass it to the TableViewer that holds the setting definitions.

 

The following page helped me a bit with the ViewerFilter: http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/DemonstratesListViewer.htm

 

Hooking it together

The bits are all in place, let's tie them together and get the filtering going when a user types in the text box.  We simply add a ModifyListener to the filter Text widget and when we receive a ModifyEvent we grab the user-entered string, create a new SettingPathFilter and set that on the tableViewer.  That triggers the tableViewer to filter its contents.  Note: I chose to use setFilters, rather than addFilter/removeFilter, to keep the code simple: I don't have to keep track of the filter to remove it afterwards I simply call setFilters again.

 

settingNameFilter.addModifyListener(new ModifyListener() {
     public void modifyText(final ModifyEvent event) {
          final Text source = (Text) event.getSource();
          String filterText = source.getText();
          if (StringUtils.isBlank(filterText)) {
               tableViewer.setFilters(new ViewerFilter [0]);
          } else {
               tableViewer.setFilters(new ViewerFilter [] {new SettingPathFilter(filterText)});
               }
     }
});

 

 

Conclusion

So there you have it, all done, with a few small changes we can find settings without having to visually scan the table.  Where else might this filtering function be useful?  Anyone done any similar customizations they would like to share?

 

The code

The code changes and the attached patch are against the upcoming 6.2 release, but I'm pretty sure they will apply to any 6.1+ version.  Leave a comment if you have any problems applying this and I'll do my best to help you out.

References

http://www.eclipse.org/swt/snippets/ - if you've not taken a look at the SWT snippets then you're missing out.  There's a ton of useful examples of using SWT.

http://wiki.eclipse.org/index.php/JFaceSnippets - just like the SWT snippets, this page contains great snippets about using the JFace ui toolkit.

2 Comments Permalink