Application Development and Automation Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
matt
Active Contributor
2,203

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 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 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.


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.
Labels in this area