Skip to Content
Technical Articles
Author's profile photo Matthew Billingham

A simple Eclipse Plugin to Call a FM when an editor is opened

Introduction

Bärbel Winkler asked a question about how to trigger some kind of popup in ADT/Eclipse using information held on the backend application server.

I realise one solution would be to have some code run every time an (ABAP) editor was opened in Eclipse. This code would call a function module on the backend, which could take some information and return a message in a popup in Eclipse.

This seemed like a fun little project; this is how I did it.

Getting started

For plugin development on Eclipse, you need the PDE (Plugin Development Environment). You can get it here. I installed it in a new folder, and then installed ADT on top. This is needed so that we can easily access the backend.

Creating the project

The first step is to create a plugin project. I called it popup. When you create a project you’re offered a list of templates, but I didn’t want any of those. Plugins work on Extension Points built into the Eclipse software. The Extension Point I needed is org.eclipse.ui.startup. This allows me to put my own program to run when eclipse starts up.

To get that I first needed to add the dependency org.eclipse.ui, which contains the required Extension Point.

Dependencies%20Tab

Dependencies Tab

The following dependencies are needed later in the Java classes, so must also be added.

  • com.sap.adt.project
  • org.eclipse.core.runtime
  • org.eclipse.core.resources
  • com.sap.conn.jco

When I added the Extension Point, a default startup element was created. It has one property – that name of the class that’s to be used for the extension.

Extensions%20Tab

Extensions Tab

All I need to do now is create the class and implement my code!

Implementing the classes

The first class is RegisterListenerAtStartup.

package com.xiting.popup;

import org.eclipse.swt.widgets.Display;

public class RegisterListenerAtStartUp implements org.eclipse.ui.IStartup {

	@Override
	public void earlyStartup() {
		Display.getDefault().asyncExec(new ListenerForPopup());
	}

}

The idea is to register a class which implements IPartListener2. In Eclipse, a part is a View or an Editor. Registering the class means that the Eclipse framework will trigger my method when an event happens on a Part – specifically, I want it to trigger when a part is opened.

In order to do this, I need an object called the active workbench window. Unfortunately, at the startup, this object is not yet initialised – it is null.

The way to get round this is to use a little trick, so that when the display is ready, the listener registration code is run. I called that class ListenerForPopup

package com.xiting.popup;

import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

public class ListenerForPopup implements Runnable, IPartListener2 {
	private static final String ADT_PREFIX = "com.sap.adt";

	@Override
	public void partOpened(IWorkbenchPartReference partRef) {
		if (!(partRef.getPart(true) instanceof IProjectProvider))
			return;
		String id = partRef.getId();
		if (id.startsWith(ADT_PREFIX)) {
			JCoDestination destination;
			try {
				destination = getDestination(partRef.getPart(true));
				String objectName = partRef.getPart(true).getTitle().substring(5); //Trim off sy-sysid
				new FunctionModuleCaller().run(objectName, destination);
			} catch (JCoException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@Override
	public void run() {
		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		IPartService partService = window.getPartService();
		IPartListener2 listener = new ListenerForPopup();
		partService.addPartListener(listener);
	}

	private JCoDestination getDestination(IWorkbenchPart part) throws JCoException {
		IProjectProvider projectProvider = (IProjectProvider) part;
		IProject project = projectProvider.getProject();
		String destinationId = AdtCoreProjectServiceFactory.createCoreProjectService().getDestinationId(project);
		return JCoDestinationManager.getDestination(destinationId);
	}
}

Now, you’ll see it implement Runnable (which has one method, the method run) and that’s what asyncExec takes as a parameter in RegisterListenerAtStartup

In a more complex development, I’d probably have implemented Runnable in one class and IPartListener2 in another – but this is simple so I’ve put them together.

I’ve only overridden one method of IPartListener2, the one whichs runs when a part is opened. It checks that the id of the part begins with com.sap.adt – which all the ABAP editor types do – and that it is an IProjectProvider – this is needed to determine the destination of the backend. Then we launch the function module with the name of the object – which will of the form <SYSID> Object name. So, for example: [D01] ZMATT

The Function Module

On the backend, I created this RFC enabled function module.

FUNCTION z_matt_test1.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(I_OBJECT) TYPE  PROGNAME
*"  EXPORTING
*"     VALUE(E_MESSAGE) TYPE  BAPI_MSG
*"----------------------------------------------------------------------

  e_message = `This was triggered by opening object` && i_object.

ENDFUNCTION.

Quite simple. It constructs a message based on whatever I_OBJECT contains.

I then wrote the Java class, FunctionModuleCaller using standard JCo techniques.

package com.xiting.popup;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;

import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoFunction;

public class FunctionModuleCaller {
	private static final String FM = "Z_MATT_TEST1";

	public void run(String objectName, JCoDestination destination) throws JCoException {
		JCoFunction function = destination.getRepository().getFunction(FM);
		function.getImportParameterList().setValue("I_OBJECT", objectName);
		function.execute(destination);
		String message = function.getExportParameterList().getString("E_MESSAGE");
		if (!(message.isBlank()))
			MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "", message);
	}
}

Results

And that’s it. As intended, when I open up an ABAP editor in Eclipse, I get the following result.

Results

Of course, you can write your FM to do whatever you like!

The GIT repository is here: https://github.com/matthewdjb/JustAPopup, with all the source code, the feature project and the update site project that you’ll need to be able to deploy your own version – suitable adjusted of course!

If you just want to use the code “as is”, you can download com.xiting.popup.install.zip from the repository directly. Unzip it to a folder, and then point Eclipse to that as a local update site.

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.