How to get the IEclipseContext in an activator
Asked Answered
S

3

7

I got stuck on one problem with an Eclipse 4 RCP application. I need to log some events. I need obtain somehow a reference to the logger. I know, how to do that using IEclipseContext, but I've nowhere found, how to obtain IEclipseContext without the dependency injection, which I cannot use in the activator. Do you anybody know, how to sort it out this problem, please?

Thanks a lot

Strontian answered 19/8, 2013 at 14:58 Comment(0)
S
4

It seems regretably, that there is no way to obtain IEclipseContext without using injection. There is written in an answer to How to use eclipse 4 DI in classes that are not attached to the application model:

The problem is, however, that the IEclipseContext already needs to be injected into a class that can access the object that needs injection.

Nevertheless I have already sorted out the problem of logging and I thing, the principle works generally. There is always some service providing things you need. If you cannot use the dependency injection, you've to get somehow (Internet and experiments are very often) an appropriate service class name. If you have got the service class name, then you can obtain an instance reference from the bundle context. Fortunately, the bundle context is accessible without using injection.

Back to our logging problem. The class being searched is org.osgi.service.log.LogService:

public class Activator implements BundleActivator {
    ...
    private static BundleContext context;
    ...

    public static BundleContext getContext() {
        return context;
    }
    ...
    public void start(BundleContext bundleContext) throws Exception {
        ServiceReference<?> logser = bundleContext.getServiceReference(LogService.class);
        LogService ls = (LogService)bundleContext.getService(logser);
        //print an error to test it (note, that info can be below the threshold)
        ls.log(LogService.LOG_ERROR, "The bundle is starting...");
        Activator.context = bundleContext;
    }
    ...
}

Et voilà!

!ENTRY eu.barbucha.rcp-experiment.kernel 4 0 2013-08-20 07:32:32.347
!MESSAGE The bundle is starting...

That's all. Later you can obtain the bundle context using Activator.getContext(), if it would be needed.

Important note: Regretably you cannot decrease the threshold now. The JVM argument -Declipse.log.level does not affect the OSGI log service and you're using just the OSGI logger now. Unfortunately they (may have provisionally) hardcoded the logging threshold (see How to log warnings and infos in eclipse 3.7). I found out, that they haven't repair it yet. Neither in the Kepler release. However you can make a compromise. You can do that injection-way, where possible.

Final solution (to catch exceptions globally as well)

I extended my activator:

ServiceReference<?> logreser = bundleContext.getServiceReference(LogReaderService.class);
LogReaderService lrs = (LogReaderService) bundleContext.getService(logreser);   
lrs.addLogListener(new LogListener() {
    @Override
    public void logged(LogEntry entry) {
        System.err.println("Something was logged: " + entry.getMessage());
    }
});

The text beginning with Something was logged really appears, whenewer is something somewhere logged. But the very advantage is, that this class is mine. I can control it. The log entry contains also the level. I can also easily set the threshold. For example on the command line.

Strontian answered 20/8, 2013 at 5:54 Comment(0)
O
6

You can get a specialized IEclipseContext by calling EclipseContextFactory.getServiceContext(bundleContext) which will allow access to OSGi services.

Outgrowth answered 20/8, 2013 at 11:17 Comment(4)
What does the specialized actually mean? I tried it, but there is no such instance of the org.eclipse.e4.core.services.Logger class int this specialized IEclipseContext, how mentioned on this wiki page. If I understand good, it can neither be. There is just the OSGI logger for these low-level things like activators and so on.Strontian
It is 'specialized' because it only contains OSGi services not other things normally found in the context. It does contain LogService and LogReaderServiceOutgrowth
Yeah, you're right. There are just the OSGI services, because the activator is matter of the OSGI-level.Strontian
If you need the e4 Logger in this context, you can try the following: eclipseContext.set(Logger.class, new WorkbenchLogger(Activator.PLUGIN_ID); Currently with "Discouraged access" warnings unfortunately.Leroy
S
4

It seems regretably, that there is no way to obtain IEclipseContext without using injection. There is written in an answer to How to use eclipse 4 DI in classes that are not attached to the application model:

The problem is, however, that the IEclipseContext already needs to be injected into a class that can access the object that needs injection.

Nevertheless I have already sorted out the problem of logging and I thing, the principle works generally. There is always some service providing things you need. If you cannot use the dependency injection, you've to get somehow (Internet and experiments are very often) an appropriate service class name. If you have got the service class name, then you can obtain an instance reference from the bundle context. Fortunately, the bundle context is accessible without using injection.

Back to our logging problem. The class being searched is org.osgi.service.log.LogService:

public class Activator implements BundleActivator {
    ...
    private static BundleContext context;
    ...

    public static BundleContext getContext() {
        return context;
    }
    ...
    public void start(BundleContext bundleContext) throws Exception {
        ServiceReference<?> logser = bundleContext.getServiceReference(LogService.class);
        LogService ls = (LogService)bundleContext.getService(logser);
        //print an error to test it (note, that info can be below the threshold)
        ls.log(LogService.LOG_ERROR, "The bundle is starting...");
        Activator.context = bundleContext;
    }
    ...
}

Et voilà!

!ENTRY eu.barbucha.rcp-experiment.kernel 4 0 2013-08-20 07:32:32.347
!MESSAGE The bundle is starting...

That's all. Later you can obtain the bundle context using Activator.getContext(), if it would be needed.

Important note: Regretably you cannot decrease the threshold now. The JVM argument -Declipse.log.level does not affect the OSGI log service and you're using just the OSGI logger now. Unfortunately they (may have provisionally) hardcoded the logging threshold (see How to log warnings and infos in eclipse 3.7). I found out, that they haven't repair it yet. Neither in the Kepler release. However you can make a compromise. You can do that injection-way, where possible.

Final solution (to catch exceptions globally as well)

I extended my activator:

ServiceReference<?> logreser = bundleContext.getServiceReference(LogReaderService.class);
LogReaderService lrs = (LogReaderService) bundleContext.getService(logreser);   
lrs.addLogListener(new LogListener() {
    @Override
    public void logged(LogEntry entry) {
        System.err.println("Something was logged: " + entry.getMessage());
    }
});

The text beginning with Something was logged really appears, whenewer is something somewhere logged. But the very advantage is, that this class is mine. I can control it. The log entry contains also the level. I can also easily set the threshold. For example on the command line.

Strontian answered 20/8, 2013 at 5:54 Comment(0)
S
2

It is possible to get the "WorkbenchContext" from the IWorkbench as a service:

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.ui.PlatformUI;

public final class EclipseContextHelper {

    public static IEclipseContext getActiveContext(){
        IEclipseContext context = getWorkbenchContext();
        return context == null ? null : context.getActiveLeaf();
    }

    public static IEclipseContext getWorkbenchContext(){
        return PlatformUI.getWorkbench().getService(IEclipseContext.class);
    }
}
Shel answered 20/10, 2015 at 7:39 Comment(1)
PlatformUI.getWorkbench() is RCP 3 API.Kirov

© 2022 - 2024 — McMap. All rights reserved.