Forum Controls
Spotlight Features

The Rich Engineering Heritage Behind Dependency Injection

Andrew McVeigh takes us on a tour of the rich heritage behind dependency injection, what it represents, and tells us why its here to stay.

Java, the OLPC, and community responsibility

The "One Laptop Per Child" project has a great device ready to ship, but there's no Java on there. Let's think about working together to put Java on OLPC!
Replies: 13 - Pages: 1  
Threads: [ Previous | Next ]
  Click to reply to this thread Reply

Getting started with Eclipse plug-ins: command-line applications

At 7:30 PM on Aug 6, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Eclipse is a modular architecture which is often associated with GUI applications, but in fact applications can be run in a headless environment from the command line as well. In this instalment, we'll look at the new IApplication and associated extension points to provide a runtime application mechanism.

In Eclipse 3.2, you could use IPlatformRunnable , but it's been replaced with IApplication in Eclipse 3.3. If you're still developing and supporting Eclipse 3.2, then you can take the concepts and use them against the older extension points and interface names; the principles are the same. The code assumes an Eclipse 3.3 runtime.

It's possible to write an OSGi application so that it can be started from the command line. The advantage of using an OSGi environment instead of a simple main method is that you get the full advantage of the modular bundle architecture, the ability to contribute extensions using either the Equinox extension registry or OSGi services, and all the benefits that a managed versioned system gives you. There's two ways of doing this; contribute an application extension which the OSGi environment can start, or have a main method that kicks off an OSGi environment via EclipseStarter. We'll just be looking at the IApplication variant here.

An eclipse application implements the IApplication extension point. An application can be started or stopped (like a bundle) and has access to a context for acquisition of arguments etc. A simple application looks like this:

import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
public class HelloWorld implements IApplication {
  public Object start(IApplicationContext context) throws Exception {
    System.out.println("Hello world!");
    return IApplication.EXIT_OK;
  }
  public void stop() {
  }
}


The bundle's manifest needs org.eclipse.core.runtime as a requirement; at run-time, it will also need the org.eclipse.equinox.app and org.eclipse.equinox.common bundles.

In order to run it, we need to select it as an application to run. We do this on the command line with the -application flag, or via PDE's 'Run an application' launch dialog:

Showing the run dialog

However, it won't show up in either of those places until there's an extension point for the application. This gives our application an ID (which we use from the command line) and associates it with the class:


<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
<extension
id="helloworld"
point="org.eclipse.core.runtime.applications">
<application>
<run
class="HelloWorld">
</run>
</application>
</extension>
</plugin>


This will allow us to run the application with -application org.example.helloworld from the command line; it will also display it in the pop-up menu for the launch application. If you run it, you should see Hello world! being printed.

Often, you'll want to be able to process arguments as part of the application. Instead of being passed a String[] directly, as you get from a Java main method, you have to obtain it from the IApplicationContext . Helpfully, it supplies a getArguments() call which you can use to find out what arguments have been passed. Unhelpfully, it doesn't actually give you the arguments; instead, you have to look up a random key application.args to obtain a String array which you can then process:

String[] args = (String[])context.getArguments().get("application.args")));


Thus, you can run and interact with your application like:

eclipse -application org.example.helloworld Hello World

Unfortunately, not all is well. If you run your application with the PDE bundles installed (which is more than likely, if you're developing bundles) then PDE automatically (and somewhat randomly) adds a -pdelaunch argument. This means that if you're developing an application, and you want to test it out with arguments (such as building an OSGi 'copy' or 'tar' type command) then you can't easily do this with PDE. It's even worse if you're building a command like 'tar', which uses - to signify command-line flags, one character at a time; the -pdelaunch would be interpreted as 'some permissions, diff, one file-system, update, norecurse, create, dereference'. Not very helpful. And there's no way you can get rid of it from the launch whilst the PDE plugins are installed in the runtime. You can voice your concern at bug 195454 , because at the moment, it doesn't look like it will be addressed as it's more important for PDE to work than for applications to work.

You can also start your application from the Equinox OSGi console. If you run the application with -console -noExit , you get an OSGi console prompt that you can use to start your application:

osgi> startApp org.example.helloworld
Launched application helloworld.0
Hello world!


Unfortunately, you have to chant magic incantations before you can do this. The first is that you need to tell Eclipse to register IApplication descriptors for each of the applications, which you do with:

-Declipse.application.registerDescriptors=true -Declipse.ignoreApp=false


For reasons only known to the Eclipse team, it actually ignores any application you pass in and doesn't register application descriptors by default. These issues just go out of their way to make writing applications difficult, and certainly not the kind of thing that is easy to debug. Without both of these, you can't start apps in the OSGi console.

Secondly, there's an interesting quirk in the way applications are hosted. If you don't specify an application with -application on the command line, then it runs the org.eclipse.equinox.app.error application, which does nothing.

However, when you run applications, you can either run them on the main thread or any thread. The command line runs on the main thread, and thus any other main apps can't run from the equinox console ; they just hang if tried. So you need to have applications that run under the any thread, which you do by modifying the plugin.xml :


<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
<extension
id="helloworld"
point="org.eclipse.core.runtime.applications">
<application thread="any">
<run
class="HelloWorld">
</run>
</application>
</extension>
</plugin>


This will allow you to start the application under the OGSi console. If you want to be able to run it more than once, then you can also add cardinality="*" to the application element; that can be useful if you want to host multiple servers via the OSGi console.

There's also a bug (which may be fixed and released for 3.3.1 ) in which an application under the any thread can't be started from the command line. This means that some systems provide two different applications , one which is started on the 'main' thread (and therefore can be used from the command line) and one on the 'any' thread (which can be run from the OSGi console).

The other OSGi commands that you can use include stopApp and apps , which allow you to see what other applications are installed and enable you to start and stop them.

Even though there's a few workarounds which need to be done to make the IApplication code work, it's the way that applications will be handled in the 3.3 timeframe and in the future, so it's worth learning about the issues and workarounds now to apply to your code.
  Click to reply to this thread Reply
1. At 7:31 PM on Aug 6, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

You can see previous posts in the 'getting started with Eclipse' series by chaining backwards from the previous post on contributing to Eclipse.

Alex.
  Click to reply to this thread Reply
2. At 7:45 PM on Aug 6, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

Here's the source project for the example, which can also be used as a runtime bundle using 'install file:///path/to/HelloWorld.jar'
  Click to reply to this thread Reply
3. At 8:24 PM on Aug 6, 2007, Chris Aniszczyk DeveloperZone Top 100 wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

omg Alex, I'm in the process of writing something similar to this.

Nice stuff. The more content the better I guess out there :)
  Click to reply to this thread Reply
4. At 4:09 AM on Aug 7, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

Yeah, but I bet you get more hits when yours goes live :-)

I'd been meaning to do it for a while, but unfortunately, took some time to get around to. Still, better late than never.

Alex
  Click to reply to this thread Reply
5. At 6:52 PM on Aug 7, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

Bug 198988 has some more information about random properties from the runtime options document:

eclipse.allowAppRelaunch if set to "true" then the main thread will continue to wait for another application descriptor to be launched after the currently running application has quit. Stopping the system.bundle (i.e. the bundle with a bundle ID equel to zero) will force the main thread to stop waiting for another application to launch. The default value is "false" eclipse.application.launchDefault Controls launching the default application automatically once the platform is running. A default application is identified by the eclipse.product or the eclipse.application options. The default value is "true". Setting this property to "false" will prevent the default application from launching automatically. Once the platform is running the main thread will wait for an application to be launched using an application descriptor service.

Should have RTFM, I guess :-)

Alex.
  Click to reply to this thread Reply
6. At 8:28 PM on Aug 15, 2007, H. Quan Javalobby Newcomers wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

Hi Alex,
Thanks for writing the series of articles. I'm a complete newbie to Eclipse, so it's good to have some references that start from the beginning. Problem is, though, that your examples are too simple for me to put to practical use, and I'm wondering if you can point readers to bigger, more practical examples at this point?
Specifically, my problem is this. I've been sent two Eclipse projects. One defines an extension point. The other project contains a skeleton plug-in for that extension (hope I'm using the correct terms) that's currently behaving like a Hello World program. I'm now trying modify the plug-in to instantiate an external class object- as a test. Through the plug-in project's property settings, I've managed to add the external jar so that the code compiles and the plug-in executes. But, during execution, it can't seem to instantiate that external class object. Going through the debugger, I can't step over the line containing the instantiation. So, I'm wondering what else I need to do so that my external jar is packaged properly with the plug-in, if that's even the problem?
Any help you could provide would be appreciated. Thanks in advance.

H.
  Click to reply to this thread Reply
7. At 8:41 PM on Aug 15, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

You've probably added the Jar as onto the Java Build Path, instead of in the Manifest.MF.

Why not create a plug-in from the existing Jar, and then use bundle dependencies? That's usually an easier way of doing it. There's even a new wizard that creates a plug-in from an existing Jar.

Alex.
  Click to reply to this thread Reply
8. At 10:17 AM on Aug 16, 2007, rashmy Blooming Javalobby Member wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

Hi Alex,
I am still on 3.2 and I tried to setup the command line application with IPlatformRunnable. Here is what I did

- Create eclipse.app( I have attached the source code )
- My class looks like this
----------------------
package eclipse.app.impl;
import org.eclipse.core.runtime.IPlatformRunnable;

public class HelloWorld implements IPlatformRunnable {
public Object run(Object args) throws Exception {
System.out.println("Hello world!");
return IPlatformRunnable.EXIT_OK;
}
}
----------------------
- Next I contributed to the extension point
id="helloworld"
point="org.eclipse.core.runtime.applications">





- I launched this as an application Run->Run..->Eclipse Application.

- In the "Arguments" tab I gave "-nosplash -application eclipse.app.helloworld".

- In the "Plug-ins" tab I selected ONLY the below list-
org.eclipse.core.contenttype_3.2.0.v20060603.jar
org.eclipse.core.jobs_3.2.0.v20060603.jar
org.eclipse.core.runtime_3.2.0.v20060603.jar
org.eclipse.equinox.common_3.2.0.v20060603.jar
org.eclipse.equinox.preferences_3.2.0.v20060601.jar
org.eclipse.equinox.registry_3.2.0.v20060601.jar
org.eclipse.osgi_3.2.0.v20060601.jar
org.eclipse.update.configurator_3.2.0.v20060605.jar
eclipse.app( the one that I created)

- When I ran the application with the above configuration things are fine. It prints the message correctly. ALL THIS WITHIN ECLIPSE workbench

I wanted to run it from command line. Hence I created a setup shown below-
somedir/
eclipse.exe
configuration/
config.ini
plugins/
org.eclipse.core.contenttype_3.2.0.v20060603.jar
org.eclipse.core.jobs_3.2.0.v20060603.jar
org.eclipse.core.runtime_3.2.0.v20060603.jar
org.eclipse.equinox.common_3.2.0.v20060603.jar
org.eclipse.equinox.launcher_1.0.0.v20070606.jar
org.eclipse.equinox.preferences_3.2.0.v20060601.jar
org.eclipse.equinox.registry_3.2.0.v20060601.jar
org.eclipse.osgi_3.2.0.v20060601.jar
org.eclipse.update.configurator_3.2.0.v20060605.jar
eclipse.app( the one that I created)
org.eclipse.equinox.launcher.win32.win32.x86_1.0.0.v20070523/
eclipse_1017a.dll

- From command line I gave the command "eclipse -nosplash -application eclipse.app.helloworld". But nothing happened.

Please NOTE - my config.ini contained
osgi.bundles=org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start
osgi.bundles.defaultStartLevel=4
osgi.framework=org.eclipse.osgi
osgi.configuration.cascaded=false

Can you point out if there is any issue with the setup?

Thanks,
Rashmy
  Click to reply to this thread Reply
9. At 10:54 AM on Aug 16, 2007, Alex Blewitt DeveloperZone Top 100 wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

Why do you have launcher 200705 in there? That's from Equinox 3.3. I doubt you'll find joy in that way. Use the 3.2 eclipse launcher/startup code.

Alex.
  Click to reply to this thread Reply
10. At 3:02 PM on Aug 16, 2007, H. Quan Javalobby Newcomers wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

Hey Alex,
Creating a plug-in from the existing Jar is probably the smarter way to go, and I'll keep that option in mind as I come up to speed on this stuff.
Meanwhile, with my current approach, your guess was essentially correct. I did add the external Jar onto the build path and expected the manifest to be taken care of for me. Plus, it must be the type of plug-in project that was sent to me, but I can't find a Manifest.MF file anywhere in that project's files. But when I right-mouse click on the plug-in project and the context menu pops-up, under PDE Tools -> Open Manifest, that opens up a view with a bunch of tabs, one of which is Runtime, with a section for Classpath: Specify the libraries that constitute the plug-in runtime. And it's there that I am able to add my external jar. Anyway, I'm going into detail here in case any other newbies can benefit from this info.
The main point is that I've gotten past this problem with your help. Thanks again, Alex. U Rock!

H.
  Click to reply to this thread Reply
11. At 8:27 PM on Aug 16, 2007, rashmy Blooming Javalobby Member wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

That was the problem. After changing the launcher it worked fine.

But I see that to I am dependent on the eclipse launcher that is platform specific. I also need this util that I am writing to run on HP-Itanium for which there is no launcher.

Basically I am writing a command line utility to validate a data model from XML on the server. This utility is like any other jar file. I was originally having a main() method that loaded the XML file and performs some validations on my data model.

But now there are other teams coming in wanting to contribute their own validations on the data model from the XML in addition to the basic validation I had. I do not want these other teams coming and changing my base Java code. Hence I thought I could use OSGI to discover these other validations contributed from the various teams as bundles. So all other teams implement this service interface in their respective bundle. Then my code could fetch these validators contributed by other teams.

I read the "Eclipse Quick start" on the Equinox website and got it working. But the OSGI services are not stopped once they are started. For example, after running the OSGI application if I try to rename the folder from where I ran the application I cannot do it. Hence I am guessing these services are still running. My requirement is to run them like any other java main method - do the job and exit. Could you suggest me if OSGI is the route to go?

Thanks!
  Click to reply to this thread Reply
12. At 10:03 AM on Jun 10, 2008, Kees Pieters Blooming Javalobby Member wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

Hi Alex,

good article, thanks!
I have followed your instructions to 'upgrade' an OSGI plugin to an application by refactoring the Activator to an Application. The only problem now is, that I am registering some OSGI services, so I still need the bundle context. Do you have any idea on how to achieve this?

Thanks

Kees
  Click to reply to this thread Reply
13. At 5:47 AM on Jun 11, 2008, Kees Pieters Blooming Javalobby Member wrote:

Re: Getting started with Eclipse plug-ins: command-line applications

I have made some progress on this one. I have made a product configuration to go with the application I just made. Then I can call getBrandingBundle() from the application context and use the bundlecontext provided there to register my services. That seems to work OK.

Thanks again

Kees

thread.rss_message